SkillAgentSearch skills...

Mysql

Async MySQL database client for ReactPHP.

Install / Use

/learn @friends-of-reactphp/Mysql
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

MySQL

CI status

Async MySQL database client for ReactPHP.

Development version: This branch contains the code for the upcoming version 0.7 release. For the code of the current stable version 0.6 release, check out the 0.6.x branch.

The upcoming version 0.7 release will be the way forward for this package. However, we will still actively support version 0.6 for those not yet on the latest version. See also installation instructions for more details.

This is a MySQL database driver for ReactPHP. It implements the MySQL protocol and allows you to access your existing MySQL database. It is written in pure PHP and does not require any extensions.

Table of contents

Quickstart example

This example runs a simple SELECT query and dumps all the records from a book table:

<?php

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

$mysql = new React\Mysql\MysqlClient('user:pass@localhost/bookstore');

$mysql->query('SELECT * FROM book')->then(
    function (React\Mysql\MysqlResult $command) {
        print_r($command->resultFields);
        print_r($command->resultRows);
        echo count($command->resultRows) . ' row(s) in set' . PHP_EOL;
    },
    function (Exception $error) {
        echo 'Error: ' . $error->getMessage() . PHP_EOL;
    }
);

See also the examples.

Usage

MysqlClient

The MysqlClient is responsible for exchanging messages with your MySQL server and keeps track of pending queries.

$mysql = new React\Mysql\MysqlClient($uri);

$mysql->query(…);

This class represents a connection that is responsible for communicating with your MySQL server instance, managing the connection state and sending your database queries. Internally, it creates the underlying database connection only on demand once the first request is invoked on this instance and will queue all outstanding requests until the underlying connection is ready. This underlying connection will be reused for all requests until it is closed. By default, idle connections will be held open for 1ms (0.001s) when not used. The next request will either reuse the existing connection or will automatically create a new underlying connection if this idle time is expired.

From a consumer side this means that you can start sending queries to the database right away while the underlying connection may still be outstanding. Because creating this underlying connection may take some time, it will enqueue all outstanding commands and will ensure that all commands will be executed in correct order once the connection is ready.

If the underlying database connection fails, it will reject all outstanding commands and will return to the initial "idle" state. This means that you can keep sending additional commands at a later time which will again try to open a new underlying connection. Note that this may require special care if you're using transactions that are kept open for longer than the idle period.

Note that creating the underlying connection will be deferred until the first request is invoked. Accordingly, any eventual connection issues will be detected once this instance is first used. You can use the quit() method to ensure that the connection will be soft-closed and no further commands can be enqueued. Similarly, calling quit() on this instance when not currently connected will succeed immediately and will not have to wait for an actual underlying connection.

__construct()

The new MysqlClient(string $uri, ?ConnectorInterface $connector = null, ?LoopInterface $loop = null) constructor can be used to create a new MysqlClient instance.

The $uri parameter must contain the database host, optional authentication, port and database to connect to:

$mysql = new React\Mysql\MysqlClient('user:secret@localhost:3306/database');

Note that both the username and password must be URL-encoded (percent-encoded) if they contain special characters:

$user = 'he:llo';
$pass = 'p@ss';

$mysql = new React\Mysql\MysqlClient(
    rawurlencode($user) . ':' . rawurlencode($pass) . '@localhost:3306/db'
);

You can omit the port if you're connecting to default port 3306:

$mysql = new React\Mysql\MysqlClient('user:secret@localhost/database');

If you do not include authentication and/or database, then this method will default to trying to connect as user root with an empty password and no database selected. This may be useful when initially setting up a database, but likely to yield an authentication error in a production system:

$mysql = new React\Mysql\MysqlClient('localhost');

This method respects PHP's default_socket_timeout setting (default 60s) as a timeout for establishing the underlying connection and waiting for successful authentication. You can explicitly pass a custom timeout value in seconds (or use a negative number to not apply a timeout) like this:

$mysql = new React\Mysql\MysqlClient('localhost?timeout=0.5');

By default, idle connections will be held open for 1ms (0.001s) when not used. The next request will either reuse the existing connection or will automatically create a new underlying connection if this idle time is expired. This ensures you always get a "fresh" connection and as such should not be confused with a "keepalive" or "heartbeat" mechanism, as this will not actively try to probe the connection. You can explicitly pass a custom idle timeout value in seconds (or use a negative number to not apply a timeout) like this:

$mysql = new React\Mysql\MysqlClient('localhost?idle=10.0');

By default, the connection provides full UTF-8 support (using the utf8mb4 charset encoding). This should usually not be changed for most applications nowadays, but for legacy reasons you can change this to use a different ASCII-compatible charset encoding like this:

$mysql = new React\Mysql\MysqlClient('localhost?charset=utf8mb4');

If you need custom connector settings (DNS resolution, TLS parameters, timeouts, proxy servers etc.), you can explicitly pass a custom instance of the ConnectorInterface:

$connector = new React\Socket\Connector([
    'dns' => '127.0.0.1',
    'tcp' => [
        'bindto' => '192.168.10.1:0'
    ],
    'tls' => [
        'verify_peer' => false,
        'verify_peer_name' => false
    )
]);

$mysql = new React\Mysql\MysqlClient('user:secret@localhost:3306/database', $connector);

This class takes an optional LoopInterface|null $loop parameter that can be used to pass the event loop instance to use for this object. You can use a null value here in order to use the default loop. This value SHOULD NOT be given unless you're sure you want to explicitly use a given event loop instance.

query()

The query(string $query, list<string|int|float|bool|null> $params = []): PromiseInterface<MysqlResult> method can be used to perform an async query.

This method returns a promise that will resolve with a MysqlResult on success or will reject with an Exception on error. The MySQL protocol is inherently sequential, so that all queries will be performed in order and outstanding queries will be put into a queue to be executed once the previous queries are completed.

$mysql->query('CREATE TABLE test ...');
$mysql->query('INSERT INTO test (id) VALUES (1)');

If this SQL statement returns a result set (such as from a SELECT statement), this method will buffer everything in memory until the result set is completed and will then resolve the resulting promise. This is the preferred method if you know your result set to not exceed a few dozens or hundreds of rows. If the size of your result set is either unknown or known to be too large to fit into memory, you should use the queryStream() method instead.

$mysql->query($query)->then(function (React\Mysql\MysqlResult $command) {
    if (isset($command->resultRows)) {
        // this is a response to a SELECT etc. with some rows (0+)
        print_r($command->resultFields);
        print_r($command->resultRows);
        echo count($command->resultRows) . ' row(s) in set' . PHP_EOL;
    } else {
        // this is an OK message in response to an UPDATE etc.
        if ($command->insertId !== 0) {
            var_dump('last insert ID', $command->insertId);
        }
        echo 'Query OK, ' . $command->affectedRows . ' row(s) affected' . PHP_EOL;
    }
}, function (Exception $error) {
    // the query was not executed successfully
    echo 'Error: ' . $error->getMessage() . PHP_EOL;
});

You can optionally pass an array of $params that will be bound to the query like this:

$mysql->query('SELECT * FROM user WHERE id > ?', [$id]);

The given $sql parameter MUST contain a single statement. Support for multiple statements is disabled for security reasons because it could allow for possible SQL injection attacks and this API is not suited for exposing multiple possible results.

queryStream()

The queryStream(string $sql, list<string|int|float|bool|null> $params = []): ReadableStreamInterface method can be used to perform an async query and stream the rows of the result set.

This method returns a readable stream that wil

View on GitHub
GitHub Stars337
CategoryData
Updated1mo ago
Forks69

Languages

PHP

Security Score

95/100

Audited on Feb 21, 2026

No findings