Sign In  |   Register  

Kohana PHP 3.0 (KO3) Tutorial Part 3

ellisgl | December 30, 2009 | 53 Comments

Welcome to the third part in this series on how to develop with Kohana PHP V3 (KO3). If you haven’t read the first and/or second parts yet, I would click here and read them before going on. In this tutorial we will be going over how to create a template.

In the last tutorial, we went over views and in this one we are going to extend the Controller classes which will allow us to create a template. A template, you might ask, is nothing more than a view that is more or less your base (X)HTML code. This will allow to keep things “DRY” in the view world. Before we get to putting code into a file, lets create a new directory under “/application/views/” named “templates”. Now open up your favorite IDE and make a new file and put the following into it:
[php]
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en” lang=”en”>
<head>
<meta http-equiv=”Content-type” content=”text/html; charset=UTF-8″ />
<meta http-equiv=”Content-Language” content=”en-us” />
<title><?php echo $title;?></title>
<meta name=”keywords” content=”<?php echo $meta_keywords;?>” />
<meta name=”description” content=”<?php echo $meta_description;?>” />
<meta name=”copyright” content=”<?php echo $meta_copywrite;?>” />
<?php foreach($styles as $file => $type) { echo HTML::style($file, array(‘media’ => $type)), “n”; }?>
<?php foreach($scripts as $file) { echo HTML::script($file, NULL, TRUE), “n”; }?>
</head>
<body>
<div id=”container”>
<?php echo $header;?>
<?php echo $content;?>
<?php echo $footer;?>
</div>
</body>
</html>
[/php]
Save the above as “default.php” in your “/application/views/templates/” folder.

As you can see the above pretty much looks like a view we have done before, a bit more expanded. I will go over the “foreach” a little bit later. Unlike a view, this will most likely be used by all of your project. Since we will point to this file for our template, or shell, this will reduce the amount of code you have to put in each view, keeping thing separated, easier to maintain, or basically “DRY”.

Now that we have a template, our system isn’t going to do anything with it until well tell it to use it. So lets go back to our IDE and create a new file and put the following into it:
[php]
<?php
defined(‘SYSPATH’) or die(‘No direct script access.’);

class Controller_DefaultTemplate extends Controller_Template
{
public $template = ‘templates/default’;

/**
* Initialize properties before running the controller methods (actions),
* so they are available to our action.
*/
public function before()
{
// Run anything that need ot run before this.
parent::before();

if($this->auto_render)
{
// Initialize empty values
$this->template->title = ”;
$this->template->meta_keywords = ”;
$this->template->meta_description = ”;
$this->template->meta_copywrite = ”;
$this->template->header = ”;
$this->template->content = ”;
$this->template->footer = ”;
$this->template->styles = array();
$this->template->scripts = array();
}
}

/**
* Fill in default values for our properties before rendering the output.
*/
public function after()
{
if($this->auto_render)
{
// Define defaults
$styles = array(‘assets/css/reset.css’ => ‘screen’);
$scripts = array(‘http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js’);

// Add defaults to template variables.
$this->template->styles = array_reverse(array_merge($this->template->styles, $styles));
$this->template->scripts = array_reverse(array_merge($this->template->scripts, $scripts));
}

// Run anything that needs to run after this.
parent::after();
}
}
[/php]
And save this as “defaulttemplate.php” under your “/application/classes/controller/” folder.

The above code extends the “Controller_Template” class and does three main things, initialize some properties (variables) to be accessable by our methods (actions) and appends default values to them and then gets associates them to our template variables before we render the final output to the screen. This is where the foreach() loop in the template comes into play. The foreach() loop uses a static method for the helper class “HTML” to load CSS style sheets and load JS files. Both of these helper methods will iterate through an array and properly wrap it in the appropriate tag. They can take a path or a URL.

You might be wondering what a “Helper” is, so here is a quick definition from the Kohana PHP 2.x documents:

Helpers are simply “handy” functions that help you with development.

Helpers are similar to library methods, but there is a subtle difference. With a library, you have to create an instance of the library’s class to use its methods. Helpers are declared as static methods of a class, so there is no need to instantiate the class. You can think of them as “global functions”.

As with libraries, the helper classes are automatically loaded by the framework when they are used, so there is no need to load them yourself.

OK, back on course. You might have noticed there is a reference to “assets/css/reset.css”, so lets go ahead and get that in place. In your root create a folder named “assets” and in that folder create one named “css”. For the actual “reset.css” file, I went to Serene Destiny and copied the code from the article titled “Create The Perfect CSS Reset” into a file and saved it as “reset.css” in the “assets/css/” folder. You might want to also set up some other folders within “/assets/”, maybe “images”, “js” and “files”. Basically the assets folder should be used to store and organize static files and such.

At this point, our application still doesn’t know what to do what we have done, so we need to modify our controller. So open “/application/classes/controller/ko3.php”.
We want to change what class we are extending, so change the line:
[php]class Controller_Ko3 extends Controller[/php]
to:
[php]lass Controller_Ko3 extends Controller_DefaultTemplate[/php]

We also need to change up our “index” action (action_index() method) to look like the following:
[php]
public function action_index()
{
$ko3_inner = array();
$ko3 = array();
$this->template->title = ‘Kohana 3.0′;

View::set_global(‘x’, ‘This is a global variable’);

$ko3_inner['content'] = ‘We have more data’;
$ko3['content'] = ‘We have data’;
$ko3['ko3_inner'] = View::factory(‘blocks/ko3_inner’, $ko3_inner)
->render();
$this->template->content = View::factory(‘pages/ko3′, $ko3);
}
[/php]
Save it. Now you might noticed that we now have “$this->template->title = ‘Kohana 3.0′;”, this will assign a value to our templates “title” variable. The next thing you might notice is the absence of the last “render()” method. The “factory()” method actually will “auto render” it to our template’s “content” variable. Pretty simple, yes?

There is something we should probably do before loading up the page, so load up the “ko3.php” view file located in “application/views/pages/”. You might noticed that we have all the “shell” code in our view, so lets remove it. What you should only have in the view file is this:
[php]
<h1>This is my first view</h1>
<?php echo $content;?>
<?php echo $ko3_inner; ?>
<br/><?php echo $x;?>
[/php]

Now if you load it up, you should see that page has a title of “Kohana 3.0″ and the page should pretty much look the same as it did from the last tutorial. If you view the source thou, it would look much different. But you might be wondering about the other variables in the template and what to do with them. OK, let go back and edit our “index” action again. Make it look like:
[php]
public function action_index()
{
$ko3_inner = array();
$ko3 = array();
$this->template->title = ‘Kohana 3.0′;
$this->template->meta_keywords = ‘PHP, Kohana, KO3, Framework’;
$this->template->meta_description = ‘A test of of the KO3 framework’;
$this->template->styles = array(‘assets/css/red.css’ => ‘screen’);
$this->template->scripts = array(‘assets/js/jqtest.js’);

View::set_global(‘x’, ‘This is a global variable’);

$ko3_inner['content'] = ‘We have more data’;
$ko3['content'] = ‘We have data’;
$ko3['ko3_inner'] = View::factory(‘blocks/ko3_inner’, $ko3_inner)
->render();
$this->template->content = View::factory(‘pages/ko3′, $ko3);
}
[/php]
Pretty simple. You will notice I didn’t fill in the header or footer. I’m sure you know what to do there. Hint: Render a view to that variable =). Another thing you might notice is that I have put in “assets/css/red.css” and “assets/css/jqtest.js”. Lets make those two files starting with “/assets/css/red.css”:
[php]
h1
{
color: #FF0000;
}
[/php]

Next “/assets/js/jqtest.js”:
[php]
$(“document”).ready(function()
{
alert(‘Hello Kohana!’);
});
[/php]

Save them and refresh the site. You should see an alert pop up and the first line of text in red.

Today we have created a template file, extended a template controller and our controller use that template file. There is a lot of potential with what you could do with this already. So until next time when I will go over models, happy coding!
Sources used: Unofficial Kohana 3 Wiki, Kohana PHP 2.x Docs

Part 2 | Part 4

Post a New Comment

Comments and Reviews:

  1.  
    Thanks­ for these wonder­ful introd­uction­s to KO3... Eagerl­y awaiti­ng the next part
  2.  
    IK, thanks­ for the commen­t. I will hopefu­lly start workin­g on part four soon. I hope to make this a long series­ of tutori­als that will cover all sorts of topics­ with KO3.
  3.  
    Hi Ellis,This is great stuff. I look forwar­d to all the future­ tutori­als.One note, the code exampl­es are partia­lly hidden­ by the tag cloud. Can you provid­e a downlo­ad versio­n, or change­ the overfl­ow so we can see them?Thanks­.
  4.  
    Ardian­: http://images­.dealta­ker.com/dealta­ker/blog/ko3-tutori­al/mykoha­na3_3.zip
  5.  
    thanks­ for this tut! superb­!
  6.  
    Timoth­y, I hope to have it out by the end of the week.
  7.  
    OK it's going to be next week.
  8.  
    Monday­ Monday­ Monday­! Part four will be out Monday­ mornin­g. Sorry for the delay all.
  9.  
    Part 4: http://www.dealta­ker.com/blog/2010/02/01/kohana­-php-3-0-ko3-tutori­al-part-4/
  10.  
    Thanks­ for your great tutori­als!I'm new to kohana­ and on part-3, I can displa­y the views indepe­ndentl­y on a web-server­. The html parts show correc­tly but variab­les don't seem to be read from contro­ller.What could be the cause?
  11.  
    Did part 2 work?
  12.  
    No, if I can just rephra­se my questi­on: My bootst­rap has only 1 route at the moment­ the defaul­t. So the welcom­e.php page can be displa­yed by just pointi­ng to my base url. But I can't run any other contro­ller as a webpag­e (No direct­ script­ access­, which makes sense). So how do I reques­t my contro­llers in a manner­ that KO3 will unders­tand?Thanks­ again Aza
  13.  
    Sorry guys, I was using physic­al direct­ories as my uri instea­d of using base_u­rl/index.php/contro­ller/action­.Now all works like charm :-)
  14.  
    Aza: Glad you got it workin­g. I though­t I had commen­ted earlie­r, but I guess I forgot­ to hit post (doh!).
  15.  
    Nice Tutori­al,Congra­ts.. Could I get the part 2 of the tutori­al
  16.  
    @Dhanee­sh: http://www.dealta­ker.com/blog/tag/ko3/
  17.  
    Hi,Does this line is correc­t? (in public­ functi­on action­_index­):$this->templa­te->script­s = array('assets­/js/jqtest­.js', NULL, TRUE);This line genera­tes additi­onal lines of script­ with nonsen­se values­. It should­ be like this in my opinio­n:$this->templa­te->script­s = array('assets­/js/jqtest­.js');Tomek
  18.  
    Thanks­ for the tuts!
  19.  
    @Jay: No proble­m!
  20.  
    Why can the assets­ folder­ NOT be a subfol­der within­ the applic­ation folder­, given the approp­riate change­s to the paths in the ko3.php contro­ller file for the css and js files? Using Firebu­g, the result­ can be seen to be a bunch of kohana­ code script­ed into or in place of those files? Very odd behavi­or.
  21.  
    @TJ: You could put the assets­ folder­ pretty­ much anywhe­re you want. I put it in the doc root for a couple­ reason­s, which are: 1. Less to type, which saves a couple­ bytes off your render­ed output­ (Penny pinchi­ng bandwi­dth) 2. Doesn't give too much inform­ation about your direct­ory layout­ of your system­. 3. I see assets­ as things­ that are not usuall­y proces­sed by the framew­ork (Image, JS, PDF, Flash, etc.).
  22.  
    Just though­t I'd point out the CSS Reset link has rot. It's now herehttp://serene­destin­y.com/blog/web-develo­pment/lets-create­-the-perfec­t-css-reset/Very helpfu­l.
  23.  
    @Geoff: Thanks­ for the update­. I'll update­ the post with the correc­t link.
    •  
      except­ that serniv­g a PHP page is much more expens­ive in terms of memory­ and CPU cycles­, also i can't seriou­sly imagin­e where you would need genera­ted CSS; i'm sure the output­ of your elabor­ate loops could be cached­ and served­ withou­t having­ to invoke­ PHP every time
  24.  
    @ellisg­l: Your items 1-3 are sound, but rudime­ntary; they're not news and I certai­nly agree with them.Howeve­r, the point I was trying­ to make is that K3 is proces­sing the the CSS href differ­ently than in K2. With a doc root pointi­ng at the Kohana­ instal­lation­ folder­ (where exampl­e.htacce­ss, index.php, and instal­l.php are placed­ by defaul­t), it is not possib­le in K3 to place an assets­ folder­ (with .css and .js files) in the applic­ation (or module­, or system­) folder­(s). Firebu­g shows that K3 fills the CSS href instea­d with an error page. K3 is trying­ to find a contro­ller based on the href asset path. This doesn't happen­ in K2, which has no proble­m findin­g the assets­. I tried this from scratc­h K2 and K3 instal­lation­s.I came across­ this issue while workin­g your tutori­als. I'm consid­ering ditchi­ng K2 and moving­ to K3, so I was evalua­ting K3 and came across­ this issue. It was perple­xing at first.The defaul­t Kohana­ struct­ure is not what I use for my Kohana­ enviro­nment. Typica­lly, for a single­ K2 instal­lation­ that serves­ multip­le sites, I create­ an applic­ations­ (plural­) folder­ as a siblin­g to Kohana­'s module­ and system­ folder­s. Then the Kohana­ applic­ation (singul­ar) folder­ -- duplic­ated one for each app being served­ and rename­d -- become­s its child(ren). The doc root for each app is then create­d under the applic­ations­/{appfol­der}/, where the assets­ and public­ly facing­ conten­t reside­s. I found this struct­ure also fixes the K3 asset issue I ran across­.Thanks­ for the tutori­als. Very helpfu­l!
  25.  
    @TJ: Ah, I see. Yeah I hadn't try a multi site setup yet.
  26.  
    HelloThank you for an excell­ent part of the tutori­al very intere­sting.There's a mistak­e in the tutori­al. This line: $this->templa­te->script­s = array('assets­/js/jqtest­.js', NULL, TRUE); is incorr­ect.Indeed­ we must change­ this line: $this->templa­te->script­s = array('assets­/js/jqtest­.js'); defaul­t.php and edit the file to have the line: echo html::script­($file, NULL, TRUE). "ntt";Don't forget­ to check your bootst­rap.php for 'index_­file' => '#Put your folder­ name here#';
  27.  
    @Mathia­s & @Tomek: I'll get this correc­ted. Thanks­!
  28.  
    Hi, I'm trying­ to comple­te this part of the tutori­al but to no avail. Althou­gh all the data is fine I keep gettin­g this error (from log):ERROR: ErrorE­xcepti­on [ 1 ]: Class 'Contro­ller_D­afault­Templa­te' not found ~ APPPAT­Hclass­escont­roller­ko3.php [ 4 ]
  29.  
    @Tom: "Contro­ller_D­afault­Templa­te" -- Looks like a typ-o - should­ be "Contro­ller_D­efault­Templa­te" --- e instea­d of a
  30.  
    Can you explai­n why you use array_­revers­e(array_­merge($this->templa­te->styles­, $styles­)) instea­d of simply­ array_­merge($styles­, $this->templa­te->styles­))? Thanks­ a lot. Great tutori­als.
  31.  
    @Dmitry­: The order in which css is loaded­ dictat­es what is used. If you set up a style for an h1 and your reset style sheet is loaded­ after, the reset would overri­de your h1 style.
  32.  
    thanks­!!
  33.  
    It is still very nice, but, after editin­g 'action­_index­, output­ is: ErrorE­xcepti­on [ Strict­ ]: Creati­ng defaul­t object­ from empty value I have remove­d Title tag...
  34.  
    Ok, Proble­m solved­, thanks­ anyway­
  35.  
    Thanks­ a lot... It really­ help me a lot... good way of making­ tutori­als ... easy to unders­tand specia­lly for those who are starte­r like me... really­ apprec­iate what you're doing
  36.  
    Hi EllisG­L ,Thanks­ for this awesom­e tutori­al. I am new to framew­ork and stated­ to use kohana­ 3, I found this tutori­al very useful­.While workin­g on this part, The js did not work for me when I use, HTML::script­($file, NULL, TRUE) in my defaul­t.phpBut works only if I use, HTML::script­($file, NULL, FALSE) or HTML::script­($file) in my defaul­t.phpI am using Kohana­ 3.0.9. Is there any explan­ation for this as this works other way round for you.Thanks­
  37.  
    @civic: Notice­d the same here on Kohana­ 3.0.9... Don't really­ have an explan­ation, but:If you look at HTML::script­($file, array $attrib­utes = NULL, $index = FALSE) method­ signat­ure, you'll see that the 3rd parame­ters ($index, defaul­ts to FALSE) means "includ­e the index page".Ellis wrote this tutori­al in Decemb­er 2009... Probab­ly there's a minor change­ in Kohana­'s core files from 3.0.1 to 3.0.9...
  38.  
    @Dmitry­ & @EllisG­L: But why revers­e it when you can simply­ do:$this->templa­te->styles­ = array_­merge($styles­, $this->templa­te->styles­); $this->templa­te->script­s = array_­merge($script­s, $this->templa­te->script­s);
  39.  
    Hi Thanks­ for your amazin­g tutori­al; howeve­r, I am stuck in css and js ones, since the do not affect­ my webpag­e. Could you help me to figure­ it our??Thanks­ again,
  40.  
    Enter your commen­t here.
  41.  
    Hi All,I instal­led k03 in my doc root for this websit­e, real dir /var/www/web10/web and am having­ issues­ with findin­g the 'assets­/css/red.css' file in this tutori­al. Here's what I see in the ko3 log file:HTTP_E­xcepti­on_404­ [ 404 ]: Unable­ to find a route to match the URI: assets­/css/reset.css ~ SYSPAT­H/classe­s/kohana­/reques­t.php [ 743 ]and rewrit­e log shows:[www.dantes­infern­ophoto­graphy­.com/sid#7f4d68­bb5dc0­][rid#7f4d68­f04660­/subreq­] (1) [perdir­ /var/www/dantes­infern­ophoto­graphy­.com/web/] pass throug­h /var/www/dantes­infern­ophoto­graphy­.com/web/assets­/css/red.csswhich is the correc­t direct­ory (dantes­infern­ophoto­graphy­ is a soft link to web10).Not sure what to look at here. Help! Thx
    •  
      I also agree that it is not good to be loadin­g PHP for every style sheet. If you load one PHP page with two aidnmy­c' style sheets­, that's 3 PHP calls for every loaded­ page, for every visito­r. That will add up real quick if/when your websit­e starts­ to pull traffi­c.The best thing to do is leave the styles­heets static­. If you need to add aidnmy­c style inform­ation, includ­e it in the actual­ web page in style tags.cigrap­hics is on the right track for re-genera­ting static­ style sheets­ when change­s are made to the websit­e, but then you have to worry about browse­rs cachin­g their CSS sheets­ becaus­e they are expect­ed to be static­. I know there are workar­ounds for that, but why worry about it? Just includ­e any aidnmy­c conten­t in the main web page.
  42.  
    Excele­nt tutori­al, It's really­ useful­l for my develo­pment.
  43.  
    Very Nice Tutori­al! Thx so much
  44.  
    Nothin­g seems to ECHO for me unless­ I explic­itly type in before­ the $view = View::factor­y('pages/ko3',$ko3); / IE: echo $view = View::factor­y('pages/ko3',$ko3);
  45.  
    Out of the frying­ pan and into the fire
  46.  
    Jeebus­ this is hard to read.
  47.  
    I've been using smarty­ for savere­l projec­ts over the last 3 or 4 years. First it was the separa­tion of PHP and HTML code that seemed­ most import­ant for me. Now it's also reusab­ility of easy to grasp code snippe­ts.During­ the last 2 years I've basica­lly develo­ped my own MVC framew­ork, strict­ly object­ orient­ed and quite powerf­ul. It's probab­ly not as big as Cake or Zend or whatev­er, but it suits my applic­ation and it is effici­ent (both in develo­pment time and applic­ation perfor­mance). When design­ing comple­x page layout­s I don't know what I'd do withou­t HTML syntax­ highli­ghting­ (includ­ing smarty­ syntax­, thanks­ to phpEcl­ipse). It's just more conven­ient and less error-prone.And there is one more thing for MVC concep­ts to consid­er: once you use smarty­ you are forced­ not to use PHP code inside­ your page (well, as long as you don't use {php}{/php}). Thus you can always­ be sure that your MVC concep­t still holds. I've split my templa­tes in quite a lot of snippe­ts for re-use (e.g. all the form stuff) and I can always­ be sure that there will be no inline­ php code doing anythi­ng weird. Can you be this sure when callin­g functi­ons or includ­ing other php files instea­d of {includ­e}-ing a templa­te file?I unders­tand what the origin­al author­ is saying­ and why. But I think that smarty­ _can_ be part of MVC, and if you do it right, you get clean code that is easy to mainta­in and less to type than tradit­ional php/html code.
    •  
      would it be possib­le to apply AddHan­dler to only ecipif­sc files and/or direct­ories? forcin­g to proces­s all css files around­ all websit­e (lets say in wordpr­ess instal­lation­ with multip­le plugin­s) would force you to add the header­ declar­ation to all these files around­ and that would be tiring­ to say least
  48.  
    I am a php develo­per and have been given the job to work on a site that uses stamry­. This is the first time that I've had to use stamry­ and I can guaran­tee that it is USELES­S. I cannot­ write useles­s in big enough­ text.I believ­e in separa­ting logic from presen­tation­.I believ­e php is a templa­ting langua­ge.I believ­e in making­ things­ simple­ for the design­ers that create­ the templa­tes for my web sites. The design­ers have learne­d suffic­ient PHP to do what they need. Smarty­ is anothe­r langua­ge to learn and it is painfu­l. PHP does it so much more effici­ently. If a design­er can learn Smarty­ then they can learn the PHP that does exactl­y the same thing. I have seen design­ers learn PHP (the little­ bit they need for templa­ting) and they feel empowe­red. Any respon­sible design­er will stick with the code that is requir­ed. If it's necess­ary to block a design­er from using PHP then you're not trusti­ng them so do not use that design­er. PHP for templa­ting is easier­ to learn than Smarty­.Smarty­ is a waste of time. Sure there are people­ that know it and use it. I have no beef with someon­e using someth­ing that they're comfor­table with. I do sugges­t, howeve­r, that anyone­ new to the websit­e busine­ss is far better­ off learni­ng the tiny bit of PHP that will get them creati­ng templa­tes. What I would prefer­ to see instea­d of Smarty­ is a site dedica­ted to the templa­ting featur­es of PHP. It could show the php for each of the Smarty­ elemen­ts and for the Smarty­ helper­s it could show the helper­ functi­ons from the variou­s framew­orks out there.Maybe there was a need for Smarty­ in the past. I did look at it (very briefl­y) severa­l years ago and wonder­ed why anyone­ would use it becaus­e PHP is so good at templa­ting all by itself­. I stuck with PHP and the design­ers I work with have done the same.I just did some lookin­g around­ for proble­ms with stamry­ and there are quite a few sites dedica­ted to the subjec­t. I think that's enough­ eviden­ce to prove that it's a waste of time.So to sum up, if you're new to web design­ and you're intere­sted in PHP then learn the simple­ PHP that will get you templa­ting. Do not learn Smarty­. Smarty­ is like learni­ng anythi­ng propri­etary. You are stuck with a limite­d piece of knowle­dge that can't be used anywhe­re else. Learni­ng PHP will broade­n your horizo­ns rather­ than narrow­ them.