Kohana: The Swift PHP Framework

Kohana: The Swift PHP Framework

Kohana is a PHP 5 framework that uses the Model View Controller (MVC) architectural pattern. There are several reasons why you should choose Kohana but the main ones are security, weightlessness and simplicity. In this tutorial, I’ll introduce its main features, and, with a simple demonstration, I’ll show you how much time Kohana can potentially save you.

Step 1: What is Kohana?

Kohana is a PHP5 framework that uses the Model View Controller architectural pattern. MVC keeps application logic
separate from the presentation. This allows us to create cleaner code and save time for bug searching.
In unfamiliar with this pattern:

  • A Model represents data on which the application operates. Usually a database.
  • A View contains presentation code such as HTML, CSS and JavaScript.
  • A Controller interprets input from the user and sends to the model and/or view.

Kohana was originally a fork of CodeIgniter (CI), which is an open-source product from EllisLab. There are many similarities between CI and Kohana, but all of the code is either new or completely rewritten. As you can read on the official Kohana web site, the main features are:

  • Highly secure
  • Extremely lightweight
  • Short learning curve
  • Uses the MVC pattern
  • 100% UTF-8 compatible
  • Loosely coupled architecture
  • Extremely easy to extend

Step 2: Downloading Kohana

Let’s get started. Visit Kohana’s official web site http://kohanaphp.com and click on the green box in the right corner to download the latest version. All Kohana libraries, helpers, and views are included in the default download package, but you may select extra modules, vendor tools, and languages if you want. For the purpose of this tutorial, the default package can be enough. Click on “Download Kohana!” to begin the download.

Step 3: Installing Kohana

Once you’ve finished downloading it:

  1. Unzip
  2. Rename the “Kohana_vx.x.x” folder to “kohana” and upload it to your web server document root
  3. Edit the global configuration file application/config/config.php as follows
  4. $config['site_domain'] = 'localhost/kohana';
  5. If you are using a unix-like system, the installation’s subdirs may have lost their permissions during zip extraction. Chmod them all to 755 by running find . -type d -exec chmod 755 {} \; from the root of your Kohana installation.
  6. Make sure the application/logs and application/cache directories are writeable. Chmod to 666.
  7. Now, point your browser to http://localhost/kohana/. Automatically, the framework will call the install.php script and check for your server requirements.

Kohana will run in nearly any environment with minimal configuration. There are a few minimum server requirements:

  • Server with Unicode support
  • PHP version >= 5.2.3
  • An HTTP server. I suggest you use XAMPP. XAMPP is an easy all-in-one tool to install MySQL, PHP and Perl.
  • Database (MsSQL, MySQL, MySQLi, PostgreSQL, PDOSqlite)

There are also some required extensions.

  • PCRE
  • iconv
  • mcrypt
  • SPL

If your installation completes successfully, you will be redirected to this test page:

If any of the tests fail, you must correct them before moving forward.

If all tests have passed, go to the Kohana directory and remove or rename the install.php script. Refresh, and you will see a welcome page like this:

Step 4: Configuring Kohana

Kohana is ready to go. No other configuration is needed. This framework is amazing. Isn’t it? Let’s review some code. Follow me.

Step 5: Your first Kohana Project

Canonical programming tutorials start with the “Hello world” example. I think, instead, that a simple application can give you a clear idea how the framework works. So, we will build a CD collection manager — just for a fun demonstration. Before we start coding, a brief introduction to Kohana file system is required.

Our application will be placed in the application folder. In this folder there are several sub folders but we need the following for our project:

  • config folder hosts all the configuration files coded as simple static arrays.
  • controllers folder hosts our custom controllers class
  • models folder hosts our custom models class
  • views folder hosts our custom files written in HTML (or any markup language or script needed to display data and interface controls to the user)

The remaining sub folders are not required for this tutorial, so I invite you to learn more on the Kohana web site.

The system folder host the Kohana core and the Kohana tools like libraries, helpers and predefined configuration files. In this project we will use some libraries and some helpers – good tools to speed up your work.

The assets folder is not a predefined Kohana folder. I have created it for media files like CSS, JS, and images. I’ll show you how to include these files in the project.

The modules folder is the place to put reusable collections of related files that together add a particular functionality to an application. The authentication module, provided by the Kohana team, is an example of module.

This is a very brief introduction to the Kohana file system, but it’s enough for the purposes of this tutorial. I don’t want to bore you more with theory.

Step 6: Project Database

I have chosen MySQL as my DBMS, but remember that Kohana also supports MsSQL, MySQLi, PostgreSQL, PDOSqlite. Create a database called “cd_collection” or choose the name you prefer, and run the following SQL through phpMyAdmin or any tool to handle the administration of MySQL.

CREATE TABLE `albums` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) collate utf8_bin NOT NULL,
  `author` varchar(50) collate utf8_bin NOT NULL,
  `genre_id` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `genre_id` (`genre_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=19 ;

INSERT INTO `albums` (`id`, `name`, `author`, `genre_id`) VALUES
(2, 'Lines, Vines And Trying Times', 'Jonas Brothers', 16),
(3, 'The E.N.D.', 'The Black Eyed Peas', 16),
(4, 'Relapse', 'Eminem', 18),
(5, 'Monuments And Melodies', 'Incubus', 1),
(6, 'Thriller', 'Michael Jackson', 16),
(7, 'Back in Black', 'AC/DC', 4),
(8, 'The Dark Side of the Moon', 'Pink Floyd', 4),
(9, 'Bat out of Hell', 'Meat Loaf', 4),
(10, 'Backstreet Boys', 'Millennium', 16),
(11, 'Rumours', 'Fleetwood Mac', 4),
(12, 'Come on Over', 'Shania Twain', 16),
(13, 'Led Zeppelin IV', 'Led Zeppelin', 4),
(14, 'Jagged Little Pill', 'Alanis Morissette', 4),
(15, 'Sgt. Pepper''s Lonely Hearts Club Band', 'The Beatles', 16),
(16, 'Falling into You', 'Céline Dion', 16),
(17, 'Music Box', 'Mariah Carey', 16),
(18, 'Born in the U.S.A.', 'Bruce Springsteen', 4);

CREATE TABLE `genres` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) collate utf8_bin NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=22 ;

INSERT INTO `genres` (`id`, `name`) VALUES
(1, 'Alternative Rock'),
(2, 'Blues'),
(3, 'Classical'),
(4, 'Rock'),
(5, 'Country'),
(6, 'Dance'),
(7, 'Folk'),
(8, 'Metal'),
(9, 'Hawaiian'),
(10, 'Imports'),
(11, 'Indie Music'),
(12, 'Jazz'),
(13, 'Latin'),
(14, 'New Age'),
(15, 'Opera'),
(16, 'Pop'),
(17, 'Soul'),
(18, 'Rap'),
(20, 'Soundtracks'),
(21, 'World Music');

ALTER TABLE `albums`
  ADD CONSTRAINT `genre_inter_relational_constraint` FOREIGN KEY (`genre_id`) REFERENCES `genres` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

As you can see, the SQL creates two tables, albums and genres, and populates them with some data. The last SQL statement adds a constraint for the foreign key “genre_id”.

The database structure is very simple and doesn’t need much explanation.

Now, you have to tell Kohana where your database is located and how to access it. Edit the global configuration file system/config/database.php as follows

$config['default'] = array
(
	'benchmark'     => TRUE,
	'persistent'    => FALSE,
	'connection'    => array
	(
		'type'     => 'mysql',	
		'user'     => 'root',	
		'pass'     => 'root',	
		'host'     => 'localhost',	
		'port'     => FALSE,		
		'socket'   => FALSE,		
		'database' => 'cd_collection'
	),
	'character_set' => 'utf8',
	'table_prefix'  => '',
	'object'        => TRUE,
	'cache'         => FALSE,
	'escape'        => TRUE
);

This code tells Kohana to connect to a MySQL database called “cd_collection” on localhost with the username “root” and the password “root”. You have to change these settings according to your database server configuration.

Step 7: Create the Controller

Let’s now create our first controller. Remember these conventions.

  • controller filename must be lowercase, e.g. album.php
  • controller class must map to filename and capitalized, and must be appended with _Controller, e.g. Album_Controller
  • must have the Controller class as (grand)parent

Also, remember how Kohana structures its URLs and how you can call a controller method; e.g http://hostname/kohana_directory/index.php/controller/function.

Let’s take a look at this simple controller.

<?php defined('SYSPATH') OR die('No direct access allowed.');

class Album_Controller extends Controller
{ 
	public function __construct()	
 	{ 
		parent::__construct();
	}
 	
	public function index()
 	{
 	  	echo "My first controller";	
	}
}

PHP5 OOP is a prerequisite. So if you aren’t well-versed, you can learn more here.

The constructor function, called __construct, initializes the class and calls the parent constructor.
The index function is the default function, so it will be called if we call the controller without
specifying any function (e.g. http://localhost/index.php/kohana/album. After the name controller
there isn’t any function, the default index function will be called.)

Given these basic rules, let’s focus on our application. The album controller implements all the actions for
the albums collection management. This controller allows us to create a new album, to show the albums stored in our database,
to update an album, and to delete an album.

So, let’s change the class as follows.

Create a file called album.php in application/controllers/ and paste the following.

<?php defined('SYSPATH') OR die('No direct access allowed.');
	
class Album_Controller extends Controller
{
	 private $album_model; 
	 private $genre_model;
	 
	 private $list_view;
	 private $create_view;
	 private $update_view;
 
	public function __construct()	
 	{ 
		parent::__construct();
		$this->album_model   = new Album_Model;
		$this->genre_model  	= new Genre_Model;
	  	$this->list_view   	= new View('list');
	  	$this->update_view  	= new View('update');
	  	$this->create_view  	= new View('create');
	}
 
 	public function index()
 	{
  		$this->show_albums_list();
 	}
		
	private function show_albums_list()
	{
		$albums_list = $this->album_model->get_list(); 
		$this->list_view->set('albums_list',$albums_list);
		$this->list_view->render(TRUE); 
	}
	
 	public function show_create_editor()
 	{
 		$this->create_view->set('genres_list',$this->get_genres_list());
  		$this->create_view->render(TRUE);
 	}
 
 	public function show_update_editor($id)
 	{
		$album_data = $this->album_model->read($id);
		$this->update_view->set('album_id',$album_data[0]->id);
		$this->update_view->set('name',$album_data[0]->name);
		$this->update_view->set('author',$album_data[0]->author);
		$this->update_view->set('genre_id',$album_data[0]->genre_id);
		$this->update_view->set('genres_list',$this->get_genres_list());
		$this->update_view->render(TRUE);
 	}
 
 	public function create()
 	{ 
		$album_data=array(
		'name'    	=> $this->input->post('name'),
		'author'  	=> $this->input->post('author'),
		'genre_id'  => $this->input->post('genre_id')
		);
		$this->album_model->create($album_data);
		url::redirect('album');
 	}
 
	public function update()
	{ 
		$album_data = array(
			'name'    	=> $this->input->post('name'),
			'author'  	=> $this->input->post('author'),
			'genre_id'  => $this->input->post('genre_id')
		);
		$this->album_model->update($this->input->post('album_id'),$album_data);
  		url::redirect('album');
 	}
  
  	public function delete($id)
 	{
		$this->album_model->delete($id);
		url::redirect('album');
 	}
 
	private function get_genres_list()
	{
		$db_genres_list  = $this->genre_model->get_list(); 
		$genres_list  = array();
		
		if(sizeof($db_genres_list) >= 1)
		{
			foreach($db_genres_list as $item)
			{
				$genres_list[$item->id] = $item->name;
			}
		}
		return $genres_list;
 	}
}

Let me explain what this code does.

Five members variables are declared at the top of the class:

private $album_model; 
private $genre_model;
		 
private $list_view;
private $create_view;
 private $update_view;

These members are private because I want to limit visibility only to this class.

In the construct method the model and view objects are created using the five members:

$this->album_model   = new Album_Model;
$this->genre_model  	= new Genre_Model;
$this->list_view   	= new View('list');
$this->update_view  	= new View('update');
$this->create_view  	= new View('create');

To create a model object use this syntax:

$obj_name = new Name_Model;

To create a view object, use this syntax:

$obj_name = new View('view_filename_without_extension');

Now there are two objects to access the album and genre model, and three objects to access the views needed to render the presentation.

The index method call the show_albums_list method that lists all albums stored in the database.

$albums_list = $this->album_model->get_list(); 
$this->list_view->set('albums_list',$albums_list);
$this->list_view->render(TRUE); 

In this method you can see how the model and view object are used to access relative methods. “get_list” is a model method (we will see it later) that returns all the albums stored in the database. The result is saved in the “$album_list” array. To pass the result array from the controller to the view, the “set” method is called on the view object. This method requires two parameters: a new empty variable (album_list) to contain data of an existing variable ($album_list). Now the new variable “album_list” contains the $album_list array (we will see later how to show the content in the view). The method “render”, with the TRUE parameter, is necessary to output data to the browser.

The show_create_editor method shows the user interface to insert a new album.

$this->create_view->set('genres_list',$this->get_genres_list());
$this->create_view->render(TRUE);

The list of the genres is passed to the view.

The show_update_editor method shows the user interface to update an existing album.

$album_data = $this->album_model->read($id);
$this->update_view->set('album_id',$album_data[0]->id);
$this->update_view->set('name',$album_data[0]->name);
$this->update_view->set('author',$album_data[0]->author);
$this->update_view->set('genre_id',$album_data[0]->genre_id);
$this->update_view->set('genres_list',$this->get_genres_list());
$this->update_view->render(TRUE);

“read” is a model method (we will see it later) that returns data ($album_data) of the album with an id equal to $id. Then, every single element of the returned data album is passed to the view.

The create method receives data, for a new album, from the view and data are stored in the database.

		$album_data=array(
		'name'    	=> $this->input->post('name'),
		'author'  	=> $this->input->post('author'),
		'genre_id'  => $this->input->post('genre_id')
		);
		$this->album_model->create($album_data);
		url::redirect('album');

$album_data is an array that contains the POST data from the view. To save the album, the array is passed to the create model method. The last line is a call to a helper method. Helpers are simply functions that assist you with development. The helper classes are automatically loaded by the framework. Helpers are declared as static methods of a class, so there is no need to instantiate the class. In this case the method “redirect” of the helper “url” is called and tells Kohana to redirect the browser to the album controller. This avoids a new insert (for example pressing F5).

“Helpers are simply functions that assist you with development.”

The update and delete methods work in the same manner as the create method above.

The last method get_genres_list gets the genres list from the model ($db_genres_list) and builds a new array ($genres_list) for the select box in the views.

		$db_genres_list  = $this->genre_model->get_list(); 
		$genres_list  = array();
		
		if(sizeof($db_genres_list) >= 1)
		{
			foreach($db_genres_list as $item)
			{
				$genres_list[$item->id] = $item->name;
			}
		}
		return $genres_list;

Step 8: Create Project Model

Let’s now create models for our web application. Remember these conventions.

  • model filename must be lowercase, e.g. album.php
  • model class must map to filename and be capitalized, and must be appended with _Model, e.g. Album_Model
  • must have the Model class as (grand)parent

Here is the album model code. Create a file called album.php in application/models/ and paste the code below on it.

<?php defined('SYSPATH') OR die('No direct access allowed.');

class Album_Model extends Model
{
 	private $album_table;
 	private $genre_table; 
 
  	public function __construct()
    	{
      		parent::__construct();
  		$this->album_table = 'albums';
		$this->genre_table = 'genres';
  	}
  
  	public function read($id)
  	{
		$this->db->where('id', $id);
		$query = $this->db->get($this->album_table); 
  		return $query->result_array();
 	}
  	
	public function delete($id)
  	{
		$this->db->delete($this->album_table, array('id' => $id));
  	}
  
  	public function update($id,$data)
  	{
		$this->db->update($this->album_table, $data, array('id' => $id));
  	}
  	
	public function create($data)
  	{
   		$this->db->insert($this->album_table, $data);
  	}
 	
	public function get_list()
 	{
  		$this->db->select('albums.id as id,albums.name as name,albums.author as author, genres.name as genre');  
  		$this->db->from($this->album_table);  
  		$this->db->join($this->genre_table,'genres.id','albums.genre_id');
  		$query = $this->db->get();
  		return $query->result_array();
	}
}

All the methods in the models make use of the Query builder syntax. This Kohana tool speeds up database development times and simplify the queries creation.

Two members variables are declared at the top of the class:

			private $album_table;
			private $genre_table; 
	

These members are private because I want to limit the visibility only to this class. They are the containers for the database tables names.

The first line in the constructor method loads the Kohana database library into $this->db. In the second and third lines the two class members are initialized.

parent::__construct();
$this->album_table = 'albums';
$this->genre_table = 'genres';

The query in the read method retrieves album records that have a certain identifier (“$id”).

			$this->db->where('id', $id);
		 	$query = $this->db->get($this->album_table); 
	  	 	return $query->result_array();
	

The query in the delete method deletes the albums table row that have a certain identifier (“$id”).

$this->db->delete($this->album_table, array('id' => $id));
	

The query in the update method updates the albums table row that has a certain identifier (“$id”) with new values from the “$data” array.

$this->db->update($this->album_table, $data, array('id' => $id));
	

The “$data” array must contain record names as keys of the array, and value as values of the array. The “$data” array must have this form:

$data = array(
	'name' 			=> 	'album_name',
	'author'		=>	'author_name',
	'genre_id'		=>	'genre_id'	
	);
	

The query in the create method inserts a new record with values of the “$data” array.

$this->db->insert($this->album_table, $data);
	

The “$data” array must have this form:

$data = array(
	'id'			=>	'album_id',
	'name' 			=> 	'album_name',
	'author'		=>	'author_name',
	'genre_id'		=>	'genre_id'	
);
	

The query in the get_list method retrieves all the albums rows.

		$this->db->select('albums.id as id,albums.name as name,albums.author as author, genres.name as genre');  
		$this->db->from($this->album_table);  
		$this->db->join($this->genre_table,'genres.id','albums.genre_id');
		$query = $this->db->get();
		return $query->result_array();
	

Now, the genre model. Create a file called genre.php in application/models/ and paste the code below it:

	<?php defined('SYSPATH') OR die('No direct access allowed.');

	class Genre_Model extends Model
	{
		private $genre_table;
	
		function __construct()
		{
			parent::__construct();
			$this->genre_table = 'genres';
		}
	
		function get_list()
		{
			$query = $this->db->get($this->genre_table);
			return  $query->result_array();		
		}
	}
	

This model is very simple so I’ll waste no further time to comment upon it. The Models and the controller are ready to go. Let’s now work on the Views.

Step 9: Create the Project View

Views are files that contain the presentation layer for your application. The purpose is to keep this information separate from your application logic for easy reusability and cleaner code. For this project, three views are required: a view to list the album collection, a view to create a new album, and a view to edit an existing album.

Create a file called list.php in application/views/ and paste the following code in:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<?php
	echo html::stylesheet(array
		(
		 'assets/css/style'
		),
		array
		(
		 'screen'
		), FALSE);
?>
		<title>CD COLLECTION</title>
		</head>
		<body>
		<?php 
				echo html::image('assets/images/add.png');
				echo html::anchor('album/show_create_editor', 'Add new album'); 
		?>
		<table class="list" cellspacing="0">
		<tr>
			<td colspan="5" class="list_title">CD Collection</td>
		</tr>	
		<tr>
			<td class="headers">Album name</td>
			<td class="headers">Author</td>
			<td colspan='3' class="headers">Genre</td>
		
		</tr>	
		<?php
			foreach($albums_list as $item)
			{
				echo "<tr>";
				echo "<td class='item'>".$item->name."</td>";
				echo "<td class='item'>".$item->author."</td>";
				echo "<td class='item'>".$item->genre."</td>";
				echo "<td class='item'>".html::anchor('album/delete/'.$item->id,html::image('assets/images/delete.png'))."</td>";		
				echo "<td class='item'>".html::anchor('album/show_update_editor/'.$item->id,html::image('assets/images/edit.png'))."</td>";		
				echo "</tr>";
			}
		?>
		</table>
		</body>
		</html>
	

This view shows an html page containing a list of all albums. This list has been created using foreach loop that prints the information in an html table. For each album row, there are two images: a “red cross” and a “pocketbook”. They link respectively the controller delete method and the update method. Both pass the album id to the album controller using a get request. Above the list there is a button to create new albums. In this code we also make use of an html helper provided by Kohana that speeds up operations to write html pages.

Let’s now create a file called create.php in application/views/.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<?php
	echo html::stylesheet(array
	(
	    'assets/css/style'
	),
	array
	(
	    'screen'
	), FALSE);
?>
<title>CD COLLECTION</title>
</head>
<body>
<?php echo form::open('album/create'); ?>
<table class='editor'>
<tr>
	<td colspan='2' class='editor_title'>Create new album</td>
</tr>
<?php
	echo "<tr>";
	echo "<td>".form::label('name', 'Name: ')."</td>";
	echo "<td>".form::input('name', '')."</td>";
	echo "</tr>";
	
	echo "<tr>";
	echo "<td>".form::label('author', 'Author: ')."</td>";	
	echo "<td>".form::input('author', '')."</td>";	
	echo "<tr/>";
	
	echo "<tr>";
	echo "<td>".form::label('genre', 'Genre: ')."</td>";	
	echo "<td>".form::dropdown('genre_id',$genres_list)."</td>";
	echo "<tr/>";
	
	echo "<tr>";
	echo "<td colspan='2' align='left'>".form::submit('submit', 'Create album')."</td>";
	echo "</tr>";
?>
</table>
<?php echo form::close(); ?>
</body>
</html>

The last but not the least is the update view. Let’s create a file called update.php in application/views/.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<?php
	echo html::stylesheet(array
	(
	    'assets/css/style'
	),
	array
	(
	    'screen'
	), FALSE);
?>
<title>CD COLLECTION</title>
</head>
<body>
<?php echo form::open('album/update'); ?>
<table class='editor'>
<tr>
	<td colspan='2' class='editor_title'>Update album</td>
</tr>
<?php
	echo "<tr>";
	echo "<td>".form::label('name', 'Name: ')."</td>";
	echo "<td>".form::input('name', $name)."</td>";
	echo "</tr>";
	
	echo "<tr>";
	echo "<td>".form::label('author', 'Author: ')."</td>";	
	echo "<td>".form::input('author', $author)."</td>";	
	echo "<tr/>";
	
	echo "<tr>";
	echo "<td>".form::label('genre', 'Genre: ')."</td>";	
	echo "<td>".form::dropdown('genre_id',$genres_list, $genre_id)."</td>";
	echo "<tr/>";
	
	echo "<tr>";
	echo "<td colspan='2' align='left'>".form::submit('submit', 'Update album')."</td>";
	echo "</tr>";
	
?>
</table>
<?php 
	echo form::hidden('album_id',$album_id);
	echo form::close(); 
?>
</body>
</html>

The first one is a simple editor that enables the user to insert information about a new album.
The fields like author and name will be inserted using an html input and genre using a
combo box. Once the user clicks on the create button, all information is passed,
as a POST request, to the create/update method in the album controller. When the controller receives these posted
variables, it calls the model that inserts a new album into the database. The forms, in both views, makes use of Kohana form helper.

To give a bit of style to our application, create the assets folder in the Kohana root at the same level of the application folder. Now, open it and create two new folders: css and images.

In the css folder create a new file called style.css and paste this:

a {
	font-family: Verdana, Geneva, Arial, Helvetica, sans-serif ;
	font-weight: normal;
	font-size: 12px;
	color: #00F;
	vertical-align:text-top;
}

img {
	border: 0;
}

label {
	font-family: Verdana, Geneva, Arial, Helvetica, sans-serif ;
	font-weight: normal;
	font-size: 12px;
}

input {
	border: 1px solid #000;
}

select {
	width:185px;
}

table.editor
{
	text-align: center;
	font-family: Verdana, Geneva, Arial, Helvetica, sans-serif ;
	font-weight: normal;
	font-size: 11px;
	color: #fff;
	width: 280px;
	background-color: #666;
	border: 0px;
	border-collapse: collapse;
	border-spacing: 0px;
}

table.editor td.editor_title
{
	background-color: #666;
	color: #fff;
	padding: 4px;
	text-align: left;
	font-weight: bold;
	font-size: 16px;
} 

table.editor td
{
	padding: 4px;
} 

table.list
{
	text-align: center;
	font-family: Verdana, Geneva, Arial, Helvetica, sans-serif ;
	font-weight: normal;
	font-size: 11px;
	color: #fff;
	width: 280px;
	background-color: #666;
	border: 0px;
	border-collapse: collapse;
	border-spacing: 0px;
}

table.list td.item
{
	background-color: #CCC;
	color: #000;
	padding: 4px;
	text-align: left;
	border: 1px #fff solid;
}

table.list td.list_title,table.list td.headers
{
	background-color: #666;
	color: #fff;
	padding: 4px;
	text-align: left;
	border-bottom: 2px #fff solid;
	font-weight: bold;
} 

table.list td.list_title
{
	font-size: 16px;
} 

table.list td.headers
{
	font-size: 12px;
}

Now copy the following images to the images folder:  

That’s all. Point your browser to http://localhost/kohana/index.php/album and you should see something similar to this:

If you try to create a new album or to edit an existing one you should see something similar to this:

Step 10: Final Thoughts

Of course, some improvements are required for this application but with a small amount of code, you’ve created a little web application.
Now, you know how to use the MVC pattern with Kohana, and how to use database libraries and helpers. To learn more, read the official documentation.

Thanks to Kohana, code maintenance is an easy task, and adding new features is a cinch. I hope you enjoyed this tutorial. Stay tuned to learn more about Kohana.


Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.getonepage.com Gafitescu Daniel

    I see it is very similar to CodeIgniter

  • http://ethan.turkeltaub.org Ethan

    Very cool! I will be sure to try this. And it has some very in-depth documentation.

    (I can’t help but notice you misspelled Michael)

  • http://www.stevedurr.co.uk Steve

    Wow, this seems realy good. Very light weight.

    I am currently using Symfony (due to my current job and am quite liking it) but this seems much lighter. I had begun to use cakePHP, when I first got in to php OOP, which also seems good. I found cake very good as a beginner to OOP.

    I intend to focus on Kohana for the time being as it seems very simple.

  • http://blog.andyhot.gr Andreas Andreou

    Coming from the java world and having used Kohana for the last 5-6 months, i only have good words to say for it.

    I18N is another of its strong points but basically its simple and clean MVC will get you up and running from the first minute.

    There are a few tricks you can use that i haven’t seen documented (like using multiple views/view fragments to compose the full result – sort of like the component-based frameworks in java, i.e. tapestry, jsf) but this should improve over time

    Eagerly waiting for v3.0

  • http://presbyteryofglasgow.org.uk/yearbook_2009 Calum MacLeod

    I had been learning kohana for a few weeks with some help from the patient folk at #kohana on freenode. I had also tried a tutorial called Kohana 101, which was a good place to start. However, this tutorial on making a CD Collection, listing albums, updating the list and deleting items has been a further revelation. I have benefitted from both tutorials. The first laid the groundwork and this latter has show what is possible for someone such as myself who is not a programmer and has limited knowledge, ability and insight. Some of us who dabble as a hobby in php and general computing need as much help as we can get and we need to examine good and orderly examples of code that works. The clarity of the presentation in this tutorial is very impressive.

    (The only downside that I shall mention was that that the copy to clipboard function seemed to keep copying the same file to my clipboard and I had not realised until I had copied the whole lot ! However, not everyone will be as dozy as I am and would notice earlier that it was not working for them. Indeed, it might be some lack of expertise on my part that caused it not to function as it ought. If you find you have error messages complaining of redeclaring classes, it may well be that you too have fallen foul of this problem. )

    I wish all tutorials could be as clear, informative and helpful as this one.

  • http://www.sonergonul.com/blog/ Soner Gönül

    Great ;)

  • exiled

    My CSS style sheet is no tbeing applied. I have created an assets/css directory and its not working. Can someone explain to me how to get it work and also the images directory too.

    • Cristian Gilè
      Author

      Have you created the assets folder in the right place?

      Create the assets folder in the Kohana root at the same level of the application folder. Now, open it and create two new folders: css and images.

      Kohana root
      |
      |__application
      |
      |__assets
      | |
      | |__css
      | |
      | |__images
      |
      |__modules
      |
      |__system

      You can view the generated HTML code and check the href attribute of the link tag to solve this issue.

  • sumit mukhia

    wowwwwww..i’ll give it a go tonight…..thanks again for an amazing tutorial..

  • http://webstik.com Nick

    Vary good framework I see!!

  • http://www.demogeek.com DemoGeek

    I’ve been developing a simple site with CodeIgniter. Initially it was a bit exciting to see we can get things done pretty quick but then it died-down on me because of the lack of OO as I come from OO background. Kohana seems to fill that gap and might have my business if they can spread out some more detailed documentation similar to the way CI has their documentation.

  • http://www.designfellow.com Senthil Kumar

    Nice Article.
    I’ve already tried kohana before 2 months.
    I am using CodeIgniter Now.
    May be, I’ll go back .

    Senthil Kumar
    designfellow.com
    @designfellow

  • http://pennyquotes.net Lamonte

    For a beginner KohanaPHP user sure you can follow this tut. No one uses the “set” method for views anymore.

    Your:
    $this->update_view->set(‘album_id’,$album_data[0]->id);

    Easily could be redone like:
    $this->update->view->album_id = $album_data[0]->id;

    Also you used sizeof() to count the amount?

    Dude thats a waste of time since theres a built in “count()” method for the Query Builder …

    if(sizeof($db_genres_list) >= 1)

    Should be:

    if($db_genres_list->count() >= 1)

    • http://www.zamshed.info Zamshed Farhan

      Thanx Lemonte. Very helpful information u gave.

  • http://milesj.me/ Miles Johnson

    The whole structure and procedure of this framework is wrong. Why do you have to initialize everything yourself? The point of a framework is to make it easy for your and to do it automatically.

    No other framework seems to get it right except CakePHP or Symfony.

    • http://www.kohanaphp.com/ loonies

      I would dissagree at this point with Miles Johnson.

      The point of framework is to alleviate with common activities performed in development, like DB access, data validation, session management, etc.

      Personally I prefer to have control over application execution.

      • Christian

        I think Miles using Cake and Symfony that why he is asking……..
        Not ready to learn new method and techniques ;)

        100% agreed with loonies,

        Great Tutorial.

      • http://milesj.me/ Miles Johnson

        I disagree with you, that is what libraries and classes are for.

        Not a framework.

        A good percentage of people who work in PHP do it procedurally wrong, and with browsing Kohana, they do it wrong.

      • Rafi B.

        Agree with loonies. I messed around with all the popular frameworks, and decided Kohana is the best way _for me_ to go. Total control of your application, great ORM module, perfect hierarchy, it’s really for serious coders who know what their doing. All in all, perfect framework in my opinion.

  • Zoran

    Lack of documentation makes this framework sucks so much… Anyway thanks for the tutorial

  • acul

    Wow.. great tutorial. I have to try and make me falling in love with Kohana. thanks

  • arturas

    thanks for tut! hope read yours tuts in future!

  • damian

    Good job.
    It is what I looked for, thanks.

  • Chris Simpson

    Fantastic stuff. the Kohana / CI choice at work is approaching so ill be sure to look closely at this.

  • Althalos

    I really like this framework. I’ve been taking a closer look at it for the past couple of days and it seems really great. Good article too, I like how it’s written and what it brings up… but, alas, I can’t get it to work. For some reason it won’t use my config file with my mysql-info, instead it uses the default user and password (dbuser/p@assword).

  • http://www.kamaroc.com Kamal El Fatihi

    Westing lotse of time

    lots lots of time to just dowing that !!

    im not agree with any of the php framworks as Rasmus said .

  • ahmad

    gr8 will giv it a try

  • Althalos

    Um.. just wanna say I eventually figured my problem out (read two posts above). It might help anyone to know that at the top of database.php there’s supposed to be a <?php .. or at least that’s how I got it working.

  • Jimmy

    Hmm… seems so complicated to me.. I saw DooPHP the other day. That’s a whole lot easier than this tutorial. If any newbies like me are interested.
    http://doophp.com

  • memati

    i get this error:
    Fatal error: Class ‘Genre_Model’ not found in C:\AppServ\www\kohana\application\controllers\album.php on line 16

  • Ste

    Great, thanks. I’ve just started to develop with a framework. I hope to see more kohana tuts here. ;)

  • Rafi B.

    +1 Kohana. v3 is awesome!!!

  • http://maxtheitpro.com Maxwell

    Great tutorial dude!
    I’ll definitely peek back once I dig into Kohana. It’s amazing how far PHP has come over the past 10 years — really. Heck, LAMP (Linux, Apache, MySQL, PHP) kicks ass!! And best of all, it’s frigging FREE!

    Cheers!

    - MaxTheITpro

  • http://www.zamshed.info Zamshed Farhan

    It is the most great tutorial to learn Kohana for beginners.

  • Robert P

    Pointless instantiation and eager-loading? If these examples reflect accepted practices for developing with Kohana then you can count me out.

    How much of a poorly developed framework will people accept in “getting the job done”?

  • marcin_qu

    
    Fatal error: Using $this when not in object context in C:\Program Files\VertrigoServ\www\kohana\application\models\genre.php on line 2

  • marcin_qu

    sorry for higher comment this error is:
    
    Fatal error: Class ‘Genre_Model’ not found in C:\Program Files\VertrigoServ\www\kohana\application\controllers\album.php on line 16

    memati have the same problem

  • prince

    this is great example. Is there any example available on how to enable authentication module and how to restrict site pages for signed in users only?

    thanks in advance

  • http://jontao.com jon tao

    wow! this is my first attempt at trying out a framework and i have to admit…this is pretty amazing!

  • skv

    i know little bit kohana , i was much confused , how to do it,
    but this is really interesting.
    Thanks a lot.

    if any one doubt , can ask me here.

  • http://www.beakvision.com Paul

    Great tutorial!!!! Thank you!!! It’s just what I needed to wrap my head around Kohana! Many thanks & keep up the great work!

  • James

    Excellent tutorial. This has really gotten me started in understanding the Kohana framework.

    I had just one question. How would I go about viewing the list, update, and create “views” inside the template class?

    Thanks for any help. I am really new to this framework.

  • Mehul Shah

    I was very confused before 2 days when i was going to learn framework of kohana. I am very new to world of framework. I tried much to find good tutorials on net. Today, i found this site & have now learned the concept of kohana by running these application. Thanks to author.

  • BhavinRana

    Not A Good Tutorial .I am Always Getting So May Errors when i copy and paste your code into my application,And i think i have to invent my own framework with all possibilities of not getting an single error.
    If You Don’t Know How to Develop or Create Framework Then Why Are You Doing So….

    Very Very Bad Framework…………..

  • http://njielitumbe.livejournal.com landfish

    @BhavinRana A tutorial may have bugs but it is not supposed to be a strictly copy-paste;it is supposed to serve for the purpose of understanding the framework.

    Kohana is a great framework especially with the ORM.I did a little application with it latlety to get familiar with the framework.It has taken me a week;With CodeIgniter I did take 2 weeks.

    The tutorial is great!

  • http://tellingmachine.com Klaus Graefensteiner

    Great Tutorial!

    I just started with Kohana and your tutorial was a big help.

  • http://www.uvlonline.com Ulrich

    many thanks to you. previously i used CI, although many similarities, but i feel more comfort using this framework.
    It is a big help for me :)

  • Jesse

    Wow, thank you so much. I was looking for a real world project and not a load of theory ideas of how to use Kohana (MVC in general). Thank you for taking the time and showing us.

  • hussain

    i test kohana framework , its a great ….
    but how i can make kohan read arabic text
    please help me

  • daniel

    This tutorial is great! Kohana is impressive, but as I see in the current versions there are some changes:
    Controller names should not be named like: Sample_Controller, but Controller_Sample, also most of the code presented in this tutorial will probably not work in the current Kohana version 3.0.5. This tutorial looks more like CodeIgniter code.

    • Tony

      Dan, you’re looking at the V3+ branch which is a complete rewrite of the version used in this tutorial (V2, which was based on CodeIgniter… hence the similarity).

      Although it looks the same with subtle changes, V3 is a completely separate project — don’t let the version numbers confuse you. The main difference is HMVC, allowing you to write your projects in an SOA format and split your code into chunks a lot easier… using HMVC in Kohana 3 you can have different routes map to different servers with 1 line of code!

      It’s definitely worth checking out the forums & unofficial wiki by Kerkness (http://kerkness.ca/wiki/doku.php) for more information.

      Kohana is without a doubt the best framework I’ve seen — it’s awesome!

  • Tung Nguyen

    Hi,

    I am newbie with Kohana. I have downloaded lasted Kohana and built application follow up instruction above. However, when I built views, I got an error like this:

    Fatal error: Class ‘html’ not found in D:\TungDir\Projects\www\CDOnline\application\views\list.php on line 6

    I used debugger and found out the code stopped at this line: echo html::stylesheet(array….

    How can I use html::stylesheet?

    Regards,
    Tung Nguyen

  • Praveen

    Where is the “system/config/database.php” file?
    I’m using Kohana v3.0.7

  • http://www.dk-unlocked.co.cc Deepesh Kapadia

    Hey I followed your tutorial step by step but in the end I get the following error:
    ErrorException [ Fatal Error ]: Class ‘Database’ not found

    SYSPATH\classes\kohana\model.php [ 54 ]

    }
    if (is_string($this->_db)
    {
    // Load the database
    $this->_db = Database::instance($this->_db);
    }
    }

    } // End Model

    1.{PHP internal call} » Kohana_Core::shutdown_handler()

    Any idea how to fix this problem??

  • Dimitri

    Why instantiate all views and models in the constructor ?!
    It’s not good for performance …

    We must instantiate only what you need, and do so in the actions.

  • Praveen

    hi,

    i ma using v2 and getting all thing done with album or picture gallery but stuk on this error. here.

    Kohana_PHP_Exception [ Fatal Error ]: Call to undefined method Database_Mysql::select()

    DOCROOT/application\models\album.php[ 39 ]

    34 $this->db->insert($this->album_table, $data);
    35 }
    36
    37 public function get_list()
    38 {
    39 $this->db->select(‘albums.id as id,albums.name as name,albums.author as author, genres.name as genre’);
    40 $this->db->from($this->album_table);
    41 $this->db->join($this->genre_table,’genres.id’,'albums.genre_id’);
    42 $query = $this->db->get();
    43 return $query->result_array();
    44 }

    1.

    {PHP internal call} » Kohana_PHP_Exception_Core::shutdown_handler(arguments )
    0

    NULL

    2.

    DOCROOT/system\core\Event.php[ 210 ] » call_user_func_array(arguments )
    function_name

    array(2) (
    0 => string(20) “Kohana_PHP_Exception”
    1 => string(16) “shutdown_handler”
    )

    parameters

    array(1) (
    0 => NULL
    )

    205 Event::$data =& $data;
    206 $callbacks = Event::get($name);
    207
    208 foreach ($callbacks as $callback)
    209 {
    210 call_user_func_array($callback, array(&$data));
    211 }
    212
    213 // Do this to prevent data from getting ‘stuck’
    214 $clear_data = ”;
    215 Event::$data =& $clear_data;

    3.

    DOCROOT/system\core\Kohana.php[ 528 ] » Event_Core::run(arguments )
    name

    string(15) “system.shutdown”

    523 return;
    524
    525 $run = TRUE;
    526
    527 // Run system.shutdown event
    528 Event::run(‘system.shutdown’);
    529
    530 // Close output buffers
    531 Kohana::close_buffers(TRUE);
    532
    533 // Run the output event

    4.

    {PHP internal call} » Kohana_Core::shutdown()

  • http://dagrevis.lv/ daGrevis

    I do request tutorial for Kohana 3.1.x! =]]