JumpGate App Walkthrough: Routes and Links


Introduction

In this step of creating our todo app, we are going to continue building out the todo service. In this step we will be setting up our routes and navigation links. The routes all live in the app/Services/ToDo/Http/Routes directory.

{info} You can see the source code at GitHub.

This step is stored as a branch called route-links.

Routes

In JumpGate, we use class based routing. By this we mean that we do not use the default routes/web.php file to store routes. Even using includes and sub directories to keep this organized more, it still felt odd to us. So we created a system where we could use a PHP class as a route group. To assist with this we have created a base route class and an interface. These are pretty easy once you get used to them.

{success} Learn more about class based routing.

All you need to get a route class started is the namespace, the middleware and the routes method. Create a new file named TaskList.php in app/Services/ToDo/Http/Routes. We will add the following needed code to get started.

<?php

namespace App\Services\ToDo\Http\Routes;

use Illuminate\Routing\Router;
use JumpGate\Core\Contracts\Routes;
use JumpGate\Core\Http\Routes\BaseRoute;

class TaskList extends BaseRoute implements Routes
{
    public $namespace = 'App\Services\Http\Controllers';

    public $middleware = [
        'web',
        'auth',
    ];

    public function routes(Router $router)
    {
        //
    }
}

This all behaves exactly like you are used to, just in a class instead of a flat file. The namespace is used to tell Laravel where our controllers will be located. The middleware is what middleware should be run before allowing access to these routes. The routes() method itself is where we place our routes that the user can access. Let's add our routes that we know we will need.

<?php

namespace App\Services\ToDo\Http\Routes;

use Illuminate\Routing\Router;
use JumpGate\Core\Contracts\Routes;
use JumpGate\Core\Http\Routes\BaseRoute;

class TaskList extends BaseRoute implements Routes
{
    public $namespace = 'App\Services\Http\Controllers';

    public $middleware = [
        'web',
        'auth',
    ];

    public function routes(Router $router)
    {
        $router->get('create')
            ->name('task-list.create')
            ->uses('TaskList@create')
            ->middleware('active:task-list.create');
        $router->post('create')
            ->name('task-list.create')
            ->uses('TaskList@store');

        $router->get('edit/{id}')
            ->name('task-list.edit')
            ->uses('TaskList@edit')
            ->middleware('active:task-list.edit');
        $router->post('edit/{id}')
            ->name('task-list.edit')
            ->uses('TaskList@update');

        $router->get('delete/{id}')
            ->name('task-list.delete')
            ->uses('TaskList@delete');

        $router->get('{id}')
            ->name('task-list.show')
            ->uses('TaskList@show')
            ->middleware('active:task-list');

        $router->get('/')
            ->name('task-list.index')
            ->uses('TaskList@index')
            ->middleware('active:task-list.index');
    }
}

As you can see, once inside the routes() method, everything behaves the same way it does in the Laravel route file. The one thing that may be new is the active:task-list middleware. This is part of our Menu package and is used to add the active class to your links when a user is on that route. The view part is already handled by our menu views so you don't need to do any extra work to make it happen.

You should notice that any route that will be dealing directly with an individual task list has {id} on it. This is how we define a wildcard URL parameter in Laravel.

{primary} A bit of magic happens here. You don't have to define your route classes anywhere. The app/Providers/RouteServiceProvider.php class uses it's load method to automatically find your route classes.

Links

Let's add the links. To do this open app/Http/Composers/Menu.php and go to the generateLeftMenu() method. We are going to add our new links here.

/**
 * Adds items to the menu that appears on the left side of the main menu.
 */
private function generateLeftMenu()
{
    $leftMenu = \Menu::getMenu('leftMenu');

    $leftMenu->link('docs', function (Link $link) {
        $link->name = 'Documentation';
        $link->url  = route('larecipe.index');
    });

    $leftMenu->dropDown('task-list', 'Lists', function (DropDown $dropDown) {
        $dropDown->link('task-list.index', function (Link $link) {
            $link->name = 'All Lists';
            $link->url  = route('task-list.index');
        });
        $dropDown->link('task-list.create', function (Link $link) {
            $link->name = 'Create List';
            $link->url  = route('task-list.create');
        });
    });
}

{success} Learn more about the Menu package

This is how we add links to the menu in JumpGate. You can see at the start we set up the menu object. Calling getMenu() will either create a new menu with that name or find an existing one. Next is the docs link that comes by default with JumpGate. To make a single link in the menu you call the link() method on your menu object. It requires a name and a url to work. The name is used as the text for the link when displaying it and the url is used for where to send the user when they click on it. Moving on, you will see our drop down for task lists. The method dropDown() will create a drop down on a menu object. This behaves almost like a miniature menu object since it can have links applied to it. There is one main difference though. When you use the active middleware, as we said earlier, is used to turn a link active in the view. However, if that link is part of a drop down, the drop down itself is active as well. This is the behavior we want as it allows the user to know where they are in the navigation without much effort or confusion. Inside the drop down we created links to 2 of our 7 routes: index and create. The other 5 are not really linkable since they require the id of a task list to do anything with.

Now do the same thing for our Tasks. Create a Task.php in app/Services/ToDo/Http/Routes.

<?php

namespace App\Services\ToDo\Http\Routes;

use Illuminate\Routing\Router;
use JumpGate\Core\Contracts\Routes;
use JumpGate\Core\Http\Routes\BaseRoute;

class Task extends BaseRoute implements Routes
{
    public $namespace = 'App\Services\ToDo\Http\Controllers';

    public $prefix = 'task';

    public $middleware = [
        'web',
        'auth',
    ];

    public function routes(Router $router)
    {
        $router->get('create/{listId}')
            ->name('task.create')
            ->uses('Task@create')
            ->middleware('active:task.create');
        $router->post('create/{listId}')
            ->name('task.create')
            ->uses('Task@store');

        $router->get('edit/{id}')
            ->name('task.edit')
            ->uses('Task@edit')
            ->middleware('active:task.edit');
        $router->post('edit/{id}')
            ->name('task.edit')
            ->uses('Task@update');

        $router->get('delete/{id}')
            ->name('task.delete')
            ->uses('Task@delete');

        $router->get('{id}')
            ->name('task.show')
            ->uses('Task@show')
            ->middleware('active:task');
    }
}

This file is nearly identical but we replaced task-list with task for our route names and active middleware. We also changed the controller from TaskList to Task. Lastly, we removed the index route since you can view all tasks in a list using task-list.show.

{info} The walkthrough continues in Setting up controllers.