Join 4,000+ others and never miss out on new tips, tutorials, and more.
Latest version:
pecl install openswoole-22.1.2 | composer require openswoole/core:22.1.5
Runtime Hooks allow OpenSwoole to listen for internal PHP API calls, take control and execute your code in a non-blocking way, allowing us to use well known and tested libraries like the PDO extension or the CURL library. The benefit of using hooks is it allows us to use existing PHP ecosystem tools and libraries and not force us to use any coroutine specific clients, instead OpenSwoole aims to support the existing ecosystem. Even native blocking PHP functions like sleep
or file_get_contents
are supported, so it is easy to adopt coroutines throughout your application without much alteration to your existing codebase.
When hooks are enabled, OpenSwoole will take care of the coroutine scheduling for you under the hood, you don't need to write any additional logic with runtime hooks once they are setup and enabled. Hooks are required to run inside a coroutine context, this means you must use enabled hook functionality within a Co::run
or inside a OpenSwoole Server request where the coroutine context is created for you for each request.
Coroutine hooks were first supported since OpenSwoole v4.1.0
Before coroutine hooks, the alternative was to write a client for each use case, this included MySQL, Redis and even file operations etc. There would have to be a new client in order to support coroutines and make sure all IO operations are asynchronous. This task of managing multiple clients was a huge workload and it meant that a lot of duplicated API had to be done, so this became complex and even harder to scale when those clients needed updates or API changes. Coroutine clients were not native, they sat in front of native clients like PHP PDO
or phpredis
, meaning developers had to use an additional client.
The solution to all this complexity and confusion with additional coroutine specific clients is coroutine hooks. By enabling OpenSwoole runtime hooks, we can forget about using additional clients and use our existing PHP ecosystem libraries and extensions, while still having full support for coroutines and improved functionality support, adding hooks which work at the low level, meant that OpenSwoole could provider better support for coroutines in libraries like phpredis
and CURL. Developers only have to understand what hooks do and how to set them up, then they can continue developing as they would have done, rather than using an additional coroutine client.
Since the breakthrough with coroutine hooks, the old OpenSwoole coroutine clients are no longer recommended and it is suggested that you migrate to use coroutine hooks if you are still using the old coroutine client API objects.
Since OpenSwoole v4.1.0, you can use any IO libraries based on php_stream
within a coroutine context.
Libraries with coroutine support:
phpredis
) or (predis
)mysqlnd
) PDO and MySQLifile_get_contents
, fopen
and many more file I/O operationsstream_socket_client
functionsfsockopen
libcurl
Libraries without coroutine support:
libmysqlclient
mongo-c-client
pdo_pgsql
, pdo_ori
, pdo_odbc
, pdo_firebird
, php-amqp
You can enable coroutine support with hook Flags:
OpenSwoole\Runtime::HOOK_ALL
OpenSwoole\Runtime::HOOK_TCP
OpenSwoole\Runtime::HOOK_UNIX
OpenSwoole\Runtime::HOOK_UDP
OpenSwoole\Runtime::HOOK_UDG
OpenSwoole\Runtime::HOOK_SSL
OpenSwoole\Runtime::HOOK_TLS
OpenSwoole\Runtime::HOOK_SLEEP
OpenSwoole\Runtime::HOOK_FILE
OpenSwoole\Runtime::HOOK_STREAM_FUNCTION
OpenSwoole\Runtime::HOOK_BLOCKING_FUNCTION
OpenSwoole\Runtime::HOOK_PROC
OpenSwoole\Runtime::HOOK_CURL
OpenSwoole\Runtime::HOOK_NATIVE_CURL
OpenSwoole\Runtime::HOOK_SOCKETS
OpenSwoole\Runtime::HOOK_STDIO
<?php
OpenSwoole\Runtime::enableCoroutine(bool $enable = true, int $flags = OpenSwoole\Runtime::HOOK_ALL);
// Or
Co::set(['hook_flags'=> OpenSwoole\Runtime::HOOK_ALL]);
The code above will enable coroutine support for all OpenSwoole Hooks, you can change which hooks you want to enable but it is likely better for performance to enable them all and take advantage of coroutines.
The enableCoroutine
call should be placed at the start of your script or at least before any Co::run
or server is used, this so that you can obtain 100% coverage. When calling enableCoroutine
it will take effect globally for the current process.
To enable multiple flags you must separate them using the pipe |
symbol:
<?php
Co::set(['hook_flags'=> OpenSwoole\Runtime::HOOK_TCP | OpenSwoole\Runtime::HOOK_SLEEP]);
Remember that enabling any hooks means you have to perform any operations inside a coroutine container for coroutine support
<?php
// Before v4.5.4
OpenSwoole\Runtime::enableCoroutine(true, OpenSwoole\Runtime::HOOK_ALL | OpenSwoole\Runtime::HOOK_CURL);
OpenSwoole\Runtime::HOOK_ALL
containsOpenSwoole\Runtime::HOOK_CURL
from version v4.5.4
<?php
// All flags but not the sleep flag
OpenSwoole\Runtime::enableCoroutine(true, OpenSwoole\Runtime::HOOK_ALL ^ OpenSwoole\Runtime::HOOK_SLEEP);
The coroutine scheduler is what OpenSwoole uses at a low level to manage different coroutine context containers and switch between other coroutines when one is waiting or blocking. Read more about the coroutine scheduler API to understand when it should be used. Most of the time you will never need to use it directly because OpenSwoole does it for you already.
<?php
$sch = new OpenSwoole\Coroutine\Scheduler();
$sch->set(['hook_flags' => OpenSwoole\Runtime::HOOK_ALL]);
If you are inside a coroutine context or a OpenSwoole server, you can change hooks dynamically once they have been enabled:
<?php
// Enable all OpenSwoole hooks at the beginning
OpenSwoole\Runtime::enableCoroutine(true, OpenSwoole\Runtime::HOOK_ALL);
// Only use the TCP hook from now on...
OpenSwoole\Runtime::enableCoroutine(true, OpenSwoole\Runtime::HOOK_TCP);
Hooks can be changed throughout the application, just take note that once any hooks are changed this will take affect globally for the current process, make sure other operations are not ongoing as this may affect them, removing or adding hooks. It is more recommended to enable hooks at the start of a PHP script so you get full coverage.
<?php
OpenSwoole\Runtime::getHookFlags();
Returns the currently set hook flags.
<?php
// Enable all hooks
OpenSwoole\Runtime::setHookFlags(OpenSwoole\Runtime::HOOK_ALL);
// Disable all hooks
OpenSwoole\Runtime::setHookFlags(0);
<?php
OpenSwoole\Runtime::enableCoroutine(false);