If you haven't read my guide on Creating a Tiny PHP MVC Framework From Scratch then you should do that immediately, the concept of the guide applies to the way things work in Laravel behind the scene. You'll get to know the architectural design of the major framework.
I guess you are done reading that, let's proceed. In this guide, we look into routing and controllers in Laravel.
- Routing
- Controllers
Routing
Routing allows you to route (send) specific requests to its appropriate controller. This is the same as the Core.php file we created in our Tiny framework, in that guide, we broke down the user's request, if for example, the user is requesting the homepage, it routes them to the appropriate controller. In laravel, you don't have to do all that, it is programmatically done behind the scene, so, you just tell laravel whatever you want to route.
You might say, Laravel, once a user sends a get request to my example.com/page route them to a specific controller. You get the idea I guess.
Again, if you've read through the Tiny Framework guide, everything in this guide would make sense. The only difference is understanding the structure of where Laravel places its component.
All Laravel routes are defined in your route files, which are located in the routes directory. In Larvel, the routes/web.php file defines routes for your application.
You will begin by defining routes in your routes/web.php file. The routes defined in routes/web.php may be accessed by entering the defined route's URL in your browser.
For example, if you want to access the homepage in your browser, then you would use the following route:
Route::get('/', function () {
return view('welcome');
});
This means, when a client sends a get request to the homepage, return the "welcome" view that is in the view folder. By default, the page would load the following:
The view is located in the resources folder:
If you want to return a custom message instead, you can do:
Route::get('/', function () {
return "This would return the default homepage;
});
Easy enough right!
You can say, if a user sends a get request to /dashboard, return something:
Route::get('/dashboard', function () {
return "This is users dashboard";
});
It's so easy to work with route in laravel. There are different kinds of route, you don't want to use a get route when a user is trying to submit a form, here are the available ones:
Route::get($uri, $callback); // GET is used to request data from a specified resource.
Route::post($uri, $callback); // POST is used to send data to a server to create/update a resource, e.g a form, i.e register-form
Route::put($uri, $callback); // same as POST but idempotent
Route::patch($uri, $callback); // PATCH updates part of the resource at that client defined URL.
Route::delete($uri, $callback); // The DELETE method deletes the specified resource.
Route::options($uri, $callback); // The OPTIONS method describes the communication options for the target resource.
You don't have to know all this, in short, the only one that is important for now is the get and post route, you would learn more about others in a future guide.
You can even return an HTML:
Route::get('/dashboard', function () {
return "<h1>This is users dashboard</h1>";
});
Well, you don't want to return an HTML directly, that is what views are made for, so, you can create a folder in your view that contains a silo architecture of your views, e.g:
Laravel uses blade as its template engine, that is why I did: dashboard.blade.php, we would get back to that later.
So, to include the view in your route, you can do:
Route::get('/dashboard', function () {
return view('pages/dashboard');
});
This would return the dashboard view in the pages folder. Another way of writing this is using:
Route::get('/dashboard', function () {
return view('pages.dashboard');
});
Which I prefer, so, pages.dashboard means the dashboard view in the pages folder, use whatever soothes you.
Another interesting thing you can do with the route is you can get the result dynamically, e.g:
Route::get('/dashboard{id}', function ($id) {
return "You passed in $id";
});
This is useful if, for example, you want to query the database based on what the user is passing. if you have say 500 /post/{$id}, you don't want to create 500 views for every one of them, so, in that case, you just create a dynamic route that handles that.
To put another one you can do:
Route::get('/post/{name}/{id}', function ($name, $id) {
return "You want $name of $id";
});
In our Tiny Framework guide, the controller is the one delegating the model and the view, but all we've been doing so far is merely returning the view from the route, which isn't something we should be doing, so, we would create a controller, and set the route to go to the controller, we then return the view from the controller.
Controllers
Controllers are stored in the app/Http/Controllers directory. There are a couple of ways you can create a controller, and one way is using the terminal which is my preferred method, or you can write the code manually if you like stress ;). To create a controller from the terminal, we can use:
$ php artisan make:controller PagesController
Controller created successfully.
$
If you look in app/Http/Controller, you'll see a Pages controller has been created:
The artisan command created it automatically for us, if somehow you can't use the terminal, then you can create PagesController in your Controller folder, and then add the following:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PagesController extends Controller
{
//
}
It uses namespace App\Http\Controller, which brings in the Request class so we can handle the request, and lastly, we are extending the core controllers.
Just to see if the controller is working, we can add the following:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PagesController extends Controller {
public function index() { // Frontpage
return "Testing Testing Testing...";
}
}
We then add it to our route file:
Route::get('/', [PagesController::class, 'index']);
This tells route whenever a client sends a get request to the homepage, return the index method in the PagesController class.
Then when you visit the homepage, you should get:
If you get the following error:
This is because it doesn't truly exist, fix it by importing the class in your route file like so:
So, to return the view in our PagesController, we do:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PagesController extends Controller
{
public function index() { // Frontpage
return view('pages.frontpage');
}
}
So, whatever is in the frontpage view would be returned instead. Let's customize our frontpage view:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{config('app.name', 'SimpleApp')}}</title>
</head>
<body class="antialiased">
<h1> Welcome To SimpleApp</h1>
<p>This is our simple application</p>
</body>
</html>
To access a value in your blade template you use 2 double curly braces, as you can see in the title section, I am accessing the app.name store in the .env file, and if that is not available, it uses 'SimpleApp'
You can set the configs in the .env file:
If you check the source of the requested URL, you'll see that it in fact replaces the tittle:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SimpleApp</title>
</head>
<body class="antialiased">
<h1> Welcome To SimpleApp</h1>
<p>This is our simple application</p>
</body>
</html>
If you want to add another view, you can simply just do:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PagesController extends Controller
{
public function index() { // Frontpage
return view('pages.frontpage');
}
public function dashboard() { // Dashboard Page
return view('pages.dashboard');
}
}
You then add a route to access dashboard method in the PagesController
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PagesController;
Route::get('/', [PagesController::class, 'index']); // Frontpage
Route::get('/dashboard', [PagesController::class, 'dashboard']); // Dashboard
This tells route whenever a client sends a get request to the homepage, return the index method in the PagesController class. Likewise, whenever a client browser sends a get request to the /dashboard URL, it returns the dashboard method in the PagesController class.
Here is the dashboard view:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{config('app.name', 'SimpleApp')}}</title>
</head>
<body class="antialiased">
<h1>DashBoard Page</h1>
<p>Welcome To Users Dashboard</p>
</body>
</html>
and here is the result:
Doing things this way gives us a sort of a granular way of creating our application.