Request Flow in Kohana 3

Exclusive offer: get 50% off this eBook here
Kohana 3.0 Beginner’s Guide

Kohana 3.0 Beginner’s Guide — Save 50%

Develop professional web applications with Kohana.

$26.99    $13.50
by Jason D. Straughan | September 2011 | Open Source

Kohana utilizes the HMVC design pattern, and allows us to create requests essentially anywhere within our applications. The request flow is the order in which files are loaded, starting with index.php and moving throughout the framework, loading essential files, processing the requests, and rendering any output.

In this article by Jason D. Straughan, author of Kohana 3.0 Beginner’s Guide, we will learn:

  • What HMVC is, and how it works
  • Kohana’s Request Flow
  • How to use the Request class

 

(For more resources on this topic, see here.)

The reader can benefit from the previous article on Routing in Kohana 3.

 

Hierarchy is King in Kohana

Kohana is layered in more ways than one. First, it has a cascading files system. This means the framework loads files for each of it’s core parts in a hierarchical order, which is explained in more detail in just a bit. Next, Kohana allows for controllers to initiate requests, making the application workflow follow a hierarchical design pattern. These features are the foundation of HMVC, which essentially is a cascading filesystem, flexible routing and request handling, the ability to execute sub-requests combined with a standard MVC pattern.

The framework manages locating and loading the right file by using a core method named Kohana::find_file(). This method searches the filesystem in a predetermined order to load the proper class first. The order the method searches in is (with default paths):

  • Application path (/application)
  • Modules (/modules) as ordered in bootstrap.php
  • System path (/system)

Cascading filesystem

As the framework loads, it creates a merged filesystem based on the order of loading described above. One of the benefits of loading files this way is the ease to overload classes that would be loaded later in the flow. We never have to, nor should we, alter a file in the system directory. We can override the default behavior of any method by overloading it in the application directory.

Another great advantage is the consistency this mechanism offers. We know the exact load order for every class in any application, making it much easier to create custom code and know exactly where it needs to live.

Kohana 3.0,Beginner's Guide

This image shows an example application being merged into the final file structure that will be used when completing a request. We can see how some classes in the application layer are overriding files in the modules.

This makes it easier to visualize how modules extend and enhance the framework by building on the system core. Our application then sits on top of the system and module files, and then can build and extend the functionality of the module and system layers. Kohana also makes it easy to load third-party libraries, referred to as vendor libraries, into the filesystem.

Each of the three layers has five basic folders into which Kohana looks:

  • Classes (/classes) contain all autoloaded class files. This directory includes our Controller, Models, and their supporting classes. Autoloading allows us to use classes without having to include them manually. Any classes inside this directory will automatically be searched and loaded when they are used.
  • Config files (/config) are files containing arrays that can be parsed and loaded using the core method Kohana::config(). Some config files are required to configure and properly load modules, while others may be created by us to make our application easier to maintain, or to keep vendor libraries tidy by moving config data to the framework. Config files are the only files in the cascading filesystem that are not overloaded; all config files are merged with their parent files.
  • Internationalization files (/i18n) make it much easier to create language files that work with our applications to deliver the proper content that best suits the language of our users.
  • Messages (/messages) are much like configuration files, in that they are arrays that are loaded by a core Kohana method. Kohana:: message() parses and returns the messages for a specific array. This functionality is very useful when creating forms and actions for our applications.
  • View files (/views) are the presentation layer of our applications, where view files and template files live.

 

Request flow in Kohana

Now that we have seen how the framework merges files to create a set of files to load on request, it is a good place to see the flow of the files in Kohana. Remember that controllers can invoke requests, making a bit of a loop between controllers, models, and views, but the frameworks always runs in the same order, beginning with the index.php file.

The index.php file sets the path to the application, modules, and system directories and saves them to as constants that are then defined for global use. These constants are APPPATH, MODPATH, and SYSPATH, and they hold the paths for the application, modules, and system paths respectively. After the error-reporting levels are set, Kohana looks to see if the install.php file exists.

If the install file is not found, Kohana takes the next step in loading the framework by loading the core Kohana class. Next, the index file looks for the application’s Kohana class, first in the application directory, then in the system path. This is the first example of Kohana looking for our files before it looks for its own.

The last thing the index file does is bootstrap our application, by requiring the bootstrap.php file and loading it.

You probably remember having to configure the bootstrap file when we installed Kohana. This is the file in which we set our base URL and modules; however, it is a bit more important than just basic installation and configuration.

The boostrap begins by setting a some basic environment settings, like the default timezone and locale. Next, it enables the autoloader, and defines the application environment. This tells the framework whether our application is in a production or development environment, allowing it to make decisions based on its environment-specific settings.

Next, the default options are set and Kohana is initialized, with the Kohana::init() method being called. After Kohana’s initialization, it sets up logging, configuration reading, and then modules.

Modules are loaded defined using an array, with the module name as the key, and the path to the module as the value. The modules load order is listed in this array, and are all subject to the same rules and conventions as core and application code.

Each module is added to the cascading file system as described above, allowing files to override any that may be added later when the system files are merged. Modules can contain their own init files, named init.php, that act similar to the application bootstrap, adding routes specific to the modules for our application to use.

The last thing the bootstrap does in a normal request flow is to set the routes for the application. Kohana ships with a default route that loads the index action in the welcome controller.

The Route object’s set method accepts an array that defines the name, URI, and defaults for the parameters set for the URI. By setting default controllers, actions, and params, we can have dynamic URLs that have default values if none are passed.

If no controller or action is passed in the URI on a vanilla Kohana install, the welcome controller will be loaded, and the index action invoked as outlined in the array passed to the Route::set() method in the boostrap.

Once all the application routes are set via the Route::set() method and init.php files residing in modules, Request::instance() is invoked, setting the request loop into action. As the Request object processes the request, it looks through routes until it finds the right controller to load. The request object then instantiates the controller, passing the request to the controller for it to use.

The Controller::before() method is then called, which acts much like a constructor. By being called first, the before() method allows any logic that need to be performed before a controller action is run to execute. Once the before method is complete, the object continues to load the requested functions, just like when a constructor is complete.

The controller action, a method in the controller class, is then called, and once complete, it returns the request response. The action method is where the business logic for the request will reside.

Once the action is complete, the Controller::after() method is called, much like the destructor of a standard PHP class.

Because of the hierarchical structure of Kohana, any controller can initiate a new request, making it possible for other controllers to be loaded, invoking more controller actions, which generate request responses.

Once all the requests have been fulfilled, Kohana renders the final request response.

The Kohana request flow can seem like it is long and complex, but it can also be looked at as very clean and organized. By using a front controller design pattern, all requests are handled by just one file: index.php. Each and every request that is handled by our applications will begin with this one file. From there the application is bootstrapped, and then the controller designed to handle the specific request is found, executed, and displayed. Although, as we have seen, there is more that is happening, for most of our applications, this simple way of looking at the request flow will make it easy to create powerful web applications using Kohana.

 

Using the Request object

The request flow in Kohana is interesting, and it is easy to see how it can be powerful on a high level, but the best way to understand HMVC and routing in Kohana is to look at some actual code, and see what the resulting outcome is for real world scenarios.

Kohana’s Request object determines the proper controller to invoke, and acts as a wrapper for the response. If we look at the Template Controller that we are extending in our Application Controller for the case study site, we can follow the inheritance path back to Kohana’s template controller, and see the request response.

One of the best ways to understand what is happening inside the framework is to drill down through the filesystem and look at the actual code. One of the great advantages of open sources frameworks is the ability to read the code that makes the library run.

Opening the welcome controller located at application/classes/controller/welcome.php, we see the following class declaration:

class Controller_Welcome extends Controller_Application

The first thing we see in the base controller class is that it extends another Controller, and then we see the declaration of an object property named $request. This variable holds the Kohana_Request object, the class that created the original controller call. In the constructor, we can see that the Kohana_Request object is being type-hinted for the argument, and it is setting the $request object property on instantiation. All that is left in the base Controller class is the before() and after() methods with no functionality.

We can then open our Application Controller, located at application/classes/controller/application.php. The class declaration in this controller looks like this:

abstract class Controller_Application extends Controller_Template

In this file, we can see the before() method loading the template view into the template variable, and in the after() method, we see the Request obeject ($this->request) having the response body set, ready to be rendered. This class, in turn, extends the Template Controller.

The Template Controller is part of the Kohana system. Since we have not created any controllers in our application or modules the original template controller that ships with Kohana is being loaded. It is located at system/classes/controller/template.php. The class declaration in this controller looks like:

abstract class Controller_Template extends Kohana_Controller_Template

Here things take a twist, and for the first time, we are going to have to leave the /classes/controller/ structure to find an inherited class. The Kohana_Controller_Template class lives in system/classes/kohana/controller/template.php. The class is fairly short and simple, and it has this class declaration:

abstract class Kohana_Controller_Template extends Controller

This controller (system/classes/controller.php) is the base controller that all requested controller classes must extend. Examining this class will let us see the Request class enter the Controller loop and the template view get sent to the Request object as the response.

Walking through the Welcome Controller’s heritage is a great way of seeing how the Request object loads a controller, and how the parent classes all contribute to the request flow in Kohana. It may seem like pointless complexity at first, however, the benefits of transparent extension are very powerful, and Kohana makes the mechanisms work all behind the scenes. But one question still remains: How is the request object aware of the controllers and routes?

Athough dissecting Kohana’s Request Class could be a article unto itself, a lot can be answered by looking at the contstructor in the system/classes/kohana/request.php file. The constructor is given the URI, and then stores object properties that the object will later use to execute the request.

The Request class does have a couple of key methods that can be very helpful. The first is Request::controller(), which returns the name of the controller for the request, and the other is Request::action(), which similarly returns the name of the action for the request.

After loading the routes, the method then iterates through the routes, determines any matches for the URI, and begins setting the controller, action, and parameters for the route. If there are not matches for optional segments of the route, the defaults are stored in the object properties.

When the Request object’s execute() method is called, the request is processed, and the response is returned. This happens by first processing the before() method, then the controller action being requested, then the after() method for the class, followed by any other requests until all have completed.

The topic of initiating a request from within a controller has arisen a few times, and is the best way to illustrate the Hierarchical aspect of HMVC. Let’s take a look at this process by creating a controller method that initiates a new request, and see how it completes.

 

Kohana 3.0 Beginner’s Guide Develop professional web applications with Kohana.
Published: August 2011
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

 

(For more resources on this topic, see here.)

 

Creating a profile page to render messages

In our case study site, users will be creating text messages that will be listed on the site. These messages will be displayed on their public profile pages, and as the site grows, they may be viewed elsewhere.

Although the first draft of the site will only show the messages on the user’s page, there could be growth where this content could be rendered in a mobile environment, in other pages, in widgets, or elsewhere. Listing the user’s messages is a core function of the application, after all.

If we created the logic and view to display the messages inside the same controller action that renders the user’s profile page, reusing the code would be difficult, if not impossible. To prevent having to write this logic in several places inside the Egotist application, it is better to create a controller that handles the logic for listing messages for a user, and a view to list out the messages, and then have any pages that use the list to request it from within their corresponding actions.

 

Time for action – Creating a profile page with messages

Using the case study site to illustrate this process, we are going to add a profile controller to handle the public pages for our users. The default page for user’s public pages will be their profile page, with all of their recent messages and information. For now, we will just pass a fake username and some messages to test functionality.

  1. Create a new controller in our application/classes/controller directory named profile.php. This will be our Profile Controller that will be used to display user profiles and related items. In the newly created file, insert the following code:

    <?php defined(‘SYSPATH’) or die(‘No direct script access.’);

    class Controller_Profile extends Controller_Application {

    public function action_index()
    {
    $content = View::factory(<profile/public>)
    ->set(<username>, <Test User>)
    ->bind(<messages>, $messages);
    $messages = array(
    <This is test message one>,
    <This is test message two>,
    <This is test message three>
    );

    $this->template->content = $content;
    }
    }

  2. As we see, this controller’s default action is going to render a view in a directory named profile, with the view file named public. To create this view, we will need to make a folder called profile in the application/views directory.
  3. In our newly created application/views/profile directory, create and open a file named public.php. In this file, insert the following code:

    <h2>Public Profile for <?= $username; ?></h2>
    <h3>Recent Messages:</h3>
    <?php foreach ($messages as $message) : ?>
    <p class=»message»>
    <?= $message; ?>
    </p>
    <?php endforeach; ?>

  4. Open the page http://localhost/egotist/profile/, it should look like this:

    Kohana 3.0,Beginner's Guide

What just happened?

We are at one of the cross roads in application development, where we are best served by thinking about how the application could act in the future, and architect our code in such a manner to anticipate future needs while minimizing code complexity.

We can assume a few things about how this page may act in the future. First of all, it will be rendering dynamic text for each user; therefore, it must have a way to retrieve data based on a particular user. The most common way of doing this is using a database, and retrieving the data from tables filled with user data.

It is also very possible that the messages listed for a user may be viewed in other means, like mobile applications or widgets, and retrieving and listing these messages would be necessary for these other locations.

 

Calling a new request inside a request

Object-oriented programming has many great advantages, too many to list here, but code reusability and abstraction are paramount in leveraging this style of programming. The principle of Don’t Repeat Yourself (DRY) coding is easier to achieve when we write abstracted code that can be used throughout our projects without having to live in more than one place.

Creating controllers that handle specific tasks that can be called directly, or requested from within other controllers or views, makes it much easier to create reusable, DRY code. Our current profile controller has a variable for our user’s name, and an array of their messages. Once a database is added, there will be code to retrieve this, and possibly more, information that will be passed to the view.

Having the logic to handle all of this in the current controller action does not allow for the messages code to be reused in other parts of the site, and is not taking advantage of the HMVC architecture inherent in Kohana. To make our code more reusable and easier to maintain, we should create a controller and view to handle listing user messages.

 

Time for action – Creating a request within a request

Having messages handled and rendered by a separate class allows us to abstract our code for more portability and reuse. Although the messages logic is very simple right now, only passing test data in an array, once a data store and more information tied to messages are introduced, the process could become more complex and needed in other parts of the application.

To fix this, we can simply move the logic to a new controller class.

  1. Create a new controller in our application/classes/controller/ directory named messages.php. This will be our Messages Controller that will be used to display user profiles and related items. In the newly created file, insert the following code:

    <?php defined(‘SYSPATH’) or die(‘No direct script access.’);

    class Controller_Messages extends Controller {

    public function action_index()
    {
    URL::redirect();
    }
    public function action_get_messages()
    {
    $messages = array(
    <This is test message one>,
    <This is test message two>,
    <This is test message three>
    );
    $this->request->response = View::factory(<profile/messages>)
    ->set(<messages>, $messages);
    }
    }

  2. As we see, this controller’s get_messages() action is going to render a view in a directory named profile, with the view file named messages. Create and open a file named messages.php in our application/views/profile directory. In this file, insert the following code:

    <?php foreach ($messages as $message) : ?>
    <p class=»message»>
    <?= $message; ?>
    </p>
    <?php endforeach; ?>

  3. Open the page http://localhost/egotist/messages/get_messages/; it should look like this:

    Kohana 3.0,Beginner's Guide

    The Messages Controller is called and shows the listed messages per the view file. The get_messages action is passing the messages to the view.

  4. To incorporate this new controller into our existing application, we will need to alter our Profile Controller. Open the file located at application/classes/controller/profile.php and modify it like this:

    <?php defined(‘SYSPATH’) or die(‘No direct script access.’);
    class Controller_Profile extends Controller_Application {
    public function action_index()
    {
    $content = View::factory(<profile/public>)
    ->set(<username>, <Test User>)
    ->bind(<messages>, $messages);
    $messages = Request::factory(‘messages/get_messages’)-
    >execute()->response;
    $this->template->content = $content;
    }
    }

  5. Now that our Profile Controller is passing a rendered view into the messages view variable instead of an array, we will need to alter our profile view script. Open the view located in our application/views/profile directory named public.php, and change the code to look like this:

    <h2>Public Profile for <?= $username; ?></h2>
    <h3>Recent Messages:</h3>
    <?= $messages; ?>

  6. Open the page http://localhost/egotist/profile/; it should look like this:

    Kohana 3.0,Beginner's Guide

What just happened?

Again, the creation of a new controller and view should be familiar to us, but there are some things happening this time that are different from our previous experiences. In the Messages Controller, we have an index, or default action that is simply redirecting users back to the home page. As this controller only has one action we are using right now, any accidental navigation to this controller should default to returning users to the default controller and action for the application.

We then created our first non-default action, action_get_messages(). When we viewed this controller action directly, we saw the messages being rendered to the browser, without any template surrounding the HTML.

This is because the Messages Controller is not extending our Application Controller or the Template Controller, but is extending Kohana’s base Controller directly. This is because we want the rendered messages view to be diverse, and have the ability to be rendered inside of other views or controllers.

When we altered our Profile Controller class, we removed the logic that is now living in the Messages Controller, and replaced the $messages view variable contents with this line of code:

$messages = Request::factory(‘messages/get_messages’)
->execute()->response;

Here, we are calling the factory method on the Request object, and telling it to request the Messages Controller’s get_messages action. This is the same request that would be fired if we browsed to http://localhost/egotist/messages/get_messages/. The execute() method then parses the request and loads the response into the Request object’s $request property, which we are calling via chaining. The same line of code could be written as follows for more clarity:

$request = Request::factory(‘messages/get_messages’);
$request->execute();
$messages = $request->response;

In our modified profile view, we replaced the foreach loop that iterated through the messages array and displayed the values with a simple echo statement that prints the results of the Messages request response.

By using this pattern when writing our controllers, we will find our code to be easy to read, maintain, and reuse. As our applications grow, take on new functionality, and require maintenance, this style of coding will make it easier and faster to keep our applications up to date.

Have a go hero – Create a request from within a view

In the case study application, we have created a request from within our Profile Controller, and assigned the executed response to a view variable, which we are then outputting inside the profile view script. Although keeping logic in the controller is important, if no other manipulation is being done, simply content being rendered for output, it can just as well live inside the view. See if you can eliminate the request for messages from the controller, move it to the view, and not change the final output that is rendered when visitng the page.

Summary

In this article we saw how to use request handling to make our applications more robust.


Further resources on this subject:


Kohana 3.0 Beginner’s Guide Develop professional web applications with Kohana.
Published: August 2011
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Jason D. Straughan

Jason D. Straughan is currently a software engineer at LiveOak 360, Inc., a web development firm with a focus on social networking and custom web applications. He is also a founding partner in Straughan Photography (SanAntonioWeddingPhotography.com) and provides consultation and training to a select number of clients through his web consulting firm. You can follow his blog, and read more about Kohana and web-related topics at http://www.JDStraughan.com

Books From Packt


CodeIgniter 1.7 Professional Development
CodeIgniter 1.7 Professional Development

Building Websites with ExpressionEngine 2
Building Websites with Expression Engine 2

Yii 1.1 Application Development Cookbook
Yii 1.1 Application Development Cookbook

Catalyst 5.8: the Perl MVC Framework
Catalyst 5.8: the Perl MVC Framework

ASP.NET MVC 2 Cookbook
ASP.NET MVC 2 Cookbook

PHP 5 CMS Framework Development - 2nd Edition
PHP 5 CMS Framework Development - 2nd Edition

SilverStripe 2.4 Module Extension, Themes, and Widgets: Beginner's Guide
SilverStripe 2.4 Module Extension, Themes, and Widgets: Beginner's Guide

Expert PHP 5 Tools
Expert PHP 5 Tools


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
3
X
E
s
6
S
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software