Skip to content

Instantly share code, notes, and snippets.

@ahsankhatri
Last active February 10, 2022 18:29
Show Gist options
  • Save ahsankhatri/de47ffe20c76151dae5d29923b4e3079 to your computer and use it in GitHub Desktop.
Save ahsankhatri/de47ffe20c76151dae5d29923b4e3079 to your computer and use it in GitHub Desktop.
Database Driven Routes Laravel 5.2

Database Driven Routes Laravel 5.2

Table: url_alias

+----+-----------------+-------------------------------------------+-----------------+-----------+------------+
| id | slug            | map_to                                    | params          | http_verb | middleware |
+----+-----------------+-------------------------------------------+-----------------+-----------+------------+
| 1  | page/about-us   | Frontend\HomeController@showPage          | a:1:{i:0;i:4;}  | GET       | web        |
| 2  | page/contact-us | Backend\DashboardController@getContactUs  | a:1:{i:0;i:4;}  | GET       | web        |
| 3  | page/contact-us | Backend\DashboardController@postContactUs |                 | POST      | web        |
+----+-----------------+-------------------------------------------+-----------------+-----------+------------+
  • slug: self explanatory
  • map_to: Namespace (if any) Controller @ method
  • params: should be serialized array
  • http_verb: register routes with http verb (GET|POST|DELETE|PUT|ANY)
  • middleware: to wrap routes under specified middleware group

Inspired from philsown/53bc22d001db979481e4, i didn't want to run db query on each request thats why file generation method is the rescure here, call route-generation functionality after change made on url_alias table.

Any suggestions will be appreciated.

Route::get('/route-generation', function() {
$db_routes = DB::table('url_alias')->get();
$collection_routes = collect($db_routes)->groupBy('middleware');
$makeRouteGroup = true;
if ( $collection_routes->count() == 1 && $collection_routes->keys()->first() == '' ) {
$makeRouteGroup = false;
}
$routes = ["<?php\n"];
if ( true === $makeRouteGroup ) {
foreach ($collection_routes as $middleware => $db_routes) {
$tabRepeat = 0;
if ( $middleware != '' ) {
$routes[] = "Route::group(['middleware' => '".$middleware."'], function () {";
$tabRepeat = 1;
}
foreach ($db_routes as $route) {
$routes[] = str_repeat("\t", $tabRepeat) . 'Route::'.strtolower($route->http_verb).'(\''.$route->slug.'\', \''.$route->map_to.'\');';
}
if ( $middleware != '' ) {
$routes[] = "});\n";
}
}
} else {
foreach ($db_routes as $route) {
$routes[] = 'Route::'.strtolower($route->http_verb).'(\''.$route->slug.'\', \''.$route->map_to.'\');';
}
}
\File::put( storage_path('framework/routes.php'), implode("\n", $routes) . "");
});
// ...
require app_path('Http/routes.php');
if (
!$this->app->runningInConsole() &&
!array_key_exists(substr($this->app->request->getPathInfo(),1), \Route::getRoutes()->get( $this->app->request->getMethod() ) ) &&
is_file(storage_path('framework/routes.php'))
) {
require storage_path('framework/routes.php');
$uri = substr($this->app->request->getPathInfo(),1);
if (
array_key_exists($uri, \Route::getRoutes()->get( $this->app->request->getMethod() ))
) {
$dbRoute = \DB::table('url_alias')->where('slug', '=', $uri)->first();
if ($dbRoute) {
$router->get($uri, function() use ($dbRoute) {
$segments = explode('@', $dbRoute->map_to);
$controller = $segments[0];
$method = $segments[1];
$obj = $this->app->make($this->namespace . '\\' . $controller);
$params = (!empty($dbRoute->params)) ? unserialize($dbRoute->params) : [];
return call_user_func_array([$obj, $method], $params);
});
}
}
unset($uri, $dbRoute);
}
@IsraelOrtuno
Copy link

I love this approach but why not to just cache the routes rather than creating php code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment