How to Run Yii2 with Swoole HTTP Server for Realtime Asynchronous Task Processing
Add to BookmarkIn this tutorial, you'll learn how to implement real-time asynchronous task processing in a Yii2 application using PHP Swoole as a microservice. This architecture lets you offload time-consuming tasks (like sending emails or generating reports) to a separate process, without waiting for them to complete in your web request.
This is not about running Yii2 on Swoole. Instead, we embed a Swoole HTTP server alongside our Yii2 project, acting as a background worker that receives and processes tasks sent from Yii2 controllers.
Benefits of This Architecture
- No more waiting for long tasks to complete during user requests.
- Real-time background processing without relying on
cron
. - Event-driven and fast thanks to Swoole.
- Clean and extendable codebase using handlers and task routing.
Project Structure
yii2-app/
├── swoole/
│ ├── runserver.php
│ ├── TaskHandlerInterface.php
│ ├── TaskRouter.php
│ ├── task-log.txt
│ └── handlers/
│ ├── SendEmailTask.php
│ └── GenerateReportTask.php
├── controllers/
│ └── SiteController.php
├── web/
│ └── index.php
...
Step 1: Setup the Swoole HTTP Server
File: swoole/runserver.php
<?php
declare(strict_types=1);
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';
$config = require __DIR__ . '/../config/console.php';
$application = new yii\console\Application($config);
$server = new \Swoole\Http\Server("127.0.0.1", 9501);
$server->on("start", function (\Swoole\Http\Server $server) {
echo "Swoole task server started at http://127.0.0.1:9501\n";
});
$server->on("request", function (\Swoole\Http\Request $request, \Swoole\Http\Response $response) {
$data = json_decode($request->rawContent(), true);
if (!$data || !isset($data['task'])) {
$response->status(400);
$response->end(json_encode(['error' => 'No task']));
return;
}
// Immediately respond before processing
$response->end(json_encode(['status' => 'Task queued']));
// Run task in coroutine asynchronously
go(function () use ($data) {
$payload = $data['payload'] ?? [];
\app\swoole\TaskRouter::dispatch($data['task'], $payload);
});
});
$server->start();
Step 2: Task Routing and Interface
File: swoole/TaskHandlerInterface.php
<?php
namespace app\swoole;
interface TaskHandlerInterface
{
public function handle(array $payload): void;
}
File: swoole/TaskRouter.php
<?php
namespace app\swoole;
class TaskRouter
{
public static function dispatch(string $taskName, array $payload): bool
{
$class = '\\app\\swoole\\handlers\\' . ucfirst($taskName) . 'Task';
file_put_contents(__DIR__ . '/task-log.txt', "Trying to dispatch: $class\n", FILE_APPEND);
if (!class_exists($class)) {
file_put_contents(__DIR__ . '/task-log.txt', "Class not found: $class\n", FILE_APPEND);
return false;
}
$handler = new $class();
if (!$handler instanceof TaskHandlerInterface) {
file_put_contents(__DIR__ . '/task-log.txt', "Handler does not implement TaskHandlerInterface: $class\n", FILE_APPEND);
return false;
}
$handler->handle($payload);
return true;
}
}
Step 3: Define Task Handlers
File: swoole/handlers/SendEmailTask.php
<?php
namespace app\swoole\handlers;
use app\swoole\TaskHandlerInterface;
class SendEmailTask implements TaskHandlerInterface
{
public function handle(array $payload): void
{
// Simulate sending an email
$to = $payload['to'] ?? 'unknown';
$subject = $payload['subject'] ?? '(no subject)';
$users = json_encode([]);
$i = 1;
while ($i <= 100) {
\Swoole\Coroutine::sleep(1);
$i++;
file_put_contents(__DIR__ . '/../task-log.txt', "$i\n", FILE_APPEND);
}
file_put_contents(__DIR__ . '/../task-log.txt', "Email Send , [EMAIL] To: $to, Subject: $subject and total users id $users\n", FILE_APPEND);
}
}
File: swoole/handlers/GenerateReportTask.php
<?php
namespace app\swoole\handlers;
use app\swoole\TaskHandlerInterface;
class GenerateReportTask implements TaskHandlerInterface
{
public function handle(array $payload): void
{
// Generate Report
file_put_contents(__DIR__ . '/../task-log.txt', "Report Generated for : " . json_encode($payload) . "\n", FILE_APPEND);
}
}
Step 4: Send Tasks from Yii2
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
class SiteController extends Controller
{
public function actionCheck()
{
$client = new \yii\httpclient\Client([
'baseUrl' => 'http://127.0.0.1:9501',
]);
$response = $client->createRequest()
->setMethod('POST')
->setUrl('/')
->setFormat(\yii\httpclient\Client::FORMAT_JSON)
->setData([
'task' => 'SendEmail',
'payload' => [
'to' => 'user@example.com',
'subject' => 'Welcome from Yii2',
],
])
->send();
if ($response->isOk) {
echo 'Task sent successfully: ' . $response->content;
}
$response = $client->createRequest()
->setMethod('POST')
->setUrl('/')
->setFormat(\yii\httpclient\Client::FORMAT_JSON)
->setData([
'task' => 'GenerateReport',
'payload' => [
'report_date' => date('Y-m-d'),
'report_title' => 'UP State Report',
],
])
->send();
if ($response->isOk) {
echo 'Task sent successfully: ' . $response->content;
exit;
}
return 'Error: ' . $response->statusCode;
}
}
Step 5: Run the Swoole Server
Run the following in a separate terminal:
php swoole/runserver.php
You’re Done!
Now when you visit http://localhost:8080/site/check
, Yii2 sends two background tasks to the Swoole server. Swoole handles them immediately, logs the results, and your controller returns without delay.
You’ve just upgraded your Yii2 app to support real-time microservice task delegation with PHP Swoole — no cron jobs, no blocking.
- You can add more task types by creating new classes in
handlers/
. - Consider moving to Redis or queues later for larger scale.
- Use this architecture to process webhooks, notifications, or database syncs instantly.
Prepare for Interview
- SQL Interview Questions for 5+ Years Experience
- SQL Interview Questions for 2–5 Years Experience
- SQL Interview Questions for 1–2 Years Experience
- SQL Interview Questions for 0–1 Year Experience
- SQL Interview Questions for Freshers
- Design Patterns in Python
- Dynamic Programming and Recursion in Python
- Trees and Graphs in Python
- Linked Lists, Stacks, and Queues in Python
- Sorting and Searching in Python
- Debugging in Python
- Unit Testing in Python
- Asynchronous Programming in PYthon
- Multithreading and Multiprocessing in Python
- Context Managers in Python
Random Blogs
- Downlaod Youtube Video in Any Format Using Python Pytube Library
- Variable Assignment in Python
- Datasets for Natural Language Processing
- AI in Marketing & Advertising: The Future of AI-Driven Strategies
- String Operations in Python
- The Ultimate Guide to Data Science: Everything You Need to Know
- 15 Amazing Keyword Research Tools You Should Explore
- How AI Companies Are Making Humans Fools and Exploiting Their Data
- Python Challenging Programming Exercises Part 2
- What Is SEO and Why Is It Important?
- Robotics & AI – How AI is Powering Modern Robotics
- Role of Digital Marketing Services to Uplift Online business of Company and Beat Its Competitors
- 5 Ways Use Jupyter Notebook Online Free of Cost
- Government Datasets from 50 Countries for Machine Learning Training
- Important Mistakes to Avoid While Advertising on Facebook
Datasets for Machine Learning
- Amazon Product Reviews Dataset
- Ozone Level Detection Dataset
- Bank Transaction Fraud Detection
- YouTube Trending Video Dataset (updated daily)
- Covid-19 Case Surveillance Public Use Dataset
- US Election 2020
- Forest Fires Dataset
- Mobile Robots Dataset
- Safety Helmet Detection
- All Space Missions from 1957
- OSIC Pulmonary Fibrosis Progression Dataset
- Wine Quality Dataset
- Google Audio Dataset
- Iris flower dataset
- Artificial Characters Dataset