PHP Promise
, (*1)
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., (*2)
See also: https://github.com/krakjoe/pthreads, (*3)
For example in Dockerfile:, (*4)
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
The PHP Promise structure is below.
, (*5)
Requirements
Get Started
Run the composer require command., (*6)
$ composer require php-promise/promise:dev-master
Next, run the example code below and you will get started to Promise, (*7)
// 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., (*8)
// 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";
});
Supported Frameworks
- Laravel
- Need to use SafetyLoader.
- CakePHP
Use Case
- For example, you can use it to run heavely processing.
Provide methods
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 in Promise::then
.
-
$reject
is called in $callee
, which immediately runs the rejected function in Promise::catch
.
- You can define
$parameters
which you want to pass resource, object and any types to Promise context.
e.g.), (*9)
(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.), (*10)
$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.');
});
Promise::all( Promise ...$promises ): Promise
- Wait multiple promise processing, then which will collect to promise results.
Promise::race( Promise ...$promises ): Promise
-
Promise::race
return a Promise when promise get a success or failed.
Promise::then( callable $onFulfilled, callable $rejected ): Promise
-
Promise::catch
is called when $resolve
is called.
e.g.), (*11)
(new \Promise\Promise(function (Resolver $resolve, Rejecter $reject) {
$resolve();
}))->then(function () {
echo 'You can see this message when `$resolve` call.';
});
Promise::catch( callable $rejected ): Promise
-
Promise::catch
is called when $reject
is called.
e.g.), (*12)
(new \Promise\Promise(function (Resolver $resolve, Rejecter $reject) {
$reject();
}))->catch(function () {
echo 'You can see this message when `$resolve` call.';
});
Promise::finally( callable $onFinally ): Promise
-
Promise::finally
is called when $resolve
or $catch
is called.
e.g.), (*13)
(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.';
});
Annotations
-
resolve
and reject
can pass only serializable values on PHP because of pthreads
has problem when pass parameters to thread to thread.
- For example, cannot pass values
resource
which opened by stream as such as fopen
.
Unit Tests
PHPUnit Testing:, (*14)
$ composer run-script phpunit
Code Sniffer Testing:, (*15)
$ composer run-script phpcs