Skip to content

Commit

Permalink
Merge pull request #22 from clue/optional-loop
Browse files Browse the repository at this point in the history
Simplify `App` usage by making `LoopInterface` argument optional
  • Loading branch information
clue authored Jun 18, 2021
2 parents d0ed78a + 74dcc40 commit f79feb6
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 158 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ empty project directory:

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

$loop = React\EventLoop\Factory::create();
$app = new FrameworkX\App($loop);
$app = new FrameworkX\App();

$app->get('/', function () {
return new React\Http\Message\Response(
Expand All @@ -41,7 +40,6 @@ $app->get('/users/{name}', function (Psr\Http\Message\ServerRequestInterface $re
});

$app->run();
$loop->run();
```

Next, we need to install X and its dependencies to actually run this project.
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"require": {
"php": ">=7.1",
"nikic/fast-route": "^1.3",
"react/event-loop": "dev-master#1a709e2 as 1.2.0",
"react/http": "^1.1",
"react/promise": "^2.7"
},
Expand Down
25 changes: 1 addition & 24 deletions docs/api/app.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,19 @@
The `App` class is your main entrypoint to any application that builds on top of X.
It provides a simple API for routing HTTP requests as commonly used in RESTful applications.

Internally, the `App` object builds on top of [ReactPHP](https://reactphp.org/)
to do its magic, hence you have to create it like this:

```php
# app.php
<?php

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

$loop = React\EventLoop\Factory::create();
$app = new FrameworkX\App($loop);
$app = new FrameworkX\App();

// Register routes here, see routing…

$app->run();
$loop->run();
```

> ℹ️ **Heads up!**
>
> Major improvements upcoming! We're actively contributing to our underlying
> libraries to make sure this can look like this in the near future:
>
> ```php
> # app.php
> <?php
>
> require __DIR__ . '/vendor/autoload.php';
>
> $app = new FrameworkX\App();
>
> // Register routes here, see routing…
>
> $app->run();
> ```
## Routing

The `App` class offers a number of API methods that allow you to route incoming
Expand Down
4 changes: 1 addition & 3 deletions docs/api/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,11 @@ a global middleware handler for all registered routes:
use Acme\Todo\AdminMiddleware;
use Acme\Todo\UserController;

$loop = React\EventLoop\Factory::create();
$app = new FrameworkX\App($loop, new AdminMiddleware());
$app = new FrameworkX\App(new AdminMiddleware());

$app->get('/user', new UserController());

$app->run();
$loop->run();
```

You can also combine global middleware handlers (think logging) with additional
Expand Down
8 changes: 2 additions & 6 deletions docs/best-practices/controllers.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ To get started, let's take a look at the following simple closure definitions:

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

$loop = React\EventLoop\Factory::create();
$app = new FrameworkX\App($loop);
$app = new FrameworkX\App();

$app->get('/', function () {
return new React\Http\Message\Response(
Expand All @@ -33,7 +32,6 @@ $app->get('/users/{name}', function (Psr\Http\Message\ServerRequestInterface $re
});

$app->run();
$loop->run();
```

While easy to get started, it's also easy to see how this will get out of hand for more complex
Expand All @@ -49,14 +47,12 @@ definition into three even simpler files:

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

$loop = React\EventLoop\Factory::create();
$app = new FrameworkX\App($loop);
$app = new FrameworkX\App();

$app->get('/', new Acme\Todo\HelloController());
$app->get('/users/{name}', new Acme\Todo\UserController());

$app->run();
$loop->run();
```

```php
Expand Down
4 changes: 1 addition & 3 deletions docs/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ You can use this example to get started by creating a new `app.php` file in your

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

$loop = React\EventLoop\Factory::create();
$app = new FrameworkX\App($loop);
$app = new FrameworkX\App();

$app->get('/', function () {
return new React\Http\Message\Response(
Expand All @@ -42,7 +41,6 @@ $app->get('/users/{name}', function (Psr\Http\Message\ServerRequestInterface $re
});

$app->run();
$loop->run();
```

On a code level, this is everything you need to get started.
Expand Down
8 changes: 3 additions & 5 deletions examples/index.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
<?php

use Psr\Http\Message\ServerRequestInterface;
use React\EventLoop\Factory;
use React\Stream\ThroughStream;

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

$loop = Factory::create();
$app = new FrameworkX\App($loop);
$app = new FrameworkX\App();

$app->get('/', function () {
return new React\Http\Message\Response(
Expand Down Expand Up @@ -73,9 +71,10 @@
);
});

$app->get('/stream', function (ServerRequestInterface $request) use ($loop) {
$app->get('/stream', function (ServerRequestInterface $request) {
$stream = new ThroughStream();

$loop = React\EventLoop\Loop::get();
$timer = $loop->addPeriodicTimer(0.5, function () use ($stream) {
$stream->write(microtime(true) . ' hi!' . PHP_EOL);
});
Expand Down Expand Up @@ -137,4 +136,3 @@
});

$app->run();
$loop->run();
8 changes: 7 additions & 1 deletion src/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use FastRoute\RouteParser\Std as RouteParser;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use React\EventLoop\Loop;
use React\EventLoop\LoopInterface;
use React\Http\Server as HttpServer;
use React\Http\Message\Response;
Expand All @@ -23,8 +24,11 @@ class App
private $router;
private $routeDispatcher;

public function __construct(LoopInterface $loop)
public function __construct(LoopInterface $loop = null)
{
if ($loop === null) {
$loop = Loop::get();
}
$this->loop = $loop;
$this->router = new RouteCollector(new RouteParser(), new RouteGenerator());
}
Expand Down Expand Up @@ -153,6 +157,8 @@ public function run()
} else {
$this->runOnce();
}

$this->loop->run();
}

private function runLoop()
Expand Down
56 changes: 16 additions & 40 deletions tests/AppMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use React\EventLoop\LoopInterface;
use React\Http\Message\ServerRequest;
use React\Http\Message\Response;
use React\Promise\PromiseInterface;
Expand All @@ -18,8 +17,7 @@ class AppMiddlewareTest extends TestCase
{
public function testGetMethodWithMiddlewareAddsGetRouteOnRouter()
{
$loop = $this->createMock(LoopInterface::class);
$app = new App($loop);
$app = new App();

$middleware = function () {};
$controller = function () { };
Expand All @@ -36,8 +34,7 @@ public function testGetMethodWithMiddlewareAddsGetRouteOnRouter()

public function testHeadMethodWithMiddlewareAddsHeadRouteOnRouter()
{
$loop = $this->createMock(LoopInterface::class);
$app = new App($loop);
$app = new App();

$middleware = function () {};
$controller = function () { };
Expand All @@ -54,8 +51,7 @@ public function testHeadMethodWithMiddlewareAddsHeadRouteOnRouter()

public function testPostMethodWithMiddlewareAddsPostRouteOnRouter()
{
$loop = $this->createMock(LoopInterface::class);
$app = new App($loop);
$app = new App();

$middleware = function () {};
$controller = function () { };
Expand All @@ -72,8 +68,7 @@ public function testPostMethodWithMiddlewareAddsPostRouteOnRouter()

public function testPutMethodWithMiddlewareAddsPutRouteOnRouter()
{
$loop = $this->createMock(LoopInterface::class);
$app = new App($loop);
$app = new App();

$middleware = function () {};
$controller = function () { };
Expand All @@ -90,8 +85,7 @@ public function testPutMethodWithMiddlewareAddsPutRouteOnRouter()

public function testPatchMethodWithMiddlewareAddsPatchRouteOnRouter()
{
$loop = $this->createMock(LoopInterface::class);
$app = new App($loop);
$app = new App();

$middleware = function () {};
$controller = function () { };
Expand All @@ -108,8 +102,7 @@ public function testPatchMethodWithMiddlewareAddsPatchRouteOnRouter()

public function testDeleteMethodWithMiddlewareAddsDeleteRouteOnRouter()
{
$loop = $this->createMock(LoopInterface::class);
$app = new App($loop);
$app = new App();

$middleware = function () {};
$controller = function () { };
Expand All @@ -126,8 +119,7 @@ public function testDeleteMethodWithMiddlewareAddsDeleteRouteOnRouter()

public function testOptionsMethodWithMiddlewareAddsOptionsRouteOnRouter()
{
$loop = $this->createMock(LoopInterface::class);
$app = new App($loop);
$app = new App();

$middleware = function () {};
$controller = function () { };
Expand All @@ -144,8 +136,7 @@ public function testOptionsMethodWithMiddlewareAddsOptionsRouteOnRouter()

public function testAnyMethodWithMiddlewareAddsAllHttpMethodsOnRouter()
{
$loop = $this->createMock(LoopInterface::class);
$app = new App($loop);
$app = new App();

$middleware = function () {};
$controller = function () { };
Expand All @@ -162,8 +153,7 @@ public function testAnyMethodWithMiddlewareAddsAllHttpMethodsOnRouter()

public function testMapMethodWithMiddlewareAddsGivenMethodsOnRouter()
{
$loop = $this->createMock(LoopInterface::class);
$app = new App($loop);
$app = new App();

$middleware = function () {};
$controller = function () { };
Expand All @@ -180,9 +170,7 @@ public function testMapMethodWithMiddlewareAddsGivenMethodsOnRouter()

public function testMiddlewareCallsNextReturnsResponseFromRouter()
{
$loop = $this->createMock(LoopInterface::class);

$app = new App($loop);
$app = new App();

$middleware = function (ServerRequestInterface $request, callable $next) {
return $next($request);
Expand Down Expand Up @@ -216,9 +204,7 @@ public function testMiddlewareCallsNextReturnsResponseFromRouter()

public function testMiddlewareCallsNextWithModifiedRequestReturnsResponseFromRouter()
{
$loop = $this->createMock(LoopInterface::class);

$app = new App($loop);
$app = new App();

$middleware = function (ServerRequestInterface $request, callable $next) {
return $next($request->withAttribute('name', 'Alice'));
Expand Down Expand Up @@ -252,9 +238,7 @@ public function testMiddlewareCallsNextWithModifiedRequestReturnsResponseFromRou

public function testMiddlewareCallsNextReturnsResponseModifiedInMiddlewareFromRouter()
{
$loop = $this->createMock(LoopInterface::class);

$app = new App($loop);
$app = new App();

$middleware = function (ServerRequestInterface $request, callable $next) {
$response = $next($request);
Expand Down Expand Up @@ -289,9 +273,7 @@ public function testMiddlewareCallsNextReturnsResponseModifiedInMiddlewareFromRo

public function testMiddlewareCallsNextReturnsDeferredResponseModifiedInMiddlewareFromRouter()
{
$loop = $this->createMock(LoopInterface::class);

$app = new App($loop);
$app = new App();

$middleware = function (ServerRequestInterface $request, callable $next) {
$promise = $next($request);
Expand Down Expand Up @@ -336,9 +318,7 @@ public function testMiddlewareCallsNextReturnsDeferredResponseModifiedInMiddlewa

public function testMiddlewareCallsNextReturnsCoroutineResponseModifiedInMiddlewareFromRouter()
{
$loop = $this->createMock(LoopInterface::class);

$app = new App($loop);
$app = new App();

$middleware = function (ServerRequestInterface $request, callable $next) {
$generator = $next($request);
Expand Down Expand Up @@ -385,9 +365,7 @@ public function testMiddlewareCallsNextReturnsCoroutineResponseModifiedInMiddlew

public function testMiddlewareCallsNextWhichThrowsExceptionReturnsInternalServerErrorResponse()
{
$loop = $this->createMock(LoopInterface::class);

$app = new App($loop);
$app = new App();

$middleware = function (ServerRequestInterface $request, callable $next) {
return $next($request);
Expand Down Expand Up @@ -416,9 +394,7 @@ public function testMiddlewareCallsNextWhichThrowsExceptionReturnsInternalServer

public function testMiddlewareWhichThrowsExceptionReturnsInternalServerErrorResponse()
{
$loop = $this->createMock(LoopInterface::class);

$app = new App($loop);
$app = new App();

$line = __LINE__ + 2;
$middleware = function (ServerRequestInterface $request, callable $next) {
Expand Down
Loading

0 comments on commit f79feb6

Please sign in to comment.