Demonstrate how async enables
executeSomeAsyncProcess(
$withData,
$andA,
$callbackToExecuteOnCompletion
);
function ($error, $result)
{
if ($error) {
}
}
$dispatcher->addListener(function (SomeEvent $e) {
// do work
});
// later:
$dispatcher->trigger($someEvent);
doFirst($payload, function ($err, $result) {
doSecond($result, function ($err, $result) {
doThird($result, function ($err, $result) {
// finally got what we needed
});
});
});
$promise = someAsyncOperationReturningAPromise($with, $data);
$promise
->then($someCallbackToExecuteOnResolution)
->then($someAdditionalCallbackToExecuteOnResolutionOfPrevious)
->catch($someCallbackToExecuteOnRejection);
where:
function then($successCallback = null, $rejectionCallback = null);
and catch() is a shortcut for:
$promise->then(null, $someCallbackToExecuteOnRejection);
async function ping() {
const res = await fetch('/api/ping');
return await res.json();
}
let ack = ping();
$result = $statement->execute($data);
use Swoole\Http\Server as HttpServer;
$server = new HttpServer('127.0.0.1', 9000);
$server->on('start', function ($server) {
echo "Server started at http://127.0.0.1:9000\n";
});
$server->on('request', function ($request, $response) {
$response->header('Content-Type', 'text/plain');
$response->end("Hello World\n");
});
$server->start();
If you forget to call it:
$server->defer(function () {
// work to defer
});
$server->set(['task_worker_num' => 4]);
$server->on('task', function ($server, $taskId, $data) {
// Handle task
// Finish task:
$server->finish('');
});
$server->on('finish', function ($server, $taskId, $returnValue) {
// Task is complete
});
$server->task($someData);
class Task {
public $handler; // callable
public $arguments; // array
}
$server->on('task', function ($server, $taskId, $task) {
if (! $task instanceof Task) {
$server->finish('');
return;
}
($task->handler)(...$task->arguments);
$server->finish('');
});
Coroutine support in Swoole is incompatible with XDebug and XHProf!
Expressive is a middleware application framework built on PSR-15
namespace Psr\Http\Server;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
interface RequestHandlerInterface {
public function handle(Request $request) : Response;
}
interface MiddlewareInterface {
public function process(
Request $request,
RequestHandlerInterface $handler
) : Response;
}
$server->on('request', function ($request, $response) use ($app) {
$appResponse = $app->handle(transformRequest($request));
transformResponse($response, $appResponse);
});
Codified in zend-expressive-swoole
$ ./vendor/bin/zend-expressive-swoole start
$result = $mysqli->query($sql);
while ($data = $result->fetch_assoc()) {
// ...
}
$server->defer($callback);
$server->task($someData);
use Phly\Swoole\TaskWorker\Task;
$server->task(new Task(function ($event) {
// handle the event
}, $event));
$listener = new QueueableListener($server, $listener);
// Where QueueableListener is equivalent to:
function (object $event) use ($server, $listener) : void {
$server->task(new Task($listener, $event));
}
In your own code:
$this->dispatcher->dispatch($someEvent);
return [
'zend-expressive-swoole' => [
'enable_coroutine' => true,
'swoole-http-server' => [
'mode' => SWOOLE_PROCESS,
],
],
];
$ ./vendor/bin/zend-expressive-swoole start --daemonize
# DOCKER-VERSION 1.3.2
FROM mwop/phly-docker-php-swoole:7.2-alpine
# Project files
COPY . /var/www/
# Reset "local"/development config files
WORKDIR /var/www
RUN rm -f config/development.config.php && \
rm config/autoload/*.local.php && \
mv config/autoload/local.php.dist config/autoload/local.php
# Overwrite entrypoint
RUN echo "#!/usr/bin/env bash
(cd /var/www ; ./vendor/bin/zend-expressive-swoole start)
" > /usr/local/bin/entrypoint
$template->addDefaultParam('*', 'user', $user);
$metadata = $resourceGenerator
->getMetadataMap()
->get(Collection::class);
$metadata->setQueryStringArguments(array_merge(
$metadata->getQueryStringArguments(),
['query' => $query]
));
if (! $validator->isValid($value)) {
$messages = $validator->getMessages();
}
echo implode("
", $validator->getMessages())
return $handler(
$request->withAttribute('user', $auth->getIdentity())
);
class StatelessVariant implements SomeInterface
{
private $proxy;
public function __construct(SomeInterface $proxy)
{
$this->proxy = $proxy;
}
}
public function morphState($data) : void
{
throw new CannotChangeStateException();
}
class StatelessVariant extends OriginalClass
{
public function morphState($data) : void
{
throw new CannotChangeStateException();
}
}
public function __construct(SomeClass $dependency) : void
becomes:
public function __construct(SomeClassFactory $factory) : void
and we then:
$dependency = ($this->factory)();
Pass stateful data to the service:
$allowed = $this->acl->isUserAllowed(
$request->getAttribute('user')
);
or the request:
$allowed = $this->acl->isRequestAllowed($request);
Instead of:
$template->addDefaultParam(/* ... */);
We use a request attribute
public function process(
Request $request,
RequestHandler $handler
) : Response {
return $handler->handle(
$request->withAttribute('template_params', (object) [])
);
}
to which we push data:
$params = $request->getAttribute('template_params');
$params->user = $this->deriveUserFromRequest($request);
return $handler->handle($request);
$templateParams = $request->getAttribute('template_params');
return new HtmlResponse($this->renderer->render(
'some::template',
array_merge((array) $templateParams, [
// more specific parameters
])
));
Use zend-expressive-session
and its zend-expressive-session-cache adapter