Saturday, September 27, 2014

Nested route and folder in Laravel

Nested route and folder in Laravel

First approach:

You have this existing route..

Route::get('/Home/{identifikation?}', 'HomeController@showWelcome');

..and you have this existing code organization:

/controllers
    /HomeController.php


And this home controller:

<?php

class HomeController extends BaseController
{

    public function showWelcome($identifikation = null)
    {
        $p = new Person; // this Person class is residing in the folder: /models
        $p->firstname = 'Michael Angelo ' . $identifikation;
        $p->lastname = 'Buen';
        $p->nick = 'Kel';



        // 'Home/ShowWelcome' resolves to /views/Home/ShowWelcome.blade.php
        return View::make('Home/ShowWelcome')->with('ninjaTurtle', $p);

    }

}



However, you have a need to move the Home url under Admin..

Route::get('/Admin/Home/{identifikation?}', 'HomeController@showWelcome');

..and likewise you wanted to move HomeController under Admin folder so the new url maps symmetrically to your code organization:

/controllers 
    /Admin
        /HomeController.php


After moving HomeController under /controllers/Admin folder, go to command-line and run:
composer dump-autoload


Then re-launch your web server:
php artisan serve


That's it! With Laravel, you can route url that maps symmetrically to your code organization. Whereas in ASP.NET MVC, controllers are just limited in these two places: the Controllers and Areas/AreaNameHere/Controllers folders, the controller's folder can't be nested. I digress


However, every time you need to move your controller to another folder, you have to do the composer dump-autoload command-line ritual in order for Laravel to find your controller. Failing to do so, you'll always receive the error "Whoops, looks like something went wrong."



Second approach:

To avoid the composer dump-autoload ritual, we can do it in another way. We'll use PHP's namespace. With the following code organization..
/controllers 
    /Admin
        /HomeController.php

..we'll have to change the routing as followed, we prefix the Admin\ namespace to HomeController class:
Route::get('/Admin/Home/{identifikation?}', 'Admin\HomeController@showWelcome');


..,then just add namespace Admin to HomeController.php:
<?php


namespace Admin;

class HomeController extends \BaseController
{

    public function showWelcome($identifikation = null)
    {
        $p = new \Person;
        $p->firstname = 'Michael Angelo ' . $identifikation;
        $p->lastname = 'Buen';
        $p->nick = 'Kel';

        // 'Home/ShowWelcome' resolves to /views/Home/ShowWelcome.blade.php
        return \View::make('Home/ShowWelcome')->with('ninjaTurtle', $p);

    }

}


As you noticed we have to prefix backslash character on the classes; failing to do so, PHP (not Laravel) will look for BaseController, Person and View classes under the namespace of Admin. To make PHP look for those three classes under the global namespace, we have to prefix those classes with backslash. As we might have to use those classes multiple times, a better approach is to import those classes using the keyword use so we don't have to prefix backslash on all classes:


<?php


namespace Admin;

use BaseController, Person, View;

class HomeController extends BaseController
{

    public function showWelcome($identifikation = null)
    {
        $p = new Person;
        $p->firstname = 'Michael Angelo ' . $identifikation;
        $p->lastname = 'Buen';
        $p->nick = 'Kel';



        // 'Home/ShowWelcome' resolves to /views/Home/ShowWelcome.blade.php
        return View::make('Home/ShowWelcome')->with('ninjaTurtle', $p);

    }

}


You might think, maybe we can just do "use \;", unfortunately PHP doesn't work that way, it doesn't work like C#'s using functionality


On a side note, it's unfortunate that PHP need to use "\" character for namespace delimiter as the dot character is used for string concatenation, otherwise the controller will not look like a folder:

Route::get('/Admin/Home/{identifikation?}', 'Admin.HomeController@showWelcome');


Anyway, when we use namespace, Laravel enforces the controller's code organization to mimic the namespace structure. The HomeController must be moved under the Admin folder. At least in Windows the backslash resembles the code organization :-)

Route::get('/Admin/Home/{identifikation?}', 'Admin\HomeController@showWelcome');



Happy Coding!

No comments:

Post a Comment