Lithium Framework: Getting Started

Daniel Sipos

Lithium is a lean but mean PHP framework (machine?) built for PHP 5.3 and up. It is designed to provide a good toolset for starting your web application, but one that is not too confining.

Lithium uses the Model-View-Controller(MVC) architecture and this is what we are going to look at in this article. I will show you how it works and how you can define some of your application’s business and presentation logic using this framework. There are a few things we will do in this respect.

We will set up a Controller to route URL requests to. This Controller will get and process some information from the database with the help of a data Model. This information will then be displayed in the browser using a View. All standard MVC stuff, but a real pleasure to perform with Lithium.

I will assume you already have the framework set up on your server to the point that you can at least see the default app starting page if you navigate to the URL. Additionally, you’ll need a database populated with some information. I’ll use MySQL but Lithium supports a number of other storage systems like MongoDB or CouchDB.

I have set up a Git repository that you can clone if you want to follow along. The master branch contains the vanilla Lithium framework whereas the MVC branch contains the code from this article. Don’t forget to also init and update the lithium submodule. To connect your database, make a copy of the connections_default.php file located in the app/config/bootstrap folder and rename it connections.php. Then add your credentials inside that file.

Let’s begin.

The data

Before getting into the fun MVC stuff, let’s get a table into our database with some information. I will be working with dummy page data so my table (called pages) will contain an id column (INT, auto increment and primary key), a title column (varchar 255), a content column (text) and a created column (INT). And in this table I have 2 sample rows. If you want to follow along exactly, here is the table create statement:

CREATE TABLE `pages` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `content` text,
  `created` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

And here are my dummy rows:

INSERT INTO `pages` (`id`, `title`, `content`, `created`)
VALUES
    (1, 'My awesome page title', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', 1397158745),
    (2, 'Some other page title', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', 1397158768);

Of course, you can use something else.

C stands for Controller

Controllers are probably the most important part of any MVC framework. Their role is to process requests routed to it by the application’s routing system.

If you look in the app/controllers/ folder of your application you’ll see that this is where we have to put ours. Let’s create there a new file called SiteController.php (each Controller class resides in its own file) and paste in the following class declaration to get started:

<?php

namespace app\controllers;

class SiteController extends \lithium\action\Controller {

}

As you can see we are extending the Lithium base controller class into our own called SiteController. Inside this class you create methods that perform the logic needed when they are requested from the URL. We’ll see this in action in a minute, but first, let’s understand how the routing works.

By default, when constructing the URL, we use arguments that map to the names of the Controller class (in our case, site), methods and parameters. If no method name is passed, Lithium will assume one by itself called index(). So if you navigate to http://example.com/site/, Lithium will look for this method and call it. Now let’s say we have a method called view() that takes 1 argument ($id). The URL to call that Controller method is http://example.com/site/view/1, where view is the name of the method and 1 is the parameter that gets passed to this function. And if the method gets more parameters, you just pass them in the URL separated by slashes (/).

However, like I mentioned, this is the default behavior. For more control, you can define routes yourself in the /app/config/routes.php file. I won’t go into details but you can find more information on the appropriate documentation page.

Now let’s go ahead and create a page() method that will be in charge of displaying individual pages from my dummy database:

public function page() {

    // Mock page info.
    $title = 'My awesome page title';
    $content = 'My awesome page content. Yes indeed.';
    $created = '10 April 2014';

    // Prepare page info for passing to the View.
    $data = array(
      'title' => $title,
      'content' => $content,
      'created' => $created,
    );

    // Pass the data to the View.
    $this->set($data);

}

Above, we mock database page information and store it an array. We then pass this array to the set() method of the Controller class (that we inherit) and this gets sent on to the View. Alternatively, we can also return the $data array instead of using the set() method. But in both cases, the keys of the array represent the variable names that we can then access from our View file. Let’s see how that works.

V stands for View

Views are the presentation layer of an MVC framework. They are used to keep the business logic of the application separate and to allow for an easy theming of what gets displayed to the browser.

Let’s create a View to display our page information. In the app/views/ folder you need to create another folder named after the Controller class that uses it (in our case, site). Inside this folder, you have to create a file named after the method itself, appended with the .html.php extension. This is the Lithium naming convention for Views that makes it very easy for us to connect them to Controllers.

So for our page example, the new file will be at app/views/site/page.html.php.

Inside this file, paste the following:

<!-- Title -->
<h1><?=$title ?></h1>

<!-- Created date -->
<p><?=$created ?></p>

<!-- Main content -->
<div class="content">
  <?=$content ?>
</div>

As you probably already guessed, this is some basic markup into which we print the variables named after the array keys passed from the Controller. Lithium uses this syntax to print variables because it also runs them through its $h() function which is responsible for sanitizing HTML. This applies however only to when you print variables and not properties of the $this object.

To test out what we have so far, navigate to http://example.com/site/page and you should see a nice page with the mock information displayed. You’ll also notice that our simple View is rendered inside a more complex layout (the default one that comes with the framework).

Layouts in Lithium are used to wrap content with commonly used markup such as headers and footers. They live in the app/layouts folder and they use $this->content() to render the View inside. Our View is rendered by default inside the default.html.php layout but you can specify another one if you want. You do this from the Controller that renders the View, either as a class property to be applied to all methods of that Controller, or inside the method itself like this:

public function page() {

    // Method logic ...

    $this->_render['layout'] = 'yourLayout';   
}

We will stick to the default one because it looks nice for our demonstration purposes.

M stands for Model

Now that the request and presentation logic are taken care of, its time to replace the mock page data with our dummy database content. We will use a Model to abstract and easily access this information.

Model classes are a very important part of an MVC framework because they define and handle the content in your database. They also make it easy for the application to perform CRUD (create, read, update, delete) operations on this data. Let’s see how they work in Lithium.

The first thing you need to do is create a class file in the app/models folder called Pages.php and inside paste the following:

<?php

namespace app\models;

class Pages extends \lithium\data\Model {

}

We are just extending the base Model class and making use of all its methods. The name of our Model class needs to match the database table that contains the relevant records. So if yours is not pages, make sure you adapt accordingly because Lithium will automatically pick up on this naming to make things easier for us.

Next, we need to include this file in our Controller class file, so paste the following below the namespace declaration:

use app\models\Pages;

It follows to remove the mock content from the page() method and make sure this function gets passed an $id parameter so that we know which page we need to retrieve. And we are left with the simple task of querying for the page record and passing the results to the View. So the revised page() method will look something like this:

public function page($id) {

    // Look for the first record that matches the passed criteria
    $record = Pages::first(array('conditions' => array('id' => $id)));
    $page = $record->data();

    // Prepare page info for passing to the View.
    $data = array(
      'title' => $page['title'],
      'content' => $page['content'],
      'created' => date('F j Y', $page['created']),
    );

    // Pass the data to the View.
    $this->set($data);

}

We are using the first() method of the Model parent class to query using conditions. The result is an object from which we retrieve the record data using the data() method. And that is in the form of an array keyed by the name of the table columns. The rest is like before except for the created field that we format using the PHP date() function since we are getting a UNIX timestamp from the database. And that’s pretty much it.

If we navigate to http:example.com/site/page/1, we should see the page with the ID of 1. If we switch the last URL argument to 2, the page should load the second record. Neat.

Conclusion

In this tutorial we’ve seen how easy it is to understand and work with the Lithium MVC framework. We’ve learned how to define Controllers, Views and Models and how to use them together to create a neatly separated application process. We’ve also seen how helpful the Lithium conventions are to get us started. Without even knowing it we abstracted our database content and exposed it for very easy access.

I hope you learned something and are curious enough to go a bit more in depth and look at the other powerful features Lithium has to offer. What are some of the built in CRUD methods and how can you extend them? How can you define your own custom routes? How can you use multiple layouts and even render smaller elements within your Views? These are all great features Lithium offers us for our web application and are worth checking out.

Did I make you curious? Want to read more about this great framework?

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Fraser Murray

    The routes documentation link is broken.

    • http://www.bitfalls.com/ Bruno Skvorc

      Thank you, fixed!

  • Zvika

    Please mention the DEV branch as initial repo, the Master has not been updated in a while and misses all the funnn!