Skip to content

Creating Routes

Adarsh Kumar Maurya edited this page Nov 28, 2018 · 1 revision

Creating Routes

We’ve built our two models and we have our relationships configured, our basic relationships, we can actually get to making the application work.

So we don’t have to do too much more to the actual application to make it function. So the next thing that we’ve got to do is we’ve got to be able to tell the application what to do when it receives an http request. So for that, what we’ll need to do is we’ll need to configure some routes.

So inside of our http directory and namespace, there is a routes.php file and so this is the place that we just go to create all the routes that we need for the actual application itself. To kind of get started we have Laravel gives you by default this basic route path, which is when you run the application you can go to just the route path and you’ll see this welcome screen.

We’ll leave that alone for a minute. We’ll start building some things outside of it. So in order to build a route, you can use this route facade that’s built into Laravel and you just kind of tell it what method you’re looking for, so you can do like GET, you can do POST, you can do PUT, you can do all of the http verbs to let it know what types of requests to look for.

So in this particular case we can just build a route method and for the moment let’s just make it be for products and in order to get it working, at a bare minimum, you can include what is a called a closure, so basically any request that comes to the application for slash products is going to attempt to return the results of this closure and the closure itself can be as something as simple as just returning the results of a model query. It doesn’t have to do anything crazy. So at a bare minimum we can get this application to return a list of all of the products that are configured in our database already.

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Routr::get('products',function(){
  return App\Product::all();
});

So what we’re telling the application to do now is that okay we’ve got our products route, any GET request to the products route should return the full collection of all of the products that are in the database and what we’re using is we’re using the product model and there’s an all method that sits on top of that so that’s some of that Eloquent magic that’s kind of baked in there.

Kind of like a select all query. Correct, that’s exactly what that one is. That one is just get me everything that you’ve got and it has some default behavior that will attempt to try and paginate the results for you so that you don’t.

Oh really? So you don’t like blow up the application if there’s millions of records but by default this all is basically exactly that. Select * from table and return all the results.

So if you were to hit that from a web just a browser, is it going to return any kind of formatted list or anything or is it just going to be like PHP objects?

So that’s actually something great that’s built into Laravel is that if a route simply returns say a collection from Eloquent, then it will turn it into JSON by default.

So if you actually want HTML, you can create view objects and return those responses, but by default it tries to help make sure that your development speed is much faster so it’s going to carry the opinion that this collections object that gets return needs to be serialized down to JSON. So if you actually went to this route right now in a browser or even in something like Postman it will return a JSON collection of all of the products that are in the database.

Great. Do you want to try it out? All right, let’s check it out. Cool. So in order to get it so that you can access it, I’m going to start a small web server that’s going to serve the project.

Adarsh:product-service adarshmaurya$ php artisan serve --host=192.168.0.6
Laravel development server started: <http://192.168.0.6:8000>

So to do that, we just do PHP Artisan serve and then I’m going to tell it to serve from a host name that is local to my machine so that way you can access it from across the network. So now if you actually, do you have your Postman?

http://192.168.0.6:8000/products

So inside of Postman, so right now we just have products. So you can actually run a GET request here and it should pull up the nine products that we’ve got in the database.

[
    {
        "id": 1,
        "name": "beats",
        "created_at": "2018-11-27 21:48:56",
        "updated_at": "2018-11-27 21:48:56"
    },
    {
        "id": 2,
        "name": "meats",
        "created_at": "2018-11-27 21:48:56",
        "updated_at": "2018-11-27 21:48:56"
    },
    {
        "id": 3,
        "name": "greets",
        "created_at": "2018-11-27 21:48:56",
        "updated_at": "2018-11-27 21:48:56"
    },
    {
        "id": 4,
        "name": "beats",
        "created_at": "2018-11-27 22:00:02",
        "updated_at": "2018-11-27 22:00:02"
    },
    {
        "id": 5,
        "name": "meats",
        "created_at": "2018-11-27 22:00:02",
        "updated_at": "2018-11-27 22:00:02"
    },
    {
        "id": 6,
        "name": "greets",
        "created_at": "2018-11-27 22:00:02",
        "updated_at": "2018-11-27 22:00:02"
    },
    {
        "id": 7,
        "name": "beats",
        "created_at": "2018-11-27 22:01:16",
        "updated_at": "2018-11-27 22:01:16"
    },
    {
        "id": 8,
        "name": "meats",
        "created_at": "2018-11-27 22:01:16",
        "updated_at": "2018-11-27 22:01:16"
    },
    {
        "id": 9,
        "name": "greets",
        "created_at": "2018-11-27 22:01:16",
        "updated_at": "2018-11-27 22:01:16"
    }
]

So that’s coming just directly from the seeds file, it’s all formatted in a JSON array? Yep. So these are the data records that the seeder put into the current database that we’ve got. But now we’re actually hosting the application. There’s a route configured to get you a collection of all of the products, so we can kind of start to see the application start to do work for us.

So the next thing that we want to do is so whenever I’m building these routes I like to reference them in other parts of the application. So if I’m building some pads or I want to actually return a fully qualified URL for a particular resource, I want to be able to do that without hard coding those values.

So one of the things you can do inside of Laravel when you’re configuring these routes is that you can actually include a couple parameters or a couple options that will help make this process work. So in order to do that, you can just include, instead of it just being the route path name and then a closure you can include everything inside of an array with some key value pairs and then the final item in the array should be the closure.

So here we can include one that’s called as and then you can come up with a name for it, so we can just call this like products.

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('products',[
  'as' => 'products'
  function(){
    return App\Product::all();
  }
]);

And so now, if I ever need to reference this route anyplace else in the application, I can just use there’s a built in method that’s just called route, and it accepts a parameter that is this keyed name and it will actually just go and try and build that route for you for whatever the value actually is and then give you the full URL instead of constantly trying to like work with just the paths themselves. Right? So if this route actually changes, the other part of the application won’t need to be updated, as long as it keeps the same name.

So I use the naming inside of these routes as just a way to keep my brain straight as far as like what I’ve built and what it’s actually doing. So we have a name, we have one that’s called products and it’s returning all of the product collection that’s inside here.

Something else that’s pretty common to do is that you might want to build route groups. So route groups just let you kind of collect individual routes and assign some kind of blanket default behavior to them.

So in this case, what we’re actually looking to do is you know, we want all of our API end points to live underneath this API sort of directory in the URL so we can go through and we can add we could say okay well, for each of these routes we want it to be api/products and we could build more routes like that. But we don’t really need to do that because we actually have these route groups available to us.

So here, much like building a GET, a PUT, or a POST, you can just do route group and this is going to accept an array of arguments and then return and have a closure as well, and so the closer just’s how we kind of tell it what to do next, and so whenever we put our route inside of this closure, this route group is now encapsulating the previous route that we put in, right? So since our requirement is that we want the actual route itself to have the prefix of like slash API then slash products, we can use a prefix keyword in our options here, and we’ll just put API. So now our previous route has not changed, it’s still the exact same that it was before, but now in order to access this route, we won’t just do slash products, we could do slash API slash products.

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::group(['prefix' => 'api'],function(){
  Route::get('products',[
    'as' => 'products',
    function(){
      return App\Product::all();
    }
  ]);

});


Route::get('products',[
  'as' => 'products',
  function(){
    return App\Product::all();
  }
]);

So why don’t you give that a try and see how it works? Nice. Same results. Great. So there’s some other things that these groups let you do.

There’s some other sort of internal infrastructure to support things called middlewares inside of Laravel. And middlewares are kind of ways to apply you know you might want to check for authentication, you might want to manipulate the incoming request and these route groups give you a great way to kind of do that for buckets of routes themselves instead of going through and manually adding them to each of them. So, for instance, instead of it just being slash API we might have like slash admin, that’s where we have all of our administrative stuff, and we might need a way to say all of the routes inside of this admin group need to make sure that the people who are accessing them are logged in and have an admin role.

The real value of the groups are to help you apply like bulk policy to multiple routes.

So even though we’re only going to have a couple routes in our project, it’s still good to use and still good to consider how it might be useful. Now we’ve got our products route wrapped in this route group that says okay the prefix is going to be API and what we want to do is we actually want to make sure that this is even working correctly.

So we’re going to kind of broach a little bit of the testing that’s included in the framework, so let’s just write a very basic test that’s going to make sure that this route is actually functioning the way that we’d hoped to.

So when we go into our project here, we can go down to the tests directory and you can see that there’s already an example test that’s been configured, and this test is just out of the box, it should always pass because we haven’t actually changed the framework, but it just basically checks to see that whenever the test engine visits the route path, that it actually sees the view that is included in the project which just has that response pf 200.

So what we’ll do in order to make our test function is that we’ll just duplicate this test and then we’ll just say test products list. We just want to bring it back down to something very basic, we want to start talking about the HTTP verbs are.

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ExampleTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }

    public function testBasicExample()
    {
       $this->visit('/')
            ->see('Laravel 5');
    }

    public function testProductList()
    {
      $this->get(route('products'))
           ->assert(ResponseOk());

    }
}

We configured a GET route, for our path, so we want to say GET and then for the parameter that we pass into this GET method, this is where we actually want to use our route method. So we named our route, right now it’s just products, so as we pass that into the GET method in our test case, we can just say route and then put products in there and then what this is going to do is it’s actually going to perform sort of a psuedo HTTP request against the application, and then we can add some assertions against that to see if it actually came up okay.

So instead of saying See something, cause we’re not actually going to see a response, right now let’s just make sure that the response is okay. So is see just for when it’s returning a view?

So see is some that method is kind of some helpful sugar in the framework that actually there’s like a crawler, like a DomCrawler that’s been included in the project and it starts to go in and actually investigate and try and figure out you know what all’s in there. But the framework itself is trying to give you a lot of shortcuts so you don’t actually have to go find a DomCrawler, tell it what to look for, tell it how to make sure that the assertion’s going to work correctly, so it makes testing go really, really fast. That’s great. There’s a lot of those built in to the framework and those are some new enhancements that came out with 5.

So now we can actually, we’ve got our test built, we’re going to go and we’re going to pull down the route for products, which will actually be API slash products, but again we don’t have to tell it to do that, we’re just going to say access this route by name, and then it’s going to go perform that request and then when it comes back it’s going to check to see if the HTTP response status code is 200.

So we’re in good shape, right? So our application is working. You’ve seen it visually work, and we now have some automated tests to let us know that it’s functioning correctly.