The PHP Promise is a library that asynchronously processes PHP like JavaScript Promise.
The library uses pthreads
, which is a PHP extension.
If you want to use the library, you need to install the pthreads
extension.
You may also need to re-compile PHP with --enable-maincontainer-zts
option in configuration.
See also: https://github.com/krakjoe/pthreads
For example in Dockerfile:
FROM centos:7
# Setup
RUN yum -y install epel-release wget
RUN cd /tmp && wget http://jp2.php.net/get/php-7.2.7.tar.gz/from/this/mirror -O php-7.2 && tar zxvf php-7.2
# Dependencies installation
RUN yum -y install git gcc gcc-c++ make libxml2-devel libicu-devel openssl-devel
# PHP installation
RUN cd /tmp/php-7.2.7 && \
./configure --enable-maintainer-zts --enable-pcntl --enable-intl --enable-zip --enable-pdo --enable-sockets --with-openssl && \
make && \
make install
# pthreads installation
RUN yum -y install autoconf
RUN cd /tmp && git clone https://github.com/krakjoe/pthreads.git && cd pthreads && \
phpize && \
./configure && \
make && \
make install
# Add an extension to php.ini
RUN echo extension=pthreads.so >> /usr/local/lib/php.ini
The PHP Promise structure is below.
- PHP >= 7.2
- pthreads 3
Run the composer require command.
$ composer require php-promise/promise:dev-master
Next, run the example code below and you will get started to Promise
// After 5 seconds, Promise will say a message "solved It!"
$promise = (new \Promise\Promise(function (Resolver $resolve, Rejecter $reject) {
sleep(5);
$resolve("Solved It!\n");
}))->then(function ($message) {
echo $message;
});
You can use Promise::all
which waits multiple Promise processing, which will collect Promise results.
// Say as follows:
// [RESOLVE] After 3 seconds says!
// [RESOLVE] After 5 seconds says!
// Sorry, Promise was rejected.
$promises = [];
$promises[] = (new \Promise\Promise(function (Resolver $resolve, Rejecter $reject) {
sleep(5);
$resolve("[RESOLVE] After 5 seconds!\n");
}))->then(function ($message) {
echo $message;
});
$promises[] = (new \Promise\Promise(function (Resolver $resolve, Rejecter $reject) {
sleep(3);
$reject("[REJECT] After 3 seconds!\n");
}))->then(function ($message) {
echo $message;
});
\Promise\Promise::all($promises)->then(function () {
echo "Okay, Promise is glad\n";
})->catch(function () {
echo "Sorry, Promise was rejected\n";
});
// or
\Promise\Promise::all($promises[0], $promises[1])->then(function () {
echo "Okay, Promise is glad\n";
})->catch(function () {
echo "Sorry, Promise was rejected\n";
});
- Laravel
- Need to use SafetyLoader.
- CakePHP
- For example, you can use it to run heavely processing.
Promise::__construct( callable $callee( Resolver $resolve, Rejecter $reject, ...$parameters ), ...$parameters ): Promise
- The constructor is called from your code and immediately runs
$callee
function. $callee
has two parameters that are$resolve
and$reject
, which are callable functions.$resolve
is called in$callee
, which immediately runs the resolved function inPromise::then
.$reject
is called in$callee
, which immediately runs the rejected function inPromise::catch
.- You can define
$parameters
which you want to pass resource, object and any types to Promise context.
e.g.)
(new \Promise\Promise(function (Resolver $resolve, Rejecter $reject) {
// Promise call `then` method when you called `$resolve` here.
$resolve();
// Promise call `reject` method when you called `$reject` here.
$reject();
}))->then(function () {
echo 'You can see this message when `$resolve` called.';
})->catch(function () {
echo 'You can see this message when `$reject` called.';
});
e.g.)
$handle = fopen('test.log', 'rw');
(new \Promise\Promise(function (Resolver $resolve, Rejecter $reject, $handle) {
$reject($handle);
}, $handle))->then(function ($handle) {
fwrite($handle, 'You can pass resource parameter.');
});
- Wait multiple promise processing, then which will collect to promise results.
Promise::race
return a Promise when promise get a success or failed.
Promise::catch
is called when$resolve
is called.
e.g.)
(new \Promise\Promise(function (Resolver $resolve, Rejecter $reject) {
$resolve();
}))->then(function () {
echo 'You can see this message when `$resolve` call.';
});
Promise::catch
is called when$reject
is called.
e.g.)
(new \Promise\Promise(function (Resolver $resolve, Rejecter $reject) {
$reject();
}))->catch(function () {
echo 'You can see this message when `$resolve` call.';
});
Promise::finally
is called when$resolve
or$catch
is called.
e.g.)
(new \Promise\Promise(function (Resolver $resolve, Rejecter $reject) {
$resolve();
}))->then(function () {
// do something
})->catch(function () {
// do something
})->finally(function () {
echo 'You can see this message when `$resolve` or `$catch` called.';
});
resolve
andreject
can pass only serializable values on PHP because ofpthreads
has problem when pass parameters to thread to thread.- For example, cannot pass values
resource
which opened by stream as such asfopen
.
PHPUnit Testing:
$ composer run-script phpunit
Code Sniffer Testing:
$ composer run-script phpcs