From b39da4a7e3070be63a3e438e4cfe77570a0fdaca Mon Sep 17 00:00:00 2001 From: Kaloyan Tsvetkov Date: Tue, 4 Jan 2022 11:27:48 +0200 Subject: [PATCH] Adding Ertuo\UnfoldedRoute --- README.md | 48 +++++++++++++++++----- src/UnfoldedRoute.php | 72 +++++++++++++++++++++++++++++++++ tests/Unabridged/API_Test.php | 5 ++- tests/Unabridged/Admin_Test.php | 3 +- tests/Unabridged/Web_Test.php | 3 +- tests/UnfoldedRouteTest.php | 39 ++++++++++++++++++ 6 files changed, 156 insertions(+), 14 deletions(-) create mode 100644 src/UnfoldedRoute.php create mode 100644 tests/UnfoldedRouteTest.php diff --git a/README.md b/README.md index 89069fc..4769974 100644 --- a/README.md +++ b/README.md @@ -413,13 +413,8 @@ whether some details have already been collected in the result or not. You can dump of all of the routes as array using `Route::toArray()`. This is helpful in situations when you need to work with the whole complete set of routes. -This is used internally by the "builders". You can read more about them in the section below. - -One exotic thing I used `Route::toArray()` for is a benchmark comparing reading -from a completely unfolded tree vs. progressively exploring the tree at runtime. -As you might have guessed it, runtime is faster. This was again to prove the -point that routes declaration eats up a lot of time in advance of the actual -routing process. +This is used internally by the "builders" and the unfolded routes. +You can read more about them in the section below. # Builders @@ -458,8 +453,7 @@ generators. The generated code for the route tree looks something like this: -``` -rule('enum', ['en', 'de', ], [])->default('en', []) ->group(function() { - return array( ... + return array( ... ); + }) + ); +}); +``` + +# Unfolded Routes + +There are benefits in working with "constant" arrays when `opcache` is enabled. +The "constant" arrays are such that are only read and they are never changed. + +To take advantage of this, you can use the `UnfoldedRoute` class. It stores a +fully unfolded routes tree that is a complete set of routes created from +`Route::toArray()` or other implementations of `ExportInterface`. + +```php +use Ertuo\Route; +use Ertuo\UnfoldedRoute; + +$unfoldedRoutesFilename = '/somewhere/where/routes/live/unfolded.php'; + +if (!is_file($unfoldedRoutesFilename)) +{ + $routes = Route::add('_locale')->rule( ... ); + + file_put_contents( + $unfoldedRoutesFilename, + 'toArray(), true) + . ';' + ); +} + +$unfolded = include $unfoldedRoutesFilename; +$routes = UnfoldedRoute::fromArray($unfolded); ``` # A Better Example diff --git a/src/UnfoldedRoute.php b/src/UnfoldedRoute.php new file mode 100644 index 0000000..6dbb97c --- /dev/null +++ b/src/UnfoldedRoute.php @@ -0,0 +1,72 @@ +unfolded = $tree; + + $route->key = $route->unfolded['key']; + $route->attributes = $route->unfolded['attributes']; + $route->rule = $route->unfolded['rule']; + $route->default = $route->unfolded['default']; + + return $route; + } + + /** + * Read a nested route identified by $step + * + * @param string $step value of current step from the source array + * @return null|RouteAbstract + */ + function readRoute(string $step) : ?RouteAbstract + { + if (empty( $this->unfolded['routes'][ $step ] )) + { + return null; + } + + return static::fromArray( $this->unfolded['routes'][ $step ] ); + } + + /** + * @see ExportInterface::toArray() + */ + function toArray() : array + { + return $this->unfolded; + } +} diff --git a/tests/Unabridged/API_Test.php b/tests/Unabridged/API_Test.php index a78a45c..0cfa770 100644 --- a/tests/Unabridged/API_Test.php +++ b/tests/Unabridged/API_Test.php @@ -2,11 +2,12 @@ namespace Ertuo\Tests\Unabridged; -use Ertuo\Route; +use Ertuo\Route; +use Ertuo\RouteAbstract; class API_Test extends Web_Test { - function getRoutes() : Route + function getRoutes() : RouteAbstract { return Route::add('_app') ->rule('enum', ['api', 'admin'])->default('web') diff --git a/tests/Unabridged/Admin_Test.php b/tests/Unabridged/Admin_Test.php index 1402605..ab5b219 100644 --- a/tests/Unabridged/Admin_Test.php +++ b/tests/Unabridged/Admin_Test.php @@ -3,10 +3,11 @@ namespace Ertuo\Tests\Unabridged; use Ertuo\Route; +use Ertuo\RouteAbstract; class Admin_Test extends Web_Test { - function getRoutes() : Route + function getRoutes() : RouteAbstract { return Route::add('_app') ->rule('enum', ['admin', 'api']) diff --git a/tests/Unabridged/Web_Test.php b/tests/Unabridged/Web_Test.php index a597fc3..2027fc3 100644 --- a/tests/Unabridged/Web_Test.php +++ b/tests/Unabridged/Web_Test.php @@ -3,13 +3,14 @@ namespace Ertuo\Tests\Unabridged; use Ertuo\Route; +use Ertuo\RouteAbstract; use Ertuo\Dispatcher; use PHPUnit\Framework\TestCase; class Web_Test extends TestCase { - function getRoutes() : Route + function getRoutes() : RouteAbstract { return Route::add('_app') ->rule('enum', ['api', 'admin'])->default('web') diff --git a/tests/UnfoldedRouteTest.php b/tests/UnfoldedRouteTest.php new file mode 100644 index 0000000..2629a21 --- /dev/null +++ b/tests/UnfoldedRouteTest.php @@ -0,0 +1,39 @@ +toArray(), 1) + . ';' + ); + + $routes = UnfoldedRoute::fromArray(include $unfolded); + unlink($unfolded); + + return $routes; + } + + function testCompareExportedArrays() + { + $parent = parent::getRoutes()->toArray(); + $unfolded = $this->getRoutes()->toArray(); + + $this->assertEquals($parent, $unfolded); + } +}