Reactive extensions for PHP

Overview

RxPHP

Reactive extensions for PHP. The reactive extensions for PHP are a set of libraries to compose asynchronous and event-based programs using observable collections and LINQ-style query operators in PHP.

Build Status Coverage Status

note: This repo is for v2.x, the latest version of RxPHP, not v1.x.

Example

$source = \Rx\Observable::fromArray([1, 2, 3, 4]);

$source->subscribe(
    function ($x) {
        echo 'Next: ', $x, PHP_EOL;
    },
    function (Exception $ex) {
        echo 'Error: ', $ex->getMessage(), PHP_EOL;
    },
    function () {
        echo 'Completed', PHP_EOL;
    }
);

//Next: 1
//Next: 2
//Next: 3
//Next: 4
//Completed

Try out the demos

$ git clone https://github.com/ReactiveX/RxPHP.git
$ cd RxPHP
$ composer install
$ php demo/interval/interval.php

Have fun running the demos in /demo.

note: When running the demos, the scheduler is automatically bootstrapped. When using RxPHP within your own project, you'll need to set the default scheduler.

Installation

  1. Install an event loop. Any event loop should work, but the ReactPHP event loop is recommended.
$ composer require react/event-loop
  1. Install RxPHP using composer.
$ composer require reactivex/rxphp
  1. Write some code.
<?php

require_once __DIR__ . '/vendor/autoload.php';

use Rx\Observable;
use React\EventLoop\Factory;
use Rx\Scheduler;

$loop = Factory::create();

//You only need to set the default scheduler once
Scheduler::setDefaultFactory(function() use($loop){
    return new Scheduler\EventLoopScheduler($loop);
});

Observable::interval(1000)
    ->take(5)
    ->flatMap(function ($i) {
        return Observable::of($i + 1);
    })
    ->subscribe(function ($e) {
        echo $e, PHP_EOL;
    });

$loop->run();

Working with Promises

Some async PHP frameworks have yet to fully embrace the awesome power of observables. To help ease the transition, RxPHP has built in support for ReactPHP promises.

Mixing a promise into an observable stream:

Observable::interval(1000)
    ->flatMap(function ($i) {
        return Observable::fromPromise(\React\Promise\resolve(42 + $i));
    })
    ->subscribe(function ($v) {
        echo $v . PHP_EOL;
    });

Converting an Observable into a promise. (This is useful for libraries that use generators and coroutines):

$observable = Observable::interval(1000)
    ->take(10)
    ->toArray()
    ->map('json_encode');

$promise = $observable->toPromise();

Additional Information

License

RxPHP is licensed under the MIT License - see the LICENSE file for details

Comments
  • RxPHP v2.x

    RxPHP v2.x

    I've started work on RxPHP v2 with the goal of bringing it's behavior closer to RxJS 4/5. You can see the progress here

    Here's a list of the changes I've made so far:

    • PHP 7 is a minimum requirement
    • It now uses the interop event-loop ( ~~defaults to ReactPHP, but~~ it'll work with any library that support the interop loop, including ~~Icicle~~, ReactPHP, Amphp and KoolKode)
    • It uses a static scheduler (you no longer pass the scheduler through subscribe). For the most part, the user will not have to worry about the scheduler.
    • ~~The event loop auto starts with register_shutdown_function. The less the user has to worry about the underlying event loop and scheduler, the better.~~
    • We had some non-standard names for operators, because they were reserved words in PHP, those have all been renamed (of, empty, do, catch, switch). Aliases of the old names were left for backwards compatibility.
    • Lots of cleanup
    • Included Allow custom operators

    v1 example

    With v1, the user has to know when to create a new scheduler and has to be familiar with event loops, which can be confusing and easy to mess up.

    $loop      = \React\EventLoop\Factory::create();
    $scheduler = new \Rx\Scheduler\EventLoopScheduler($loop);
    
    \Rx\Observable::interval(1000)
        ->take(5)
        ->flatMap(function ($i) {
            return \Rx\Observable::just($i + 1);
        })
        ->subscribe(new \Rx\Observer\CallbackObserver(function ($e) {
            echo $e, PHP_EOL;
        }), $scheduler);
    
    $loop->run();
    
    

    v2 example

    With v2, we pick the correct default scheduler for each operator that requires one, which you can override as needed (setting a scheduler should be the exception, not the rule). In the example below, interval and of already have the correct default scheduler, so the user doesn't need to define one.

    \Rx\Observable::interval(1000)
        ->take(5)
        ->flatMap(function ($i) {
            return \Rx\Observable::of($i + 1);
        })
        ->subscribe(function ($e) {
            echo $e, PHP_EOL;
        });
    

    v2 with Loop::execute example

    You can also use it within Loop::execute, without making any changes to your Rx code

    \Interop\Async\Loop::execute(function () {
        \Rx\Observable::interval(1000)
            ->take(5)
            ->flatMap(function ($i) {
                return \Rx\Observable::of($i + 1);
            })
            ->subscribe(function ($e) {
                echo $e, PHP_EOL;
            });
    });
    

    Remaining Items and Ideas

    • [x] If possible, combine subscribe and subscribeCallback
    • [x] Add support for async-interop/promise
    • [x] Move react promise support to stand alone project or remove
    • [x] ~~Look into simplifying AnonymousObservable by moving auto dispose code to Observable~~
    • [x] Figure out how to get it to work with HHVM
    • [ ] Add a forEach method to Observable that'll behave like subscribe except it'll block until complete (for use with synchronous code) similar to RxJava.

    Before I move this to the ReactiveX/RxPHP repo, I'd like to get some feedback on the changes above as well as other changes or pain points that we should address with v2.

    help wanted 
    opened by davidwdan 23
  • Benchmark runner

    Benchmark runner

    I've mentioned it in #134 already. This is a script runner with a couple of benchmarks that follow their RxJS 5 equivalents.

    It can run all tests in the /benchmark/**/*.php directory with:

    php benchmark/run.php
    

    Or a single script:

    php benchmark/run.php benchmark/distinct/distinct.php
    
    opened by martinsik 18
  • Testing?

    Testing?

    Not an issue, more a question but could you point me in the direction of how to test something like the following:

    $observable ->flatmap(function($value){ return a zip of a couple of api requests if exists }) ->map(function($value){ return a cleaned value }) ->flatmap(function($value){ return related api requests if exists }) ->filter(function($value){ return false if related api requests don't pass }) ->filter(function($value){ return false if related api requests don't pass }) ->filter(function($value){ return false if related api requests don't pass }) ->toArray();

    Thanks!

    P.S thanks for an awesome library :)

    opened by alexsup 16
  • The finally() operator

    The finally() operator

    This is the finally() operator based on its RxJS 5 implementation. I called in finallyCall() here because finally is a keyword but in RxPHP 2 I'll rename it to just finally().

    opened by martinsik 13
  • Marble testing

    Marble testing

    This PR is a preliminary implementation of marble testing as requested at SunshinePHP at the talk by @luijar see: https://github.com/ReactiveX/rxjs/blob/master/doc/writing-marble-tests.md

    Example:

        public function testMapAddOne()
        {
            $cold     = '--1--2--|';
            $expected = '--2--3--|';
    
            $results = $this->scheduler->startWithCreate(function () use ($cold) {
                return $this->createCold($cold)->map(function ($x) { return $x + 1; });
            });
    
            $this->assertEquals($expected, $this->convertMessagesToMarbles($results->getMessages()));
        }
    
    opened by mbonneau 11
  • use now() method in VirtualTimeScheduler::schedule

    use now() method in VirtualTimeScheduler::schedule

    Will change nothing for VirtualTimeScheduler itself but will fix clock offset issue in EventLoopScheduler

    Clock is often out of sync when I use EventLoopScheduler, this patch seems to fix all my troubles.

    opened by etienneroudeix 10
  • compose() operator

    compose() operator

    Please add thru() operator inspired by mostjs: https://github.com/cujojs/most/blob/master/docs/api.md#thru

    $process = function ($observable) {
        return $observable
            ->filter(function ($val) { return $val % 2 == 0; })
            ->map(function ($val) { return $val * 2; });
    };
    

    it allows to use

    $source = Observable::fromArray(range(1, 10))
           ->map(..)
           ->filter(..)
            ->thru($process)
            ->map(..);
    
    

    instead of

    $source = $process(
                        Observable::fromArray(range(1, 10))
                           ->map(..)
                           ->filter(..)
                      )->map(..);
    
    opened by mamciek 9
  • Unexpected Script Execution within PHP 7.3

    Unexpected Script Execution within PHP 7.3

    PHP version: 7.3.0 OS: 10.13.6 RxPHP: v2.0.7 React Event Loop: v1.0.0

    Issue: It appears as though the event loop is being caused to go into an infinite loop in random places, preventing the completion of the script.

    Shauns-MacBook-Air:untitled1 shaunbramley$ php index.php
    10
    20
    30
    40
    ^C
    Shauns-MacBook-Air:untitled1 shaunbramley$ php index.php
    10
    20
    30
    40
    50
    60
    ^C
    Shauns-MacBook-Air:untitled1 shaunbramley$ php index.php
    10
    20
    30
    40
    50
    ^C
    Shauns-MacBook-Air:untitled1 shaunbramley$ 
    

    Expected Output:

    Shauns-MacBook-Air:untitled1 shaunbramley$ php index.php
    10
    20
    30
    40
    50
    60
    Shauns-MacBook-Air:untitled1 shaunbramley$ 
    

    Script being executed:

    require_once 'vendor/autoload.php';
    
    
    $sets = function() : array {
        return [10, 20, 30, 40, 50, 60];
    };
    
    use Rx\Observable;
    use React\EventLoop\Factory;
    
    $loop = Factory::create();
    
    
    Observable::fromArray($sets())
    ->subscribe(function($e) {
        echo $e, PHP_EOL;
    });
    
    $loop->run();
    

    XDebug Trace: trace.2231894626.0ca0c7.xt.zip

    PHP version and information:

    Shauns-MacBook-Air:untitled1 shaunbramley$ php -v
    PHP 7.3.0 (cli) (built: Dec 11 2018 19:39:33) ( NTS )
    Copyright (c) 1997-2018 The PHP Group
    Zend Engine v3.3.0-dev, Copyright (c) 1998-2018 Zend Technologies
        with Xdebug v2.7.0beta1, Copyright (c) 2002-2018, by Derick Rethans
        with Zend OPcache v7.3.0, Copyright (c) 1999-2018, by Zend Technologies
    Shauns-MacBook-Air:untitled1 shaunbramley$ php -info
    phpinfo()
    PHP Version => 7.3.0
    
    System => Darwin Shauns-MacBook-Air.local 17.7.0 Darwin Kernel Version 17.7.0: Fri Nov  2 20:43:16 PDT 2018; root:xnu-4570.71.17~1/RELEASE_X86_64 x86_64
    Build Date => Dec 11 2018 19:31:06
    Configure Command =>  './configure'  '--prefix=/usr/local/Cellar/php/7.3.0' '--localstatedir=/usr/local/var' '--sysconfdir=/usr/local/etc/php/7.3' '--with-config-file-path=/usr/local/etc/php/7.3' '--with-config-file-scan-dir=/usr/local/etc/php/7.3/conf.d' '--with-pear=/usr/local/Cellar/php/7.3.0/share/php/pear' '--enable-bcmath' '--enable-calendar' '--enable-dba' '--enable-dtrace' '--enable-exif' '--enable-ftp' '--enable-fpm' '--enable-intl' '--enable-mbregex' '--enable-mbstring' '--enable-mysqlnd' '--enable-opcache-file' '--enable-pcntl' '--enable-phpdbg' '--enable-phpdbg-webhelper' '--enable-shmop' '--enable-soap' '--enable-sockets' '--enable-sysvmsg' '--enable-sysvsem' '--enable-sysvshm' '--enable-wddx' '--enable-zip' '--with-apxs2=/usr/local/opt/httpd/bin/apxs' '--with-bz2=/usr' '--with-curl=/usr/local/opt/curl-openssl' '--with-fpm-user=_www' '--with-fpm-group=_www' '--with-freetype-dir=/usr/local/opt/freetype' '--with-gd' '--with-gettext=/usr/local/opt/gettext' '--with-gmp=/usr/local/opt/gmp' '--with-iconv=/usr' '--with-icu-dir=/usr/local/opt/icu4c' '--with-jpeg-dir=/usr/local/opt/jpeg' '--with-kerberos=/usr' '--with-layout=GNU' '--with-ldap=/usr/local/opt/openldap' '--with-ldap-sasl=/usr' '--with-libxml-dir=/usr' '--with-libedit=/usr' '--with-libzip' '--with-mhash=/usr' '--with-mysql-sock=/tmp/mysql.sock' '--with-mysqli=mysqlnd' '--with-ndbm=/usr' '--with-openssl=/usr/local/opt/openssl' '--with-password-argon2=/usr/local/opt/argon2' '--with-pdo-dblib=/usr/local/opt/freetds' '--with-pdo-mysql=mysqlnd' '--with-pdo-odbc=unixODBC,/usr/local/opt/unixodbc' '--with-pdo-pgsql=/usr/local/opt/libpq' '--with-pdo-sqlite=/usr/local/opt/sqlite' '--with-pgsql=/usr/local/opt/libpq' '--with-pic' '--with-png-dir=/usr/local/opt/libpng' '--with-pspell=/usr/local/opt/aspell' '--with-sodium=/usr/local/opt/libsodium' '--with-sqlite3=/usr/local/opt/sqlite' '--with-tidy=/usr/local/opt/tidy-html5' '--with-unixODBC=/usr/local/opt/unixodbc' '--with-webp-dir=/usr/local/opt/webp' '--with-xmlrpc' '--with-xsl=/usr' '--with-zlib=/usr'
    Server API => Command Line Interface
    Virtual Directory Support => disabled
    Configuration File (php.ini) Path => /usr/local/etc/php/7.3
    Loaded Configuration File => /usr/local/etc/php/7.3/php.ini
    Scan this dir for additional .ini files => /usr/local/etc/php/7.3/conf.d
    Additional .ini files parsed => /usr/local/etc/php/7.3/conf.d/ext-opcache.ini
    
    PHP API => 20180731
    PHP Extension => 20180731
    Zend Extension => 320180731
    Zend Extension Build => API320180731,NTS
    PHP Extension Build => API20180731,NTS
    Debug Build => no
    Thread Safety => disabled
    Zend Signal Handling => enabled
    Zend Memory Manager => enabled
    Zend Multibyte Support => provided by mbstring
    IPv6 Support => enabled
    DTrace Support => available, disabled
    
    Registered PHP Streams => https, ftps, compress.zlib, compress.bzip2, php, file, glob, data, http, ftp, phar, zip
    Registered Stream Socket Transports => tcp, udp, unix, udg, ssl, tls, tlsv1.0, tlsv1.1, tlsv1.2
    Registered Stream Filters => zlib.*, bzip2.*, convert.iconv.*, string.rot13, string.toupper, string.tolower, string.strip_tags, convert.*, consumed, dechunk
    
    This program makes use of the Zend Scripting Language Engine:
    Zend Engine v3.3.0-dev, Copyright (c) 1998-2018 Zend Technologies
        with Xdebug v2.7.0beta1, Copyright (c) 2002-2018, by Derick Rethans
        with Zend OPcache v7.3.0, Copyright (c) 1999-2018, by Zend Technologies
    
    
     _______________________________________________________________________
    
    
    Configuration
    
    bcmath
    
    BCMath support => enabled
    
    Directive => Local Value => Master Value
    bcmath.scale => 0 => 0
    
    bz2
    
    BZip2 Support => Enabled
    Stream Wrapper support => compress.bzip2://
    Stream Filter support => bzip2.decompress, bzip2.compress
    BZip2 Version => 1.0.6, 6-Sept-2010
    
    calendar
    
    Calendar support => enabled
    
    Core
    
    PHP Version => 7.3.0
    
    Directive => Local Value => Master Value
    allow_url_fopen => On => On
    allow_url_include => Off => Off
    arg_separator.input => & => &
    arg_separator.output => & => &
    auto_append_file => no value => no value
    auto_globals_jit => On => On
    auto_prepend_file => no value => no value
    browscap => no value => no value
    default_charset => UTF-8 => UTF-8
    default_mimetype => text/html => text/html
    disable_classes => no value => no value
    disable_functions => no value => no value
    display_errors => STDOUT => STDOUT
    display_startup_errors => On => On
    doc_root => no value => no value
    docref_ext => no value => no value
    docref_root => no value => no value
    enable_dl => Off => Off
    enable_post_data_reading => On => On
    error_append_string => no value => no value
    error_log => no value => no value
    error_prepend_string => no value => no value
    error_reporting => 32767 => 32767
    expose_php => On => On
    extension_dir => /usr/local/lib/php/pecl/20180731 => /usr/local/lib/php/pecl/20180731
    file_uploads => On => On
    hard_timeout => 2 => 2
    highlight.comment => <font style="color: #FF8000">#FF8000</font> => <font style="color: #FF8000">#FF8000</font>
    highlight.default => <font style="color: #0000BB">#0000BB</font> => <font style="color: #0000BB">#0000BB</font>
    highlight.html => <font style="color: #000000">#000000</font> => <font style="color: #000000">#000000</font>
    highlight.keyword => <font style="color: #007700">#007700</font> => <font style="color: #007700">#007700</font>
    highlight.string => <font style="color: #DD0000">#DD0000</font> => <font style="color: #DD0000">#DD0000</font>
    html_errors => Off => Off
    ignore_repeated_errors => Off => Off
    ignore_repeated_source => Off => Off
    ignore_user_abort => Off => Off
    implicit_flush => On => On
    include_path => .:/usr/local/Cellar/php/7.3.0/share/php/pear => .:/usr/local/Cellar/php/7.3.0/share/php/pear
    input_encoding => no value => no value
    internal_encoding => no value => no value
    log_errors => On => On
    log_errors_max_len => 1024 => 1024
    mail.add_x_header => Off => Off
    mail.force_extra_parameters => no value => no value
    mail.log => no value => no value
    max_execution_time => 0 => 0
    max_file_uploads => 20 => 20
    max_input_nesting_level => 64 => 64
    max_input_time => -1 => -1
    max_input_vars => 1000 => 1000
    memory_limit => 1024M => 1024M
    open_basedir => no value => no value
    output_buffering => 0 => 0
    output_encoding => no value => no value
    output_handler => no value => no value
    post_max_size => 8M => 8M
    precision => 14 => 14
    realpath_cache_size => 4096K => 4096K
    realpath_cache_ttl => 120 => 120
    register_argc_argv => On => On
    report_memleaks => On => On
    report_zend_debug => Off => Off
    request_order => GP => GP
    sendmail_from => no value => no value
    sendmail_path => /usr/sbin/sendmail -t -i  => /usr/sbin/sendmail -t -i 
    serialize_precision => -1 => -1
    short_open_tag => Off => Off
    SMTP => localhost => localhost
    smtp_port => 25 => 25
    sys_temp_dir => no value => no value
    syslog.facility => LOG_USER => LOG_USER
    syslog.filter => no-ctrl => no-ctrl
    syslog.ident => php => php
    track_errors => Off => Off
    unserialize_callback_func => no value => no value
    upload_max_filesize => 2M => 2M
    upload_tmp_dir => no value => no value
    user_dir => no value => no value
    user_ini.cache_ttl => 300 => 300
    user_ini.filename => .user.ini => .user.ini
    variables_order => GPCS => GPCS
    xmlrpc_error_number => 0 => 0
    xmlrpc_errors => Off => Off
    zend.assertions => 1 => 1
    zend.detect_unicode => On => On
    zend.enable_gc => On => On
    zend.multibyte => Off => Off
    zend.script_encoding => no value => no value
    zend.signal_check => Off => Off
    
    ctype
    
    ctype functions => enabled
    
    curl
    
    cURL support => enabled
    cURL Information => 7.63.0
    Age => 4
    Features
    AsynchDNS => Yes
    CharConv => No
    Debug => No
    GSS-Negotiate => No
    IDN => No
    IPv6 => Yes
    krb4 => No
    Largefile => Yes
    libz => Yes
    NTLM => Yes
    NTLMWB => Yes
    SPNEGO => Yes
    SSL => Yes
    SSPI => No
    TLS-SRP => Yes
    HTTP2 => Yes
    GSSAPI => Yes
    KERBEROS5 => Yes
    UNIX_SOCKETS => Yes
    PSL => No
    HTTPS_PROXY => Yes
    MULTI_SSL => No
    BROTLI => Yes
    Protocols => dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, pop3, pop3s, rtsp, smb, smbs, smtp, smtps, telnet, tftp
    Host => x86_64-apple-darwin17.7.0
    SSL Version => OpenSSL/1.0.2q
    ZLib Version => 1.2.11
    
    Directive => Local Value => Master Value
    curl.cainfo => no value => no value
    
    date
    
    date/time support => enabled
    timelib version => 2018.01RC2
    "Olson" Timezone Database Version => 2018.5
    Timezone Database => internal
    Default timezone => UTC
    
    Directive => Local Value => Master Value
    date.default_latitude => 31.7667 => 31.7667
    date.default_longitude => 35.2333 => 35.2333
    date.sunrise_zenith => 90.583333 => 90.583333
    date.sunset_zenith => 90.583333 => 90.583333
    date.timezone => no value => no value
    
    dba
    
    DBA support => enabled
    Supported handlers => ndbm cdb cdb_make inifile flatfile 
    
    Directive => Local Value => Master Value
    dba.default_handler => flatfile => flatfile
    
    dom
    
    DOM/XML => enabled
    DOM/XML API Version => 20031129
    libxml Version => 2.9.4
    HTML Support => enabled
    XPath Support => enabled
    XPointer Support => enabled
    Schema Support => enabled
    RelaxNG Support => enabled
    
    ev
    
    Ev support => enabled
    Debug support => disabled
    Version => 1.0.4
    
    exif
    
    EXIF Support => enabled
    Supported EXIF Version => 0220
    Supported filetypes => JPEG, TIFF
    Multibyte decoding support using mbstring => enabled
    Extended EXIF tag formats => Canon, Casio, Fujifilm, Nikon, Olympus, Samsung, Panasonic, DJI, Sony, Pentax, Minolta, Sigma, Foveon, Kyocera, Ricoh, AGFA, Epson
    
    Directive => Local Value => Master Value
    exif.decode_jis_intel => JIS => JIS
    exif.decode_jis_motorola => JIS => JIS
    exif.decode_unicode_intel => UCS-2LE => UCS-2LE
    exif.decode_unicode_motorola => UCS-2BE => UCS-2BE
    exif.encode_jis => no value => no value
    exif.encode_unicode => ISO-8859-15 => ISO-8859-15
    
    fileinfo
    
    fileinfo support => enabled
    libmagic => 533
    
    filter
    
    Input Validation and Filtering => enabled
    
    Directive => Local Value => Master Value
    filter.default => unsafe_raw => unsafe_raw
    filter.default_flags => no value => no value
    
    ftp
    
    FTP support => enabled
    FTPS support => enabled
    
    gd
    
    GD Support => enabled
    GD Version => bundled (2.1.0 compatible)
    FreeType Support => enabled
    FreeType Linkage => with freetype
    FreeType Version => 2.9.1
    GIF Read Support => enabled
    GIF Create Support => enabled
    JPEG Support => enabled
    libJPEG Version => 9 compatible
    PNG Support => enabled
    libPNG Version => 1.6.35
    WBMP Support => enabled
    XBM Support => enabled
    WebP Support => enabled
    
    Directive => Local Value => Master Value
    gd.jpeg_ignore_warning => 1 => 1
    
    gettext
    
    GetText Support => enabled
    
    gmp
    
    gmp support => enabled
    GMP version => 6.1.2
    
    hash
    
    hash support => enabled
    Hashing Engines => md2 md4 md5 sha1 sha224 sha256 sha384 sha512/224 sha512/256 sha512 sha3-224 sha3-256 sha3-384 sha3-512 ripemd128 ripemd160 ripemd256 ripemd320 whirlpool tiger128,3 tiger160,3 tiger192,3 tiger128,4 tiger160,4 tiger192,4 snefru snefru256 gost gost-crypto adler32 crc32 crc32b fnv132 fnv1a32 fnv164 fnv1a64 joaat haval128,3 haval160,3 haval192,3 haval224,3 haval256,3 haval128,4 haval160,4 haval192,4 haval224,4 haval256,4 haval128,5 haval160,5 haval192,5 haval224,5 haval256,5 
    
    MHASH support => Enabled
    MHASH API Version => Emulated Support
    
    iconv
    
    iconv support => enabled
    iconv implementation => libiconv
    iconv library version => 1.11
    
    Directive => Local Value => Master Value
    iconv.input_encoding => no value => no value
    iconv.internal_encoding => no value => no value
    iconv.output_encoding => no value => no value
    
    intl
    
    Internationalization support => enabled
    ICU version => 63.1
    ICU Data version => 63.1
    ICU TZData version => 2018e
    ICU Unicode version => 11.0
    
    Directive => Local Value => Master Value
    intl.default_locale => no value => no value
    intl.error_level => 0 => 0
    intl.use_exceptions => 0 => 0
    
    json
    
    json support => enabled
    json version => 1.7.0
    
    ldap
    
    LDAP Support => enabled
    Total Links => 0/unlimited
    API Version => 3001
    Vendor Name => OpenLDAP
    Vendor Version => 20446
    SASL Support => Enabled
    
    Directive => Local Value => Master Value
    ldap.max_links => Unlimited => Unlimited
    
    libxml
    
    libXML support => active
    libXML Compiled Version => 2.9.4
    libXML Loaded Version => 20904
    libXML streams => enabled
    
    mbstring
    
    Multibyte Support => enabled
    Multibyte string engine => libmbfl
    HTTP input encoding translation => disabled
    libmbfl version => 1.3.2
    oniguruma version => 6.9.0
    
    mbstring extension makes use of "streamable kanji code filter and converter", which is distributed under the GNU Lesser General Public License version 2.1.
    
    Multibyte (japanese) regex support => enabled
    Multibyte regex (oniguruma) backtrack check => On
    Multibyte regex (oniguruma) version => 6.9.0
    
    Directive => Local Value => Master Value
    mbstring.detect_order => no value => no value
    mbstring.encoding_translation => Off => Off
    mbstring.func_overload => 0 => 0
    mbstring.http_input => no value => no value
    mbstring.http_output => no value => no value
    mbstring.http_output_conv_mimetypes => ^(text/|application/xhtml\+xml) => ^(text/|application/xhtml\+xml)
    mbstring.internal_encoding => no value => no value
    mbstring.language => neutral => neutral
    mbstring.strict_detection => Off => Off
    mbstring.substitute_character => no value => no value
    
    mysqli
    
    MysqlI Support => enabled
    Client API library version => mysqlnd 5.0.12-dev - 20150407 - $Id: 401a40ebd5e281cf22215acdc170723a1519aaa9 $
    Active Persistent Links => 0
    Inactive Persistent Links => 0
    Active Links => 0
    
    Directive => Local Value => Master Value
    mysqli.allow_local_infile => On => On
    mysqli.allow_persistent => On => On
    mysqli.default_host => no value => no value
    mysqli.default_port => 3306 => 3306
    mysqli.default_pw => no value => no value
    mysqli.default_socket => /tmp/mysql.sock => /tmp/mysql.sock
    mysqli.default_user => no value => no value
    mysqli.max_links => Unlimited => Unlimited
    mysqli.max_persistent => Unlimited => Unlimited
    mysqli.reconnect => Off => Off
    mysqli.rollback_on_cached_plink => Off => Off
    
    mysqlnd
    
    mysqlnd => enabled
    Version => mysqlnd 5.0.12-dev - 20150407 - $Id: 401a40ebd5e281cf22215acdc170723a1519aaa9 $
    Compression => supported
    core SSL => supported
    extended SSL => supported
    Command buffer size => 4096
    Read buffer size => 32768
    Read timeout => 86400
    Collecting statistics => Yes
    Collecting memory statistics => Yes
    Tracing => n/a
    Loaded plugins => mysqlnd,debug_trace,auth_plugin_mysql_native_password,auth_plugin_mysql_clear_password,auth_plugin_sha256_password
    API Extensions => pdo_mysql,mysqli
    
    mysqlnd statistics =>  
    bytes_sent => 0
    bytes_received => 0
    packets_sent => 0
    packets_received => 0
    protocol_overhead_in => 0
    protocol_overhead_out => 0
    bytes_received_ok_packet => 0
    bytes_received_eof_packet => 0
    bytes_received_rset_header_packet => 0
    bytes_received_rset_field_meta_packet => 0
    bytes_received_rset_row_packet => 0
    bytes_received_prepare_response_packet => 0
    bytes_received_change_user_packet => 0
    packets_sent_command => 0
    packets_received_ok => 0
    packets_received_eof => 0
    packets_received_rset_header => 0
    packets_received_rset_field_meta => 0
    packets_received_rset_row => 0
    packets_received_prepare_response => 0
    packets_received_change_user => 0
    result_set_queries => 0
    non_result_set_queries => 0
    no_index_used => 0
    bad_index_used => 0
    slow_queries => 0
    buffered_sets => 0
    unbuffered_sets => 0
    ps_buffered_sets => 0
    ps_unbuffered_sets => 0
    flushed_normal_sets => 0
    flushed_ps_sets => 0
    ps_prepared_never_executed => 0
    ps_prepared_once_executed => 0
    rows_fetched_from_server_normal => 0
    rows_fetched_from_server_ps => 0
    rows_buffered_from_client_normal => 0
    rows_buffered_from_client_ps => 0
    rows_fetched_from_client_normal_buffered => 0
    rows_fetched_from_client_normal_unbuffered => 0
    rows_fetched_from_client_ps_buffered => 0
    rows_fetched_from_client_ps_unbuffered => 0
    rows_fetched_from_client_ps_cursor => 0
    rows_affected_normal => 0
    rows_affected_ps => 0
    rows_skipped_normal => 0
    rows_skipped_ps => 0
    copy_on_write_saved => 0
    copy_on_write_performed => 0
    command_buffer_too_small => 0
    connect_success => 0
    connect_failure => 0
    connection_reused => 0
    reconnect => 0
    pconnect_success => 0
    active_connections => 0
    active_persistent_connections => 0
    explicit_close => 0
    implicit_close => 0
    disconnect_close => 0
    in_middle_of_command_close => 0
    explicit_free_result => 0
    implicit_free_result => 0
    explicit_stmt_close => 0
    implicit_stmt_close => 0
    mem_emalloc_count => 0
    mem_emalloc_amount => 0
    mem_ecalloc_count => 0
    mem_ecalloc_amount => 0
    mem_erealloc_count => 0
    mem_erealloc_amount => 0
    mem_efree_count => 0
    mem_efree_amount => 0
    mem_malloc_count => 0
    mem_malloc_amount => 0
    mem_calloc_count => 0
    mem_calloc_amount => 0
    mem_realloc_count => 0
    mem_realloc_amount => 0
    mem_free_count => 0
    mem_free_amount => 0
    mem_estrndup_count => 0
    mem_strndup_count => 0
    mem_estrdup_count => 0
    mem_strdup_count => 0
    mem_edupl_count => 0
    mem_dupl_count => 0
    proto_text_fetched_null => 0
    proto_text_fetched_bit => 0
    proto_text_fetched_tinyint => 0
    proto_text_fetched_short => 0
    proto_text_fetched_int24 => 0
    proto_text_fetched_int => 0
    proto_text_fetched_bigint => 0
    proto_text_fetched_decimal => 0
    proto_text_fetched_float => 0
    proto_text_fetched_double => 0
    proto_text_fetched_date => 0
    proto_text_fetched_year => 0
    proto_text_fetched_time => 0
    proto_text_fetched_datetime => 0
    proto_text_fetched_timestamp => 0
    proto_text_fetched_string => 0
    proto_text_fetched_blob => 0
    proto_text_fetched_enum => 0
    proto_text_fetched_set => 0
    proto_text_fetched_geometry => 0
    proto_text_fetched_other => 0
    proto_binary_fetched_null => 0
    proto_binary_fetched_bit => 0
    proto_binary_fetched_tinyint => 0
    proto_binary_fetched_short => 0
    proto_binary_fetched_int24 => 0
    proto_binary_fetched_int => 0
    proto_binary_fetched_bigint => 0
    proto_binary_fetched_decimal => 0
    proto_binary_fetched_float => 0
    proto_binary_fetched_double => 0
    proto_binary_fetched_date => 0
    proto_binary_fetched_year => 0
    proto_binary_fetched_time => 0
    proto_binary_fetched_datetime => 0
    proto_binary_fetched_timestamp => 0
    proto_binary_fetched_string => 0
    proto_binary_fetched_json => 0
    proto_binary_fetched_blob => 0
    proto_binary_fetched_enum => 0
    proto_binary_fetched_set => 0
    proto_binary_fetched_geometry => 0
    proto_binary_fetched_other => 0
    init_command_executed_count => 0
    init_command_failed_count => 0
    com_quit => 0
    com_init_db => 0
    com_query => 0
    com_field_list => 0
    com_create_db => 0
    com_drop_db => 0
    com_refresh => 0
    com_shutdown => 0
    com_statistics => 0
    com_process_info => 0
    com_connect => 0
    com_process_kill => 0
    com_debug => 0
    com_ping => 0
    com_time => 0
    com_delayed_insert => 0
    com_change_user => 0
    com_binlog_dump => 0
    com_table_dump => 0
    com_connect_out => 0
    com_register_slave => 0
    com_stmt_prepare => 0
    com_stmt_execute => 0
    com_stmt_send_long_data => 0
    com_stmt_close => 0
    com_stmt_reset => 0
    com_stmt_set_option => 0
    com_stmt_fetch => 0
    com_deamon => 0
    bytes_received_real_data_normal => 0
    bytes_received_real_data_ps => 0
    
    odbc
    
    ODBC Support => enabled
    Active Persistent Links => 0
    Active Links => 0
    ODBC library => unixODBC
    ODBCVER => 0x0380
    ODBC_INCLUDE => -I/usr/local/opt/unixodbc/include
    ODBC_LFLAGS => -L/usr/local/opt/unixodbc/lib
    ODBC_LIBS => -lodbc
    
    Directive => Local Value => Master Value
    odbc.allow_persistent => On => On
    odbc.check_persistent => On => On
    odbc.default_cursortype => Static cursor => Static cursor
    odbc.default_db => no value => no value
    odbc.default_pw => no value => no value
    odbc.default_user => no value => no value
    odbc.defaultbinmode => return as is => return as is
    odbc.defaultlrl => return up to 4096 bytes => return up to 4096 bytes
    odbc.max_links => Unlimited => Unlimited
    odbc.max_persistent => Unlimited => Unlimited
    
    openssl
    
    OpenSSL support => enabled
    OpenSSL Library Version => OpenSSL 1.0.2q  20 Nov 2018
    OpenSSL Header Version => OpenSSL 1.0.2q  20 Nov 2018
    Openssl default config => /usr/local/etc/openssl/openssl.cnf
    
    Directive => Local Value => Master Value
    openssl.cafile => no value => no value
    openssl.capath => no value => no value
    
    pcntl
    
    pcntl support => enabled
    
    pcre
    
    PCRE (Perl Compatible Regular Expressions) Support => enabled
    PCRE Library Version => 10.32 2018-09-10
    PCRE Unicode Version => 11.0.0
    PCRE JIT Support => enabled
    PCRE JIT Target => x86 64bit (little endian + unaligned)
    
    Directive => Local Value => Master Value
    pcre.backtrack_limit => 1000000 => 1000000
    pcre.jit => 0 => 0
    pcre.recursion_limit => 100000 => 100000
    
    PDO
    
    PDO support => enabled
    PDO drivers => dblib, mysql, odbc, pgsql, sqlite
    
    pdo_dblib
    
    PDO Driver for FreeTDS/Sybase DB-lib => enabled
    Flavour => freetds
    
    pdo_mysql
    
    PDO Driver for MySQL => enabled
    Client API version => mysqlnd 5.0.12-dev - 20150407 - $Id: 401a40ebd5e281cf22215acdc170723a1519aaa9 $
    
    Directive => Local Value => Master Value
    pdo_mysql.default_socket => /tmp/mysql.sock => /tmp/mysql.sock
    
    PDO_ODBC
    
    PDO Driver for ODBC (unixODBC) => enabled
    ODBC Connection Pooling => Enabled, strict matching
    
    pdo_pgsql
    
    PDO Driver for PostgreSQL => enabled
    PostgreSQL(libpq) Version => 11.1
    
    pdo_sqlite
    
    PDO Driver for SQLite 3.x => enabled
    SQLite Library => 3.26.0
    
    pgsql
    
    PostgreSQL Support => enabled
    PostgreSQL(libpq) Version => 11.1
    PostgreSQL(libpq)  => PostgreSQL 11.1 on x86_64-apple-darwin15.6.0, compiled by Apple LLVM version 8.0.0 (clang-800.0.42.1), 64-bit
    Multibyte character support => enabled
    SSL support => enabled
    Active Persistent Links => 0
    Active Links => 0
    
    Directive => Local Value => Master Value
    pgsql.allow_persistent => On => On
    pgsql.auto_reset_persistent => Off => Off
    pgsql.ignore_notice => Off => Off
    pgsql.log_notice => Off => Off
    pgsql.max_links => Unlimited => Unlimited
    pgsql.max_persistent => Unlimited => Unlimited
    
    Phar
    
    Phar: PHP Archive support => enabled
    Phar API version => 1.1.1
    Phar-based phar archives => enabled
    Tar-based phar archives => enabled
    ZIP-based phar archives => enabled
    gzip compression => enabled
    bzip2 compression => enabled
    OpenSSL support => enabled
    
    
    Phar based on pear/PHP_Archive, original concept by Davey Shafik.
    Phar fully realized by Gregory Beaver and Marcus Boerger.
    Portions of tar implementation Copyright (c) 2003-2009 Tim Kientzle.
    Directive => Local Value => Master Value
    phar.cache_list => no value => no value
    phar.readonly => On => On
    phar.require_hash => On => On
    
    phpdbg_webhelper
    
    Version => 0.5.0
    
    Directive => Local Value => Master Value
    phpdbg.auth => no value => no value
    phpdbg.path => no value => no value
    
    posix
    
    POSIX support => enabled
    
    pspell
    
    PSpell Support => enabled
    
    readline
    
    Readline Support => enabled
    Readline library => EditLine wrapper
    
    Directive => Local Value => Master Value
    cli.pager => no value => no value
    cli.prompt => \b \>  => \b \> 
    
    Reflection
    
    Reflection => enabled
    
    session
    
    Session Support => enabled
    Registered save handlers => files user 
    Registered serializer handlers => php_serialize php php_binary wddx 
    
    Directive => Local Value => Master Value
    session.auto_start => Off => Off
    session.cache_expire => 180 => 180
    session.cache_limiter => nocache => nocache
    session.cookie_domain => no value => no value
    session.cookie_httponly => no value => no value
    session.cookie_lifetime => 0 => 0
    session.cookie_path => / => /
    session.cookie_samesite => no value => no value
    session.cookie_secure => 0 => 0
    session.gc_divisor => 1000 => 1000
    session.gc_maxlifetime => 1440 => 1440
    session.gc_probability => 1 => 1
    session.lazy_write => On => On
    session.name => PHPSESSID => PHPSESSID
    session.referer_check => no value => no value
    session.save_handler => files => files
    session.save_path => no value => no value
    session.serialize_handler => php => php
    session.sid_bits_per_character => 5 => 5
    session.sid_length => 26 => 26
    session.upload_progress.cleanup => On => On
    session.upload_progress.enabled => On => On
    session.upload_progress.freq => 1% => 1%
    session.upload_progress.min_freq => 1 => 1
    session.upload_progress.name => PHP_SESSION_UPLOAD_PROGRESS => PHP_SESSION_UPLOAD_PROGRESS
    session.upload_progress.prefix => upload_progress_ => upload_progress_
    session.use_cookies => 1 => 1
    session.use_only_cookies => 1 => 1
    session.use_strict_mode => 0 => 0
    session.use_trans_sid => 0 => 0
    
    shmop
    
    shmop support => enabled
    
    SimpleXML
    
    SimpleXML support => enabled
    Schema support => enabled
    
    soap
    
    Soap Client => enabled
    Soap Server => enabled
    
    Directive => Local Value => Master Value
    soap.wsdl_cache => 1 => 1
    soap.wsdl_cache_dir => /tmp => /tmp
    soap.wsdl_cache_enabled => 1 => 1
    soap.wsdl_cache_limit => 5 => 5
    soap.wsdl_cache_ttl => 86400 => 86400
    
    sockets
    
    Sockets Support => enabled
    
    sodium
    
    sodium support => enabled
    libsodium headers version => 1.0.16
    libsodium library version => 1.0.16
    
    SPL
    
    SPL support => enabled
    Interfaces => OuterIterator, RecursiveIterator, SeekableIterator, SplObserver, SplSubject
    Classes => AppendIterator, ArrayIterator, ArrayObject, BadFunctionCallException, BadMethodCallException, CachingIterator, CallbackFilterIterator, DirectoryIterator, DomainException, EmptyIterator, FilesystemIterator, FilterIterator, GlobIterator, InfiniteIterator, InvalidArgumentException, IteratorIterator, LengthException, LimitIterator, LogicException, MultipleIterator, NoRewindIterator, OutOfBoundsException, OutOfRangeException, OverflowException, ParentIterator, RangeException, RecursiveArrayIterator, RecursiveCachingIterator, RecursiveCallbackFilterIterator, RecursiveDirectoryIterator, RecursiveFilterIterator, RecursiveIteratorIterator, RecursiveRegexIterator, RecursiveTreeIterator, RegexIterator, RuntimeException, SplDoublyLinkedList, SplFileInfo, SplFileObject, SplFixedArray, SplHeap, SplMinHeap, SplMaxHeap, SplObjectStorage, SplPriorityQueue, SplQueue, SplStack, SplTempFileObject, UnderflowException, UnexpectedValueException
    
    sqlite3
    
    SQLite3 support => enabled
    SQLite Library => 3.26.0
    
    Directive => Local Value => Master Value
    sqlite3.extension_dir => no value => no value
    
    standard
    
    Dynamic Library Support => enabled
    Path to sendmail => /usr/sbin/sendmail -t -i 
    
    Directive => Local Value => Master Value
    assert.active => 1 => 1
    assert.bail => 0 => 0
    assert.callback => no value => no value
    assert.exception => 0 => 0
    assert.quiet_eval => 0 => 0
    assert.warning => 1 => 1
    auto_detect_line_endings => 0 => 0
    default_socket_timeout => 60 => 60
    from => no value => no value
    session.trans_sid_hosts => no value => no value
    session.trans_sid_tags => a=href,area=href,frame=src,form= => a=href,area=href,frame=src,form=
    url_rewriter.hosts => no value => no value
    url_rewriter.tags => form= => form=
    user_agent => no value => no value
    
    sysvmsg
    
    sysvmsg support => enabled
    
    sysvsem
    
    sysvsem support => enabled
    
    sysvshm
    
    sysvshm support => enabled
    
    tidy
    
    Tidy support => enabled
    libTidy Version => 5.6.0
    libTidy Release => 2017/11/25
    
    Directive => Local Value => Master Value
    tidy.clean_output => no value => no value
    tidy.default_config => no value => no value
    
    tokenizer
    
    Tokenizer Support => enabled
    
    wddx
    
    WDDX Support => enabled
    WDDX Session Serializer => enabled
    
    xdebug
    
    xdebug support => enabled
    Version => 2.7.0beta1
    IDE Key => shaunbramley
    
    Supported protocols
    DBGp - Common DeBuGger Protocol
    
    Directive => Local Value => Master Value
    xdebug.auto_trace => Off => Off
    xdebug.cli_color => 0 => 0
    xdebug.collect_assignments => Off => Off
    xdebug.collect_includes => On => On
    xdebug.collect_params => 0 => 0
    xdebug.collect_return => Off => Off
    xdebug.collect_vars => Off => Off
    xdebug.coverage_enable => On => On
    xdebug.default_enable => On => On
    xdebug.dump.COOKIE => no value => no value
    xdebug.dump.ENV => no value => no value
    xdebug.dump.FILES => no value => no value
    xdebug.dump.GET => no value => no value
    xdebug.dump.POST => no value => no value
    xdebug.dump.REQUEST => no value => no value
    xdebug.dump.SERVER => no value => no value
    xdebug.dump.SESSION => no value => no value
    xdebug.dump_globals => On => On
    xdebug.dump_once => On => On
    xdebug.dump_undefined => Off => Off
    xdebug.extended_info => On => On
    xdebug.file_link_format => no value => no value
    xdebug.filename_format => no value => no value
    xdebug.force_display_errors => Off => Off
    xdebug.force_error_reporting => 0 => 0
    xdebug.gc_stats_enable => Off => Off
    xdebug.gc_stats_output_dir => /var/tmp/ => /var/tmp/
    xdebug.gc_stats_output_name => gcstats.%p => gcstats.%p
    xdebug.halt_level => 0 => 0
    xdebug.idekey => no value => no value
    xdebug.max_nesting_level => 256 => 256
    xdebug.max_stack_frames => -1 => -1
    xdebug.overload_var_dump => 2 => 2
    xdebug.profiler_aggregate => Off => Off
    xdebug.profiler_append => Off => Off
    xdebug.profiler_enable => Off => Off
    xdebug.profiler_enable_trigger => Off => Off
    xdebug.profiler_enable_trigger_value => no value => no value
    xdebug.profiler_output_dir => /var/tmp/ => /var/tmp/
    xdebug.profiler_output_name => cachegrind.out.%p => cachegrind.out.%p
    xdebug.remote_addr_header => no value => no value
    xdebug.remote_autostart => Off => Off
    xdebug.remote_connect_back => Off => Off
    xdebug.remote_cookie_expire_time => 3600 => 3600
    xdebug.remote_enable => Off => Off
    xdebug.remote_handler => dbgp => dbgp
    xdebug.remote_host => localhost => localhost
    xdebug.remote_log => no value => no value
    xdebug.remote_mode => req => req
    xdebug.remote_port => 9000 => 9000
    xdebug.remote_timeout => 200 => 200
    xdebug.scream => Off => Off
    xdebug.show_error_trace => Off => Off
    xdebug.show_exception_trace => Off => Off
    xdebug.show_local_vars => Off => Off
    xdebug.show_mem_delta => Off => Off
    xdebug.trace_enable_trigger => Off => Off
    xdebug.trace_enable_trigger_value => no value => no value
    xdebug.trace_format => 0 => 0
    xdebug.trace_options => 0 => 0
    xdebug.trace_output_dir => /var/tmp/ => /var/tmp/
    xdebug.trace_output_name => trace.%c => trace.%c
    xdebug.var_display_max_children => 128 => 128
    xdebug.var_display_max_data => 512 => 512
    xdebug.var_display_max_depth => 3 => 3
    
    xml
    
    XML Support => active
    XML Namespace Support => active
    libxml2 Version => 2.9.4
    
    xmlreader
    
    XMLReader => enabled
    
    xmlrpc
    
    core library version => xmlrpc-epi v. 0.51
    author => Dan Libby
    homepage => http://xmlrpc-epi.sourceforge.net
    open sourced by => Epinions.com
    
    xmlwriter
    
    XMLWriter => enabled
    
    xsl
    
    XSL => enabled
    libxslt Version => 1.1.29
    libxslt compiled against libxml Version => 2.9.4
    EXSLT => enabled
    libexslt Version => 1.1.28
    
    Zend OPcache
    
    Opcode Caching => Disabled
    Optimization => Disabled
    SHM Cache => Enabled
    File Cache => Disabled
    Startup Failed => Opcode Caching is disabled for CLI
    
    Directive => Local Value => Master Value
    opcache.blacklist_filename => no value => no value
    opcache.consistency_checks => 0 => 0
    opcache.dups_fix => Off => Off
    opcache.enable => On => On
    opcache.enable_cli => Off => Off
    opcache.enable_file_override => Off => Off
    opcache.error_log => no value => no value
    opcache.file_cache => no value => no value
    opcache.file_cache_consistency_checks => 1 => 1
    opcache.file_cache_only => 0 => 0
    opcache.file_update_protection => 2 => 2
    opcache.force_restart_timeout => 180 => 180
    opcache.huge_code_pages => Off => Off
    opcache.interned_strings_buffer => 8 => 8
    opcache.lockfile_path => /tmp => /tmp
    opcache.log_verbosity_level => 1 => 1
    opcache.max_accelerated_files => 10000 => 10000
    opcache.max_file_size => 0 => 0
    opcache.max_wasted_percentage => 5 => 5
    opcache.memory_consumption => 128 => 128
    opcache.opt_debug_level => 0 => 0
    opcache.optimization_level => 0x7FFEBFFF => 0x7FFEBFFF
    opcache.preferred_memory_model => no value => no value
    opcache.protect_memory => 0 => 0
    opcache.restrict_api => no value => no value
    opcache.revalidate_freq => 2 => 2
    opcache.revalidate_path => Off => Off
    opcache.save_comments => 1 => 1
    opcache.use_cwd => On => On
    opcache.validate_permission => Off => Off
    opcache.validate_root => Off => Off
    opcache.validate_timestamps => On => On
    
    zip
    
    Zip => enabled
    Zip version => 1.15.4
    Libzip headers version => 1.5.1
    Libzip library version => 1.5.1
    
    zlib
    
    ZLib Support => enabled
    Stream Wrapper => compress.zlib://
    Stream Filter => zlib.inflate, zlib.deflate
    Compiled Version => 1.2.5
    Linked Version => 1.2.11
    
    Directive => Local Value => Master Value
    zlib.output_compression => Off => Off
    zlib.output_compression_level => -1 => -1
    zlib.output_handler => no value => no value
    
    Additional Modules
    
    Module Name
    
    Environment
    
    Variable => Value
    TERM_PROGRAM => Apple_Terminal
    SHELL => /bin/bash
    TERM => xterm-256color
    TMPDIR => /var/folders/v8/41y8snyn5qq_3fqjs1r3sfr80000gn/T/
    Apple_PubSub_Socket_Render => /private/tmp/com.apple.launchd.ZMSMH9QFlL/Render
    TERM_PROGRAM_VERSION => 404.1
    TERM_SESSION_ID => 3812EB85-0EEC-4D0B-8B16-DD870789A2CF
    USER => shaunbramley
    SSH_AUTH_SOCK => /private/tmp/com.apple.launchd.RKPyZFaT1C/Listeners
    PATH => /usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
    PWD => /Users/shaunbramley/phpstormprojects/untitled1
    LANG => en_CA.UTF-8
    XPC_FLAGS => 0x0
    XPC_SERVICE_NAME => 0
    SHLVL => 1
    HOME => /Users/shaunbramley
    LOGNAME => shaunbramley
    _ => /usr/local/bin/php
    OLDPWD => /Users/shaunbramley
    __CF_USER_TEXT_ENCODING => 0x1F5:0x0:0x52
    
    PHP Variables
    
    Variable => Value
    $_SERVER['TERM_PROGRAM'] => Apple_Terminal
    $_SERVER['SHELL'] => /bin/bash
    $_SERVER['TERM'] => xterm-256color
    $_SERVER['TMPDIR'] => /var/folders/v8/41y8snyn5qq_3fqjs1r3sfr80000gn/T/
    $_SERVER['Apple_PubSub_Socket_Render'] => /private/tmp/com.apple.launchd.ZMSMH9QFlL/Render
    $_SERVER['TERM_PROGRAM_VERSION'] => 404.1
    $_SERVER['TERM_SESSION_ID'] => 3812EB85-0EEC-4D0B-8B16-DD870789A2CF
    $_SERVER['USER'] => shaunbramley
    $_SERVER['SSH_AUTH_SOCK'] => /private/tmp/com.apple.launchd.RKPyZFaT1C/Listeners
    $_SERVER['PATH'] => /usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
    $_SERVER['PWD'] => /Users/shaunbramley/phpstormprojects/untitled1
    $_SERVER['LANG'] => en_CA.UTF-8
    $_SERVER['XPC_FLAGS'] => 0x0
    $_SERVER['XPC_SERVICE_NAME'] => 0
    $_SERVER['SHLVL'] => 1
    $_SERVER['HOME'] => /Users/shaunbramley
    $_SERVER['LOGNAME'] => shaunbramley
    $_SERVER['_'] => /usr/local/bin/php
    $_SERVER['OLDPWD'] => /Users/shaunbramley
    $_SERVER['__CF_USER_TEXT_ENCODING'] => 0x1F5:0x0:0x52
    $_SERVER['PHP_SELF'] => 
    $_SERVER['SCRIPT_NAME'] => 
    $_SERVER['SCRIPT_FILENAME'] => 
    $_SERVER['PATH_TRANSLATED'] => 
    $_SERVER['DOCUMENT_ROOT'] => 
    $_SERVER['REQUEST_TIME_FLOAT'] => 1546649389.1847
    $_SERVER['REQUEST_TIME'] => 1546649389
    $_SERVER['argv'] => Array
    (
    )
    
    $_SERVER['argc'] => 0
    
    PHP License
    This program is free software; you can redistribute it and/or modify
    it under the terms of the PHP License as published by the PHP Group
    and included in the distribution in the file:  LICENSE
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    If you did not receive a copy of the PHP license, or have any
    questions about PHP licensing, please contact [email protected].
    Shauns-MacBook-Air:untitled1 shaunbramley$ 
    
    opened by shaunbramley 8
  • `forkJoin` does not work as I expected

    `forkJoin` does not work as I expected

    Using RxPHP version 2.0.2 with PHP 7.1.7 (on Windows 10, on OSX El Capitan and on Ubuntu 17.04). The behavior is the same on every platform, with an immediate scheduler or with the React event loop.

    When I try to run the forkJoin demo :

    $ php forkJoin.php
    Next value: 47c
    Complete!
    

    But when looking at the code, the next value should be: 45c (e.g. the 7 value is not the last one produced by $obs2... in fact 7 is not produced at all by any observable).

    $obs1 = Observable::range(1, 4);
    $obs2 = Observable::range(3, 5);
    $obs3 = Observable::fromArray(['a', 'b', 'c']);
    

    When using forkJoin in my own code :

    $obs1 = <an observable that produces a single `Job` instance>;
    $obs2 = <an observable that produces a single `Configuration` instance>;
    $obs3 = <an observable that produces a single `GitData` instance>;
    
    Observable::forkjoin([$obs1, $obs2, $obs3], function($v1, $v2, $v3) {
      echo '$v1 = ', get_class($v1), PHP_EOL;
      echo '$v2 = ', get_class($v2), PHP_EOL;
      echo '$v3 = ', get_class($v3), PHP_EOL;
    })->subscribe(...);
    

    The output I get is not in the expected order (and it is the same even if I change the scheduler):

    $v1 = Configuration
    $v2 = Job
    $v3 = GitData
    

    I'm starting with the Observables: have I misinterpreted what forkJoin should produce, have I missed something? Thanks in advance.

    opened by cedx 7
  • Autostart the scheduler

    Autostart the scheduler

    This issue is to discuss using register_shutdown_function to automatically start the loop. This would be done bootstrap.php and set within require in composer.json, like this:

    register_shutdown_function(function () {
        Loop::execute(function () {}, Loop::get());
    });
    

    Pros:

    1. Users will not need to wrap their code in Loop::execute.
    2. Currently, if someone tries using operators and forgets to wrap them, the program will exit and nothing will happen. By using register shutdown, everything that has been sent to the loop before the program exists, will run.
    3. It hides more of the internal plumbing, that shouldn't matter to most users

    Cons:

    ???

    opened by mbonneau 7
  • Not getting any output in the console

    Not getting any output in the console

    Hello. I cannot get any output in my console except for when I use the var_dump() on the Observable object which returns object attributes. This is what my script looks like:

    <?php
    
    require __DIR__ . '/vendor/autoload.php';
    
    use Rx\{Scheduler, Observable};
    use React\EventLoop\Factory;
    
    $loop = Factory::create();
    
    Scheduler::setDefaultFactory(
        function () use ($loop) {
            return new Scheduler\EventLoopScheduler($loop);
        }
    );
    
    function stdOutObserver() {
        return new Rx\Observer\CallbackObserver(
            function ($value) {
                print("Next value " . $value . PHP_EOL);
            },
            function (Exception $ex) {
                print("Exception " . $ex->getMessage() . PHP_EOL);
            },
            function () {
                print("Done!" . PHP_EOL);
            }
        );
    }
    
    $numbers = [1, 2, 3, 4];
    
    $source = Observable::fromArray($numbers)
        ->map(
            function ($value) {
                if ($value === 3) {
                    throw new Exception('Number error');
                }
                return $value; 
            }
        );
    
    $source->subscribe('stdOutObserver');
    

    My console looks like this:

    functional-lib-issues

    question 
    opened by ace411 6
  • Handling streams

    Handling streams

    Hello, Is there any simple way to instantiate an observer from a resource ? I was hoping to use rxphp to handle huge data without too much memory footprint

    question 
    opened by DGCarramona 1
  • Take operator doesn't dispose upstream observable

    Take operator doesn't dispose upstream observable

    If there is an active polling observable upstream it will keep polling as long as it isn't disposed. By disposing when we reach the desired amount of items, the possible upstream polling is also stopped.

    opened by WyriHaximus 9
  • Implement mergeDelayError

    Implement mergeDelayError

    Implement #205.

    Items in this PR that may need discussion are what to do about errors occurring on multiple observables and whether this should be implemented as a mergeAll type operator that merges a sequence of observables.

    The the multiple error issue: it looks like the Java flavored Rx implementations use a CompositeException that gets emitted onError. We could implement a similar functionality.

    opened by mbonneau 2
  • [WIP] Higher-Order Marble tests

    [WIP] Higher-Order Marble tests

    I cherry picked the higher-order test code from v1 so we can start working on getting higher-order marble tests working.

    Some tests are failing.
    @martinsik if you get a chance, can you look at the failing tests?

    opened by davidwdan 7
Releases(2.0.11)
Owner
ReactiveX
Reactive Extensions for Async Programming
ReactiveX
An asynchronous event driven PHP socket framework. Supports HTTP, Websocket, SSL and other custom protocols. PHP>=5.3.

Workerman What is it Workerman is an asynchronous event-driven PHP framework with high performance to build fast and scalable network applications. Wo

walkor 10.2k Jan 4, 2023
Event-driven, non-blocking I/O with PHP.

Event-driven, non-blocking I/O with PHP. ReactPHP is a low-level library for event-driven programming in PHP. At its core is an event loop, on top of

ReactPHP 8.5k Jan 8, 2023
A non-blocking concurrency framework for PHP applications. 🐘

Amp is a non-blocking concurrency framework for PHP. It provides an event loop, promises and streams as a base for asynchronous programming. Promises

Amp 3.8k Jan 6, 2023
Icicle is a PHP library for writing asynchronous code using synchronous coding techniques

Icicle is now deprecated in favor of Amp v2.0. This version is is currently under development, but close to release. The v2.0 branches are amp_v2 in a

icicle.io 1.1k Dec 21, 2022
Événement is a very simple event dispatching library for PHP.

Événement Événement is a very simple event dispatching library for PHP. It has the same design goals as Silex and Pimple, to empower the user while st

Igor 1.2k Jan 4, 2023
Asynchronous coroutines for PHP 7.

Recoil An asynchronous coroutine kernel for PHP 7. composer require recoil/recoil The Recoil project comprises the following packages: recoil/api - T

Recoil 787 Dec 8, 2022
A pragmatic event sourcing library for PHP with a focus on developer experience.

EventSaucePHP EventSauce is a somewhat opinionated, no-nonsense, and easy way to introduce event sourcing into PHP projects. It's designed so storage

EventSauce 685 Dec 31, 2022
PHP 7.4 EventStore Implementation

Prooph Event Store Common classes and interface for Prooph Event Store implementations. Installation You can install prooph/event-store via composer b

null 532 Dec 9, 2022
Golang's defer statement for PHP

PHP Defer A defer statement originally comes from Golang. This library allows you to use defer functionality in PHP code. Usage <?php defer($context,

null 249 Dec 31, 2022
🚀 Coroutine-based concurrency library for PHP

English | 中文 Swoole is an event-driven asynchronous & coroutine-based concurrency networking communication engine with high performance written in C++

Swoole Project 17.7k Jan 5, 2023
PHP Application using DDD CQRS Event Sourcing with Hexagonal Architecture

PHP Application using DDD CQRS Event Sourcing with Hexagonal Architecture Application built with Ecotone Framework and powered by integrations with Pr

EcotoneFramework 65 Dec 27, 2022
Revolt is a rock-solid event loop for concurrent PHP applications.

Revolt is a rock-solid event loop for concurrent PHP applications.

Revolt PHP 586 Jan 2, 2023
Reactive extensions for PHP

RxPHP Reactive extensions for PHP. The reactive extensions for PHP are a set of libraries to compose asynchronous and event-based programs using obser

ReactiveX 1.6k Dec 12, 2022
A magic PHP framework. Build reactive web apps without writing HTML, CSS, or JavaScript! Powered by Tailwind, Alpine, Laravel, & Livewire.

Malzahar A magic PHP framework. Build reactive web apps without writing HTML, CSS, or JavaScript! Powered by Tailwind, Alpine, Laravel, & Livewire. Re

null 26 Nov 17, 2022
Viewi for Laravel: Build full-stack and completely reactive user interfaces with PHP.

[WIP] Laravel Viewi This is just a proof-of-concept. Don't use it in production! Viewi for Laravel: Build full-stack and completely reactive user inte

Protone Media 5 Jan 26, 2022
Reactive Form Builder for Vue.js with Laravel Support

Dynamic Form Builder for Laravel with Vue.js Create even the most complex forms with ease, using two-sided validation, eloquent, nested elements, cond

Laraform 340 Dec 31, 2022
Framework X – the simple and fast micro framework for building reactive web applications that run anywhere.

Framework X Framework X – the simple and fast micro framework for building reactive web applications that run anywhere. Quickstart Documentation Tests

Christian Lück 620 Jan 7, 2023
GitHub action to setup PHP with required extensions, php.ini configuration, code-coverage support and various tools like composer...

Setup PHP in GitHub Actions Setup PHP with required extensions, php.ini configuration, code-coverage support and various tools like composer in GitHub

Shivam Mathur 2.4k Jan 6, 2023
GitHub action to setup PHP with required extensions, php.ini configuration, code-coverage support and various tools like composer...

Setup PHP in GitHub Actions Setup PHP with required extensions, php.ini configuration, code-coverage support and various tools like composer in GitHub

Shivam Mathur 2.4k Jan 6, 2023
True asynchronous PHP I/O and HTTP without frameworks, extensions, or annoying code. Uses the accepted Fibers RFC to be implemented into PHP 8.1

PHP Fibers - Async Examples Without External Dependencies True asynchronous PHP I/O and HTTP without frameworks, extensions, or annoying code behemoth

Cole Green 121 Jan 6, 2023