I’d like to present my approach to what can be the possible way to make a widget in Kohana3. I formulated it in the form of tutorial to make learning process more informal and practice-oriented (Kohanian gurus will certainly find nothing interesting below). Following text is the translation of my recent tutorial written in Russian, so it is based on my previous Ko3 tutorials (deploying Ko3, views in Ko3, simple HMVC in Ko3, and user input in Ko3, all in Russian). I hope that tutor is self-sufficient but ask me if anything is not clear. Also… I’m not a designer so only basic output decoration is presented, you can add more glamour if needed.

I love all kinds of feedback so if you find grammatical (my English is poor), semantic, stylish (maybe coding style) or even sense of humor mistake please let me know. I want to amend this tutorial.

First of all, a little definition: I consider widget as a fragment of web page that is relatively independent on the other content of the page and (optionally) is possible to independently interact with user. Thus some typical cases of widget lifestyle can be like same widget on some pages or some exemplars of a widget on the same page. Some widget examples are calendars, polls, navigation bars, statistics etc.

Due to considerable independence on the page content a widget can be plugged outside of controller action method, for example in constructor or view. And simple widget can be made without any HMVC, but I do use this voodoo to make yet another example of its implementation. Our widget will show system date and time and a welcome message with the current page slug.

But let’s code it!

Let’s create parent controller for our future widget controllers. Now it is empty, but we’ll add some service functionality soon.

[code lang="php"]

class Controller_Widget extends Controller_Template {

}

[/code]

I’ll store widget controllers in application/controller/widget/ folder. So make the file date.php for Controller_Widget_Date. Widget will be invoked by subrequest like that:

[code lang="php"]

Request::factory('widget_date/show/day-year')->execute();

[/code]

Consequently in the widget controller we should mention at least the template name (file will be created later) and action_show() method with one input parameter (output format):

[code lang="php"]

public $template = 'widgets/date';

public function action_show ($format = 'year-day-hour-min')

{

$fields = explode('-',strval($format));

$d = getdate();

$date = "";

foreach ($fields as $field)

{

switch ($field)

{

case "min":

$date .= 'Minutes: '.$d['minutes'].'<br />';

break;

case "hour":

$date .= 'Hours: '.$d['hours'].'<br />';

break;

case "day":

$date .= 'Day: '.$d['month'].' '.$d['mday'].'<br />';

break;

case "year":

$date .= 'Year: '.$d['year'].'<br />';

break;

}

}

$this->template->page = Request::instance()->action;

$this->template->date = $date;

}

[/code]

Note that the property Request::instance()->action contains name of main controller execute method.

Well, let’s write our creation in the main controller (in my tutorials it is the Controller_Welcome). Widgets should not depend on page content, so we can plug them outside of actions, for example in _construct() or before() methods. I love constructors but want to try new before() stuff:

I created $widgets array to store widgets htmls. In before() method I invoked parent::before(), to init our template (can avoid this but you’ll need to write $this->template = View::factory($this->template); think it is less beautiful). Then bind our widget storage to main template and do subrequest to grab our widget html.

Yes, it is ugly and non developer-friendly. What if you need more flexibility in widget demonstration? Use config. Possible way to do this can be something like that.

Clone our present widget to widget ‘Cdate’. Simply rename widget controller and template (fix widget name in template), than plug thing in Controller_Welcome::before() — that’s all with cloning! Now start modification. First add configuration file cdate.php in application/config/cdate/. Configuration can be like that:

[code lang="php"]

return array

(

'default' => array

(

'format' => 'day-hour-min-year',

'allowed_pages' => array(),

),

'form' => array

(

'format' => 'hour-min',

'allowed_pages' => array('form'),

),

'page' => array

(

'format' => 'year-hour-min',

'allowed_pages' => array('page1','page2'),

),

);

[/code]

There are some variants of configuration, everyone containing widget format (that we’re set in quasi-uri earlier) and array of pages (page slugs) to show widget.

The parent controller Controller_Widget will contain the property $_config to store config data and the service method of config loading:

[code lang="php"]

protected $_config;

public function load_config($conf_name,$conf_entry='default')

{

$this->_config = Kohana::config($conf_name.'.'.$conf_entry);

}

[/code]

Next step is modifying of our widget controller. Add config name in $config_name = 'widget/cdate', and in Controller_Widget_Cdate::action_show() load config, track the requested action and parse config format if needed: