From 75c4e4f97bf0ed433a197510335328f985ca741d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Tue, 13 Jul 2021 09:03:25 +0200 Subject: [PATCH] Simplify usage by supporting new default loop --- README.md | 21 +++++++++++---------- composer.json | 4 ++-- examples/01-query.php | 5 +---- examples/02-query-stream.php | 5 +---- examples/11-interactive.php | 7 ++----- examples/12-slow-stream.php | 16 +++++++--------- src/Factory.php | 32 ++++++++++++++++++-------------- tests/FactoryTest.php | 11 +++++++++++ 8 files changed, 53 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 721a62d..9f1a9fc 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,7 @@ It is written in pure PHP and does not require any extensions. This example runs a simple `SELECT` query and dumps all the records from a `book` table: ```php -$loop = React\EventLoop\Factory::create(); -$factory = new Factory($loop); +$factory = new React\MySQL\Factory(); $uri = 'test:test@localhost/test'; $connection = $factory->createLazyConnection($uri); @@ -51,8 +50,6 @@ $connection->query('SELECT * FROM book')->then( ); $connection->quit(); - -$loop->run(); ``` See also the [examples](examples). @@ -62,19 +59,23 @@ See also the [examples](examples). ### Factory The `Factory` is responsible for creating your [`ConnectionInterface`](#connectioninterface) instance. -It also registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage). ```php -$loop = \React\EventLoop\Factory::create(); -$factory = new Factory($loop); +$factory = new React\MySQL\Factory(); ``` +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](https://github.com/reactphp/event-loop#loop). +This value SHOULD NOT be given unless you're sure you want to explicitly use a +given event loop instance. + If you need custom connector settings (DNS resolution, TLS parameters, timeouts, proxy servers etc.), you can explicitly pass a custom instance of the [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface): ```php -$connector = new \React\Socket\Connector($loop, array( +$connector = new React\Socket\Connector(null, array( 'dns' => '127.0.0.1', 'tcp' => array( 'bindto' => '192.168.10.1:0' @@ -85,7 +86,7 @@ $connector = new \React\Socket\Connector($loop, array( ) )); -$factory = new Factory($loop, $connector); +$factory = new React\MySQL\Factory(null, $connector); ``` #### createConnection() @@ -120,7 +121,7 @@ connection attempt and/or MySQL authentication. ```php $promise = $factory->createConnection($url); -$loop->addTimer(3.0, function () use ($promise) { +Loop::addTimer(3.0, function () use ($promise) { $promise->cancel(); }); ``` diff --git a/composer.json b/composer.json index 1c509d6..a539930 100644 --- a/composer.json +++ b/composer.json @@ -6,11 +6,11 @@ "require": { "php": ">=5.4.0", "evenement/evenement": "^3.0 || ^2.1 || ^1.1", - "react/event-loop": "^1.0 || ^0.5", + "react/event-loop": "^1.2", "react/promise": "^2.7", "react/promise-stream": "^1.1", "react/promise-timer": "^1.5", - "react/socket": "^1.1" + "react/socket": "^1.8" }, "require-dev": { "clue/block-react": "^1.2", diff --git a/examples/01-query.php b/examples/01-query.php index 0ae6a16..1ce8ea6 100644 --- a/examples/01-query.php +++ b/examples/01-query.php @@ -5,8 +5,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$factory = new Factory($loop); +$factory = new Factory(); $uri = 'test:test@localhost/test'; $query = isset($argv[1]) ? $argv[1] : 'select * from book'; @@ -33,5 +32,3 @@ }); $connection->quit(); - -$loop->run(); diff --git a/examples/02-query-stream.php b/examples/02-query-stream.php index dfc2d9f..101175e 100644 --- a/examples/02-query-stream.php +++ b/examples/02-query-stream.php @@ -6,8 +6,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$factory = new Factory($loop); +$factory = new Factory(); $uri = 'test:test@localhost/test'; $query = isset($argv[1]) ? $argv[1] : 'select * from book'; @@ -30,5 +29,3 @@ }); $connection->quit(); - -$loop->run(); diff --git a/examples/11-interactive.php b/examples/11-interactive.php index fae883b..459b780 100644 --- a/examples/11-interactive.php +++ b/examples/11-interactive.php @@ -7,13 +7,12 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$factory = new Factory($loop); +$factory = new Factory(); $uri = 'test:test@localhost/test'; // open a STDIN stream to read keyboard input (not supported on Windows) -$stdin = new ReadableResourceStream(STDIN, $loop); +$stdin = new ReadableResourceStream(STDIN); $stdin->pause(); //create a mysql connection for executing queries @@ -86,5 +85,3 @@ echo 'Connection error: ' . $e->getMessage() . PHP_EOL; $stdin->close(); }); - -$loop->run(); diff --git a/examples/12-slow-stream.php b/examples/12-slow-stream.php index 98fd3f9..097ea97 100644 --- a/examples/12-slow-stream.php +++ b/examples/12-slow-stream.php @@ -2,19 +2,19 @@ // $ php examples/12-slow-stream.php "SHOW VARIABLES" +use React\EventLoop\Loop; use React\MySQL\ConnectionInterface; use React\MySQL\Factory; require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$factory = new Factory($loop); +$factory = new Factory(); $uri = 'test:test@localhost/test'; $query = isset($argv[1]) ? $argv[1] : 'select * from book'; //create a mysql connection for executing query -$factory->createConnection($uri)->then(function (ConnectionInterface $connection) use ($query, $loop) { +$factory->createConnection($uri)->then(function (ConnectionInterface $connection) use ($query) { // The protocol parser reads rather large chunked from the underlying connection // and as such can yield multiple (dozens to hundreds) rows from a single data // chunk. We try to artifically limit the stream chunk size here to try to @@ -44,13 +44,13 @@ $stream = $connection->queryStream($query); $throttle = null; - $stream->on('data', function ($row) use ($loop, &$throttle, $stream) { + $stream->on('data', function ($row) use (&$throttle, $stream) { echo json_encode($row, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL; // simple throttle mechanism: explicitly pause the result stream and // resume it again after some time. if ($throttle === null) { - $throttle = $loop->addTimer(1.0, function () use ($stream, &$throttle) { + $throttle = Loop::addTimer(1.0, function () use ($stream, &$throttle) { $throttle = null; $stream->resume(); }); @@ -62,16 +62,14 @@ echo 'Error: ' . $e->getMessage() . PHP_EOL; }); - $stream->on('close', function () use ($loop, &$throttle) { + $stream->on('close', function () use (&$throttle) { echo 'CLOSED' . PHP_EOL; if ($throttle) { - $loop->cancelTimer($throttle); + Loop::cancelTimer($throttle); $throttle = null; } }); $connection->quit(); }, 'printf'); - -$loop->run(); diff --git a/src/Factory.php b/src/Factory.php index a75b88f..ed5e248 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -2,6 +2,7 @@ namespace React\MySQL; +use React\EventLoop\Loop; use React\EventLoop\LoopInterface; use React\MySQL\Commands\AuthenticateCommand; use React\MySQL\Io\Connection; @@ -17,24 +18,31 @@ class Factory { + /** @var LoopInterface */ private $loop; + + /** @var ConnectorInterface */ private $connector; /** * The `Factory` is responsible for creating your [`ConnectionInterface`](#connectioninterface) instance. - * It also registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage). * * ```php - * $loop = \React\EventLoop\Factory::create(); - * $factory = new Factory($loop); + * $factory = new React\MySQL\Factory(); * ``` * + * 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](https://github.com/reactphp/event-loop#loop). + * This value SHOULD NOT be given unless you're sure you want to explicitly use a + * given event loop instance. + * * If you need custom connector settings (DNS resolution, TLS parameters, timeouts, * proxy servers etc.), you can explicitly pass a custom instance of the * [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface): * * ```php - * $connector = new \React\Socket\Connector($loop, array( + * $connector = new React\Socket\Connector(null, array( * 'dns' => '127.0.0.1', * 'tcp' => array( * 'bindto' => '192.168.10.1:0' @@ -45,20 +53,16 @@ class Factory * ) * )); * - * $factory = new Factory($loop, $connector); + * $factory = new React\MySQL\Factory(null, $connector); * ``` * - * @param LoopInterface $loop - * @param ConnectorInterface|null $connector + * @param ?LoopInterface $loop + * @param ?ConnectorInterface $connector */ - public function __construct(LoopInterface $loop, ConnectorInterface $connector = null) + public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null) { - if ($connector === null) { - $connector = new Connector($loop); - } - - $this->loop = $loop; - $this->connector = $connector; + $this->loop = $loop ?: Loop::get(); + $this->connector = $connector ?: new Connector($this->loop); } /** diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php index 19508da..b7d3bf7 100644 --- a/tests/FactoryTest.php +++ b/tests/FactoryTest.php @@ -9,6 +9,17 @@ class FactoryTest extends BaseTestCase { + public function testConstructWithoutLoopAssignsLoopAutomatically() + { + $factory = new Factory(); + + $ref = new \ReflectionProperty($factory, 'loop'); + $ref->setAccessible(true); + $loop = $ref->getValue($factory); + + $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); + } + public function testConnectWillUseHostAndDefaultPort() { $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();