Skip to content

Lecture 1.7: Routing, Requests and Controllers

DA edited this page Aug 25, 2019 · 7 revisions

Routing

The very first thing that you need to do when building your application is structuring your URIs in a flexible and scalable way that is agnostic of how your application files are structured. This framework does it all for you. What you need to focus your effort on is planning where the URIs should go.

Defining Routes

A route file is provided for you /application/config/routing/web.php. This is where your routes should be defined. There are 4 route methods available

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::delete($uri, $callback);

Your first reaction might be that HTML forms do not support PUT and DELETE. True that and the framework is capable of doing that work for you. You can check here how it is done.

"Hello World" Route

The most basic route provides a simple way to execute any method (through Closure) upon the definition of the route.

try {
    Route::get('helloworld', function() {
            echo 'Hello World';
    });
} catch (Exception $e) {
    echo $e->getMessage();
}

You should be able to access it by navigating to http://your-app/helloworld in your browser. If you have not changed the name of the app folder caligrafy then you could use http://localhost/caligrafy/helloworld.

Routing with parameters

It is not unusual to want to capture variables from the URI to act on them. For example if you want to access all the information on a specific book, you would want the URI to be http://your-app/books/1 where 1 is the id of the book that you want.

In order to do that with this framework you need to use {variablename} syntax:

Route::get('books/{id}', function() {
   // any code would go here
});

By doing so, any value that you put after books/ will be captured and you will be able to use it in your code. So if you navigate to http://your-app/books/1, your code will be able to capture 1. Similarly, if you replace the one with another value, your code will be able to capture that value. Later you will learn how you can fetch this value in your code.

Controller Routing

In an MVC structure, you most likely want to route to a controller to hand off the logic to a controller class that will handle executing that logic. In order to do this, you could define a route that will call the controller:

Route::get('books', 'BookController');

This route will redirect all calls to http://your-app/books to the controller BookController.

You could also specify a specific method from the BookController to execute:

Route::get('books', 'BookController@read');

This route would call the method read from BookController. Later on, you will learn how to create controllers.

Requests

The Request class provides you with the flexibility to get all the information needed about a request made to your application. The Request class exists in the context of a successful route. In other words, if the routing is not successful then there is no easy way to have access to the Request class and to leverage its powerful functionalities.

Accessing the Request

From the moment a route is successful, the Request class is available for use.

  • It can be accessed from the context of any Class created in the /application folder by invoking a global helper method:
request();
  • In the context of a Controller, the Request is a property of these classes:
use Caligrafy\Controller;

class BookController extends Controller {
   public function test()
   {
       dump($this->request); // will return the entire request object
   }
}

Learn more about Requests here

Controllers

A Controller is a key entity in an MVC architecture. It is the layer that is responsible for interfacing with both the Model and the View. It takes its input from a View, interfaces with the Model to either get information or add to the information, it calls upon any other logic that needs to be applied to the information and finally sends it back to the View to be displayed.

Most of the concepts that we covered thus far - Routing, Request, Models, Relationships, Validation, Views - come into play together in the context of a Controller.

Creating a Controller

  • All the controllers that you create should be in the /application/controllers folder. In this folder, you can organize the controllers to your convenience. If you prefer to have your controllers in a different folder, you can always do that for as long as it is within the /application folder.

  • There is no formal naming convention for a controller. We do recommend that you remain consistent.

Learn more about naming conventions here

  • All the controllers that you create should extend the Controller class
use Caligrafy\Controller;

class BookController extends Controller {
    // your code goes here
}
  • The controllers that you create need to have at the very least, an index method. The index method gets called by default when no method is specified in the Route.
use Caligrafy\Controller;

class BookController extends Controller {
    // index method
    public function index()
    {
       // your code goes here
    }
}
  • Controllers usually cover all the actions that can be taken on the Model that it controls. It is therefore common to have several other methods within a controller.
use Caligrafy\Controller;

class BookController extends Controller {
    // index method
    public function index()
    {
       // your code goes here
    }
    public function read()
    {
       // your code goes here

    }
}

Routing to the Controller

In the Routing section, we covered the basics of how to route a request to a Controller or to a specific method within the controller. We will summarize them herewith.

The following route will redirect all calls to http://your-app/books to the index method in the BookController:

Route::get('books', 'BookController');

The following route will redirect all calls to http://your-app/books to the read method in BookController:

Route::get('books', 'BookController@read');

Controller Context

Frameworks are meant to help organize and structure code. Some frameworks impose that a Controller be tied to a Model and imposes a naming convention that forces developers to have a single controller for a model.

Our framework provides the flexibility to create a controller that is independent of a model and it allows changing its context at any point using the associate method that takes a Model and a database table name arguments and returns a Controller:

public function associate(Model $model, String $tablename);`

Let's consider the books example again. Assume you have a Book and a Publisher models in an online library system. In a model-constrained framework, if you need to allow the users to make changes to the Publisher model, you will need to have a dedicated PublisherController.

In this framework, you could change the context in methods or even within the same method:

use Caligrafy\Controller;

class MyController extends Controller {

    public function readBook()
    {
       // associate the controller with the Book model and the books table
       $this->associate('Book', 'books'); 
       
       // all controller methods executed below will be in the context of Book
     }
     public function addPublisher()
     {
       // associate the controller with the Book model and the books table
       $this->associate('Publisher', 'publishers'); 

       // all controller methods executed below will be in the context of Publisher
 
     }
}

Controller Methods & Properties

  • Methods can be created as needed in a controller provided they don't override the built-in Controller methods. From the moment you override these methods, the framework could behave abnormally.

  • Despite the fact that there is no prescriptive way on how to organize the logic within a method, we recommend the following logical structure:

use Caligrafy\Controller;

class MyController extends Controller {
   
    public function myMethod()
    {
       // Context: set the context of the controller by association with model and table 
       
       // Retrieve & Validate: fetch any parameters needed from the request when applicable and validate it
       
       // Model: Create a model when applicable based on the retrieved data or the data to be changed

       // Act: perform the action on the model

       // View: return a view with the output of the action
    }

}
  • From the moment a Controller is a created as previously described, powerful built-in methods and properties are provided out of the box.

Learn more about Controller Methods and Properties here