Introducing RxPHP
RxPHP ( https://github.com/ReactiveX/RxPHP ) is a port of RxJS. We're going to be using Composer to handle all dependencies in our PHP projects. It has become a state of the art tool, so if you haven't used it before, download it first and check out some basic usage at https://getcomposer.org/ .
Then, create a new directory and initialize a composer project:
$ mkdir rxphp_01 $ cd rxphp_01 $ php composer.phar init
Fill in the required fields by the interactive wizard and then add RxPHP as a dependency:
$ php composer.phar require reactivex/rxphp
When the library successfully downloads, composer will also create autoload.php
file to handle all class auto-loading on demand.
Then, our code will print string lengths of different types of fruit:
// rxphp_01.php require __DIR__ . '/vendor/autoload.php'; $fruits = ['apple', 'banana', 'orange', 'raspberry']; $observer = new \Rx\Observer\CallbackObserver( function($value) { printf("%s\n", $value); }, null, function() { print("Complete\n"); }); \Rx\Observable::fromArray($fruits) ->map(function($value) { return strlen($value); }) ->subscribe($observer);
Note
In all future examples, we won't include the autoload.php
file, to keep the examples as short as possible. However, it's obviously required in order to run the examples. If you're unsure, have a look at the source codes provided for each chapter.
We first created an observer - CallbackObserver
to be precise - which takes three functions as arguments. These are called on the next item in the stream, on error and when the input stream is complete and won't emit any more items.
The advantage of the CallbackObserver
class is that we don't need to write a custom observer class every time we want to handle incoming items in some special and not very reusable way. With CallbackObserver
, we can just write the callables for signals we want to handle.
When we run this example, we'll see:
$ php rxphp_01.php 5 6 6 9 Complete
This example was very easy, but compared to the JavaScript environment, it's not very common to use asynchronous operations in PHP and, in case we do have to work asynchronously, it's probably something non-trivial. In Chapter 3, Writing a Reddit reader with RxPHP, we'll use Symfony Console component to handle all user input from the command line and, where we can, use similar principles to handling mouse events as we saw in the two RxJS examples above.
The JavaScript examples work very well as examples of what reactive programming using Reactive Extensions looks like and what its benefits are.
Note
If you want to know more about Reactive Extensions, head over to http://reactivex.io/. Also, before continuing to the next chapter, you can have a look at how many different operators Rx supports http://reactivex.io/documentation/operators.html and how these can be used in different languages.
RxPHP 1.x and RxPHP 2
As of April 2017, there're two versions of RxPHP.
The RxPHP 1.x is stable and requires PHP 5.5+. All examples in this book are made for RxPHP 1.x, more specifically, RxPHP 1.5+. It's API is based mostly on RxJS 4, but it takes some features from RxJS 5 as well.
There's also RxPHP 2 in development, which requires PHP 7.0+. RxPHP 2 API from the user's perspective is almost the same as 1.x, it just makes some things easier (for example working with even loops, as we'll see in Chapter 6, PHP Streams API and Higher-Order Observables). When we encounter any differences worth mentioning, we'll give them extra space.
Note
The newer RxPHP 2 was meant to be based to the PHP loop interoperability specification (https://github.com/async-interop/event-loop). However, the specification is still in pre-release stage and it won't be stable in the nearest future. For this reason, the RxPHP team decided to leave the async-interop support for future releases. For more information visit https://github.com/ReactiveX/RxPHP/pull/150.