Application Routes
Application routes are located in app/Routes.php
Simply-PHP uses Rewrite engine to modify URL's apperance, Then router class is processing URL endpoint and decomposing it into parameters to determine the controller or action to receive the request.
Application routes are located in app/Routes.php
Basic routing accepts two parameters:
Router::set('home',[
'controller' => 'home',
'action' => 'index'
]);
Router above can be convert to much shorter code. Thi can achieve by passing a variable to the router first parameter.
Router::set('{controller:home}/{action:index}');
Here we pass a controller variable and action variable.
Router accepts variables by enclosing them with { }.
Router::set('{controller:home}/{action:index}');
Here we pass a controller variable and action variable.
This route can only call the index action inside HomeController.
Router can accepts variables with regular expression by specifying variable like {var:regex}.
Router::set('users/show/{id:\d+}',[
'controller' => 'user',
'action' => 'show'
]);
Here wew pass a variable id with regex \d+
telling the router that this variable only accepts a valid number
Here are some regex for variables that can be use for your application
[a-z0-9]+(?:-[a-z0-9]+)*$ Valid Slug eg: news-report-2019\w+ accepts letters and numbers\d+ accepts only numbers\bSHOW|\bEDIT|\bUPDATE accepts show, edit and update (case insensitive).Simply-PHP has a predefined routes
Simply has a route resource that address CRUD in a controller. Instead of declaring mutltiple route for CRUD in a controller just declare a route resource for your controller.
Router::resource('products','ProductController');
| # | URL | Description | controller@action |
|---|---|---|---|
| 1 | /products | Show product list | ProductController@index |
| 2 | /products/create | Show product create form | ProductController@create |
| 3 | /products/store | Accepts and store data from product create form | ProductController@store |
| 4 | /products/show/{id} | Show single product entry | ProductController@show(Request $request) |
| 5 | /products/edit/{id} | Show product edit form | ProductController@edit(Request $request) |
| 6 | /products/update/{id} | Accepts and update existing data from product create form | ProductController@update(Request $request) |
| 7 | /products/destroy/{id} | Delete the product from the table | ProductController@destroy(Request $request) |
NOTE: The product controller here only serves as example. You can create your own
Routes can be dynamic by using the advantage of the routes variable
Router::set('dashboard/{action}',[
'controller' => 'dashboard'
]);
Notice the action variable here. Router can simply find the action from URL in the controller to be called if it is existing
Router class can also accept optional parameters.
Router::set('product/{id?}',[
'controller' => 'ProductController',
'action' => 'someAction'
]);
Route Optional Parameters: (just add ? to the route variable eg: {id?}
:all? routeRouter class can accept any url using the :all? parameter. This can be usefull when you're create a Single Page Application,
or If you are using a Front-End framework like React.js, Vue.js, Angular.js, etc.
Router::set('application/{:all?}',[
'controller' => 'SinglePageController',
'action' => 'index'
]);
all parameters pass to http:://myDomain.com/application/you/can/put/anything/here will pass the request to SinglePageController
Routes can be grouped under a common prefix using Router::group(). Groups can be nested.
Router::group('admin', function () {
Router::get('users', ['controller' => 'AdminController', 'action' => 'users']);
Router::get('settings', ['controller' => 'AdminController', 'action' => 'settings']);
});
// Matches: /admin/users, /admin/settings
Routes can be restricted to specific HTTP methods using the dedicated helpers.
Router::get('posts', ['controller' => 'PostController', 'action' => 'index']);
Router::post('posts/store', ['controller' => 'PostController', 'action' => 'store']);
Router::put('posts/update/{id}', ['controller' => 'PostController', 'action' => 'update']);
Router::delete('posts/destroy/{id}', ['controller' => 'PostController', 'action' => 'destroy']);
If a controller action method ends with Action (e.g. indexAction), the router calls it automatically when the route specifies 'action' => 'index'.
// Controller method:
class ProductController extends Controller
{
public function indexAction()
{
return view('product.index');
}
}
// Route - the 'Action' suffix is resolved automatically:
Router::set('products', [
'controller' => 'ProductController',
'action' => 'index'
]);
The router normalizes trailing slashes. /products and /products/ resolve to the same route.
// Both of these match the same route:
Router::set('products', ['controller' => 'ProductController', 'action' => 'index']);
// http://example.com/products
// http://example.com/products/
Controller methods receive their arguments automatically via the ControllerDispatcher. Arguments are resolved by type-hint and parameter name matching.
Type-hint Request to receive the current HTTP request. The same Request instance is shared across all controllers in a request cycle.
use Simple\Request;
class ProductController extends Controller
{
public function index(Request $request)
{
$search = $request->get('search');
return view('product.index');
}
}
Route placeholders are passed as arguments matching the parameter name:
// Route:
Router::set('product/{id}/{slug}', [
'controller' => 'ProductController',
'action' => 'show'
]);
// Controller — parameter names match route placeholders:
class ProductController extends Controller
{
public function show(string $id, string $slug)
{
return "Product #{$id}: {$slug}";
}
}
Parameters with defaults are preserved when the route doesn't provide a value:
class ProductController extends Controller
{
public function index(string $sort = 'name', int $page = 1)
{
// $sort defaults to 'name', $page defaults to 1
}
}
Non-built-in type-hints are recursively resolved. The dispatcher inspects each class's constructor and resolves its dependencies automatically:
class ProductService
{
public function __construct(private Logger $logger) {}
public function all(): array { /* ... */ }
}
class ProductController extends Controller
{
// ProductService and its Logger dependency are auto-resolved:
public function index(ProductService $service)
{
$products = $service->all();
return view('product.index', ['products' => $products]);
}
}
Sometimes you want to organize your controllers inside their own folder. The folder name then will be the namespace
Example:
You have your controller inside the Admin folder in the Controller's folder.
Your controller's namespace should be: namespace App\Controllers\Admin;
Make sure you are extending the default Controller::class. eg: class AdminController extends \App\Controllers\Controller {
Example of a AdminController inside a Admin folder:
<?php
namespace App\Controllers\Admin;
use App\Controllers\Controller;
use Simple\Request;
class AdminController extends Controller
{
public function index()
{
return 'hello';
}
}
The namespace parameter tells the router where to look for the controller:
Router::set('administrator/{action}',[
'namespace' => 'admin',
'controller' => 'AdminController'
]);
Here we pass an admin namespace parameter
You can also pass the full controller class name directly. When the controller value contains a backslash (\), the router uses it as-is — no namespace prefix or Controller suffix is added:
Router::set('administrator/{action}',[
'controller' => 'App\Controllers\Admin\AdminController'
]);
Both approaches are equivalent. Use whichever is clearer for your project.