DEV Community

Cover image for Laravel101: Exploring Laravel Controllers and Namespace Loading
Kazem
Kazem

Posted on • Updated on

Laravel101: Exploring Laravel Controllers and Namespace Loading

Hey there!

In our last tutorial, we talked about how sending and processing data in routes. but it can get super messy, especially when we’ve got a lot of information to deal with. Lucky for us, Laravel has got our back with a solution — controllers!


What we need to know about controllers in Laravel is that controllers are classes that prepare data to be sent to the view.

Creating a controller is a piece of cake — just use the artisan command! You might remember using the php artisan serve command to create a local server. Well, if you enter the php artisan command in the main path of your Laravel project, you’ll see all the amazing things you can do with it.

Every artisan command comes with a handy description to guide you through it. For example, if you want to learn more about the controller, just type in your terminal following command and you’ll get all the juicy details:

Image description

Alright, let’s keep this train rolling! So, when it comes to creating a controller in Laravel, the main argument of the command is simply the name of the controller. Easy peasy, right? As for the other features, don’t worry, we’ll dive into those in future tutorials. But for now, let’s focus on the task at hand!

So, for our project example from the previous article, we want to create a controller that sends data to the view through the controller instead of the route. To make this happen, we just need to create the controller using the following command:

php artisan make:controller UserController
Enter fullscreen mode Exit fullscreen mode

Now let’s open it and move our function inside the route into here and choose a name for that like friends:

Image description

Finally, it is enough to go back to the web route and give the name of the class and the function that returns this output as an array instead our function like bellow:

Route::get('/friends', [
    App\Http\Controllers\UserController::class, 
    'friends'
]);
Enter fullscreen mode Exit fullscreen mode

A super neat trick that I really like it is when you have only one function in a controllers! There is a magic method called the __invoke(), and believe me it's pretty cool. It’s exactly like anonymous callback function we used it directly in route. So the only thing you need is just rename your function in controller to __invoke :

class UserController extends Controller 
{
    public function __invoke()
    {
        $users = ['John', 'Mike', 'Susan', 'Jimmy', 'Kazem'];
        return view('me.friends', compact('users'));
    }
}

Enter fullscreen mode Exit fullscreen mode

Then the friends route is going to like this:

Image description

Another things we can do here is to choose a name according to our route:

Route::get('/friends', UserController::class)->name('user.friends');
Enter fullscreen mode Exit fullscreen mode

Now if you run following command in your terminal you’ll see all the route exist currently in your app:

php artisan route:list 

// or

php artisan r:l
Enter fullscreen mode Exit fullscreen mode

But as you see in your terminal there also some other routes which are not specified with us! These are related to packages which comes with laravel as default.

Image description

You can ignore it now with following command:

php artisan r:l --except-vendor
Enter fullscreen mode Exit fullscreen mode

Here we go!

Image description

Wait wait! This is also feasible to filter this list with --name flag by the name we defined for our route:

Image description

It’s always a good idea to give meaningful names to your routes in Laravel. This makes it easier to group and filter them, which can be really helpful when you have a lot of routes in your application.


What’s a Namespace?

If you’re new to PHP and you see the keyword “namespace” inside a controller, don’t worry! It’s actually a really helpful feature.

Namespaces are a way to organize your code and avoid naming conflicts with other classes that might have the same name. They help you load classes into different groups so that you can use them more efficiently.

Let’s say you want to create a new UserController but you already have it! to do that you have create another directory like Profile , Then, when you want to use your new user controller in your routes, you can simply specify its namespace location, like this: use App\Http\Controllers\Profile\UserController.

This separates it from the original UserControllerand avoids any naming conflicts. Pretty cool, right?

What? PSR-4? did you heard that one too?!

It’s a fancy name for a PHP standard, but don’t worry, it’s not some strange creature! Basically, PSR-4 helps you organize your code by mapping your namespaces to directories on your, is it clear? let me explain it with an example.

Suppose we want instead of writing out use App\Http\Controllers\UserController just use use Controllers\UserController

To make this magic happen, you’ll need to do a little editing in your composer.json file. It’s kind of like the package.json file in a Node.js project and contains some basic configuration. Inside, you’ll find a section called autoload :

"autoload": {
    "psr-4": {
        "App\\": "app/",
        "Database\\Factories\\": "database/factories/",
        "Database\\Seeders\\": "database/seeders/"
    }
},
"autoload-dev": {
    "psr-4": {
        "Tests\\": "tests/"
    }
},
Enter fullscreen mode Exit fullscreen mode

autoload-dev used for dev environment so for now we just need to define our new loading rule like bellow inside autoload:

"autoload": {
    "psr-4": {
        "App\\": "app/",
        "Controllers": "app/Http/Controolers/",
        "Database\\Factories\\": "database/factories/",
        "Database\\Seeders\\": "database/seeders/"
    }
},
Enter fullscreen mode Exit fullscreen mode

And change namespace for every controller inside app/Http/Controllers to namespace Controllers .

Then we can point out to our controller simply like this:

Route::get('/friends', Controllers\UserController::class)
  ->name('user.friends');

// or 

use Controllers\UserController;
Route::get('/friends', UserController::class)->name('user.friends');
Enter fullscreen mode Exit fullscreen mode

If you do that you’ll get the following error! 🤯

Image description

> Here is the deal: If you make any changes to your composer.json file, you’ll need to run the following command to set up those changes in your project!

composer dump-autoload
Enter fullscreen mode Exit fullscreen mode

And voila! In this tutorial, you have learned how to send data through the controller class in Laravel, both in routes and views. You’ve also learned a bit about namespaces and loading classes in Laravel. In the next article, we’ll delve deeper into the blade structure and show you how to create a more suitable layout for your current project. It’s going to be awesome!

Top comments (3)

Collapse
 
mhasan profile image
Mahmudul Hasan

Where you use __invoke() method? I don't see. This post is bit confusing.

Collapse
 
kazemmdev profile image
Kazem

Hey there!
As I mentioned in the post you need only rename your function into __invoke
Btw, I recently made a few tweaks to make it more clear!

Collapse
 
mhasan profile image
Mahmudul Hasan

Thanks for updating the post, let me check this again.