Below you will find an article / tutorial on Kohana 3.2 – An elegant HMVC PHP5 framework that provides a rich set of components for building web applications.
I am sharing a site template that use authentication & internationalization. You can view the website (not much to see) and download it from github. Any pull request will be more than welcome!

Download via Github:
https://github.com/patricksebastien/kohana-3.2-example
Topics
Install
Using GIT:
http://kohanaframework.org/3.2/guide/kohana/tutorials/git
or
Download:
http://kohanaframework.org/download
Structure of folders:
www/yoursite/site/index.php &
.htaccess -> and your assets (css, images, js)
www/yoursite/application -> the very core of your site
www/yoursite/module &
system -> core of kohana
or:
www/kohana/version/system &
module -> multiple site using kohana
or:
everything in
www/yoursite/site (application, module, system, index.php, .htaccess, …)
Test:
127.0.0.1/
If it’s greenish, then remove
install.php
index.php
Reflect this structure in
www/yoursite/site/index.php:
1 2 3
| $application = '../application';
$modules = '../modules';
$system = '../system'; |
bootstrap.php
Modify
application/bootstrap.php
Set PRODUCTION vs DEVELOPMENT
1 2 3 4 5
| if (isset($_SERVER['KOHANA_ENV'])) {
Kohana ::$environment = constant('Kohana::'.strtoupper($_SERVER['KOHANA_ENV']));
} else {
Kohana ::$environment = ($_SERVER['REMOTE_ADDR'] == '127.0.0.1' ? Kohana ::DEVELOPMENT : Kohana ::PRODUCTION);
} |
Initialize Kohana
1 2 3 4 5
| 'base_url' => '/', // or for example: /yoursite/site/mykoapp
'index_file' => FALSE, // SEO (avoid index.php/mycontroller/action)
'profile' => (Kohana::$environment !== Kohana::PRODUCTION), //see how good you are
'caching' => (Kohana::$environment === Kohana::PRODUCTION),
'errors' => TRUE, //for custom 404, 500 FALSE for internal error handling |
Enable modules (for example):
1 2 3
| 'auth' => MODPATH.'auth', // Basic authentication
'database' => MODPATH.'database', // Database access
'orm' => MODPATH.'orm', // Object Relationship Mapping |
Many modules are available:
https://github.com/kolanos/kohana-universe
http://kohana-modules.com/
Set the routes (default controller will be login.php in this example)
http://kohanaframework.org/3.2/guide/kohana/routing
The order of your routes are important!
1 2 3 4 5
| Route ::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'login', // application/classes/controller/login.php
'action' => 'index',
)); |
.htaccess
Add this line at the very top of
.htaccess (protect from sniffing directory)
1
| Options All -Indexes -Multiviews |
and modify (/ or for example: /yoursite/site/mykoapp)
1 2
| # Installation directory
RewriteBase / |
Template
http://kerkness.ca/kowiki/doku.php?id=template-site:create_the_template
Create the template controller (classes/controller/template/website.php) extending Controller_Template
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <?php defined('SYSPATH') or die('No direct script access.');
class Controller_Template_Website extends Controller_Template
{
public $template = 'template/website';
/**
* The before() method is called before your controller action.
* In our template controller we override this method so that we can
* set up default values. These variables are then available to our
* controllers if they need to be modified.
*/
public function before () {
parent ::before();
if ($this->auto_render) {
// Initialize empty values
$this->template->title = '';
$this->template->content = '';
$this->template->styles = array();
$this->template->scripts = array();
}
}
/**
* The after() method is called after your controller action.
* In our template controller we override this method so that we can
* make any last minute modifications to the template before anything
* is rendered.
*/
public function after () {
if ($this->auto_render) {
$styles = array(
'assets/css/website.css' => 'screen, projection',
);
$scripts = array(
'http://code.jquery.com/jquery.min.js',
);
$this->template->styles = array_merge( $this->template->styles, $styles );
$this->template->scripts = array_merge( $this->template->scripts, $scripts );
}
parent ::after();
}
} |
Create the controller (classes/controller/login.php) extending Controller_Template_Website (look at the second action for an example on how to use another template per action):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Controller_Login extends Controller_Template_Website {
public function action_index()
{
$this->template->title = 'Log in';
$this->template->content = View::factory('login'); // application/views/login.php
}
// this action is using another template but using the same Controller_Template_Website
public function action_showinfooverlay()
{
$this->template = 'template/overlay';
parent::before();
$this->template->title = 'Log in';
$this->template->content = View::factory('login'); // application/views/login.php
}
} |
Create the html template (view/template/website.php)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <!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=" <?php echo substr(I18n ::$lang, 0, 2); ?>" lang=" <?php echo substr(I18n ::$lang, 0, 2); ?>">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="language" content=" <?php echo I18n ::$lang ?>" />
<title> <?php echo $title ?></title>
<?php foreach ($styles as $file => $type) echo HTML ::style($file, array('media' => $type)), PHP_EOL ?>
<?php foreach ($scripts as $file) echo HTML ::script($file), PHP_EOL ?>
</head>
<body>
<div id="wrapper">
<?php echo $content ?>
</div>
</body>
</html> |
Finally create your view content application/views/login.php
1 2 3 4 5 6 7 8 9
| <?php echo Form::open(); ?>
<dl>
<dt><?php echo Form::label('username', 'User') ?></dt>
<dd><?php echo Form::input('username') ?></dd>
<dt><?php echo Form::label('password', 'Pwd') ?></dt>
<dd><?php echo Form::password('password') ?></dd>
</dl>
<p><?php echo Form::submit(NULL, 'Log in'); ?></p>
<?php echo Form::close(); ?> |
At this point you can point your browser to see the login page:
http://localhost/ -> depending on base_url and .htaccess (could be in a sub-folder)
http://localhost/login -> not defined login as the default controller in bootstrap.php
Someone on #kohana (irc / freenode) made a suggestion of using view classes instead of template controller. Here’s two solutions: https://github.com/zombor/kostache & https://github.com/beautiful/view
Configure
Database
Copy modules/database/config/database.php to application/config/database.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 'default' => array
(
'type' => 'mysql',
'connection' => array(
'hostname' => 'localhost',
'database' => 'yourdb',
'username' => 'user',
'password' => 'pwd',
'persistent' => FALSE,
),
'table_prefix' => '',
'charset' => 'utf8',
'caching' => FALSE,
'profiling' => FALSE, // if you use profiling turn this on (to see querys)
), |
Cookie
in
application/bootstrap.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| /**
* Cookie
*/
// Set the magic salt to add to a cookie
Cookie ::$salt = 'fjsdijeihrewhbfsugfuyegwufewgwb';
// Set the number of seconds before a cookie expires
Cookie ::$expiration = DATE::WEEK; // by default until the browser close
// Restrict the path that the cookie is available to
//Cookie::$path = '/';
// Restrict the domain that the cookie is available to
//Cookie::$domain = 'www.mydomain.com';
// Only transmit cookies over secure connections
//Cookie::$secure = TRUE;
// Only transmit cookies over HTTP, disabling Javascript access
//Cookie::$httponly = TRUE; |
Session (stored in database)
http://kohanaframework.org/3.2/guide/kohana/sessions
in
application/bootstrap.php add the default session handler:
1
| Session::$default = 'database'; |
Copy system/config/encrypt.php to application/config/encrypt.php
1 2 3 4 5 6 7 8 9
| return array(
'default' => array(
'key' => 'fjdsjkfdskjfurew',
'cipher' => MCRYPT_RIJNDAEL_128 ,
'mode' => MCRYPT_MODE_NOFB ,
),
); |
Create a table if you want to use database session
1 2 3 4 5 6 7
| CREATE TABLE `sessions` (
` session_id` VARCHAR (24) NOT NULL,
`last_active` INT UNSIGNED NOT NULL,
`contents` TEXT NOT NULL,
PRIMARY KEY (` session_id` ),
INDEX (`last_active` )
) ENGINE = MYISAM ; |
Copy system/config/session.php to application/config/session.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| return array(
'database' => array(
'name' => 'session',
'encrypted' => TRUE, // need a key in config/encrypt.php
'lifetime' => DATE::HOUR, // 0 = expire when the browser close
'group' => 'default',
'table' => 'sessions',
'columns' => array(
'session_id' => 'session_id',
'last_active' => 'last_active',
'contents' => 'contents'
),
'gc' => 500,
),
); |
Use it in your controller:
1 2
| Session::instance()->set('key', 'value');
Session::instance()->get('key'); |
yoursite
Create a file in
application/config/yoursite.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php defined('SYSPATH') or die('No direct access allowed.');
return array(
'myconfig1' => 'fjdsjkfdskjfurew',
'playlists' => array
(
1478363 => 10171,
22857234 => 10171,
386 => 10171,
722 => 10171,
893 => 10171,
237 => 10171,
),
); |
Then you can call a config like this:
1 2
| $playlists = Kohana::$config->load('yoursite.playlists');
Kohana::$config->load('yoursite.myconfig1 '); |
Message
(might be better to use I18N directly)
Create a file in application/message/yoursite.php for you project
1 2 3 4 5
| <?php defined('SYSPATH') or die('No direct script access.');
return array(
'permission' => 'You don\'t have the permission',
'wrong' => 'Wrong username or password',
); |
Then you can use it like this:
1
| Kohana::message('yoursite', 'permission'); |
Translation
http://blog.mixu.net/2010/11/11/kohana-3-i18n-tutorial/
1
| <?php echo __ ('Dear :firstname, your username is: :user', array(':firstname' => 'gfdgfdg', ':user' => 'gfdgfd')); ?> |
Validation
http://kohanaframework.org/3.2/guide/kohana/security/validation
Copy system/messages/validation to application/message/validation.php if you want to change the error message
1 2 3 4 5 6 7 8 9 10 11 12 13
| // Validate a form ($_POST)
if (isset($_POST) && Valid ::not_empty($_POST)) {
// Validate the login form
$post = Validation ::factory($_POST)
->rule('username', 'not_empty')
->rule('username', 'regex', array(':value', '/^[a-z_.]++$/iD'))
->rule('password', 'not_empty')
->rule('password', 'min_length', array(':value', 3));
// If the form is valid and the username and password matches
if ($post->check()) {
echo 'Validated';
} |
Using a callback for custom validation & error message
1 2 3 4 5 6 7 8 9
| // form post handling
if (isset($_POST) && Valid ::not_empty($_POST)) {
// validate
$post = Validation ::factory($_POST)
->rule('username', 'alpha_numeric')
->rule('password', array($this, 'pwdneusr'), array(':validation', ':field', 'username'));
if ($post->check()) {
}
} |
1 2 3 4 5 6 7 8 9
| // CALLBACK
// validation rule: password != username
public function pwdneusr($validation, $password, $username)
{
if ($validation[$password] === $validation[$username])
{
$validation->error($password, 'pwdneusr');
}
} |
Error page
http://kohanaframework.org/3.2/guide/kohana/tutorials/error-pages
Create the views
views/error/404.php / 500.php etc…
Extend the exception handler of Kohana
classes/kohana/exception.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <?php defined('SYSPATH') or die('No direct script access.');
class Kohana_Exception extends Kohana_Kohana_Exception {
public static function handler (Exception $e)
{
if (Kohana ::DEVELOPMENT === Kohana ::$environment)
{
parent ::handler($e);
}
else
{
try
{
Kohana ::$log->add(Log::ERROR, parent ::text($e));
$attributes = array
(
'controller' => 'error',
'action' => 500,
'message' => rawurlencode($e->getMessage())
);
if ($e instanceof HTTP_Exception )
{
$attributes['action'] = $e->getCode();
}
// Error sub-request.
echo Request ::factory(Route ::get('error')->uri($attributes))
->execute()
->send_headers()
->body();
}
catch (Exception $e)
{
// Clean the output buffer if one exists
ob_get_level() and ob_clean();
// Display the exception text
echo parent ::text($e);
// Exit with an error status
exit(1);
}
}
}
} |
Create the controller:
classes/controller/error.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?php defined('SYSPATH') or die('No direct script access.');
class Controller_Error extends Controller_Template_Nobrand {
public function before ()
{
parent ::before();
// Internal request only!
if (Request ::$initial !== Request ::$current) {
if ($message = rawurldecode($this->request->param('message'))) {
$this->template->message = $message;
}
} else {
$this->request->action(404);
}
$this->response->status((int ) $this->request->action());
}
public function action_404 ()
{
$this->template->title = '404 Not Found';
$this->template->content = View ::factory('error/404' );
}
public function action_500 ()
{
$this->template->title = 'Internal Server Error';
$this->template->content = View ::factory('error/500' );
}
public function action_503 ()
{
$this->template->title = 'Maintenance Mode';
$this->template->content = View ::factory('error/503' );
}
} |
Edit application/bootstrap.php to add the route:
1 2 3 4
| Route ::set('error', 'error/<action>(/<message>)', array('action' => '[0-9]++', 'message' => '.+'))
->defaults(array(
'controller' => 'error'
)); |
Authentication
Copy modules/auth/config/auth.php to application/config/auth.php
1 2 3 4 5 6 7
| return array(
'driver' => 'orm',
'hash_method' => 'sha256',
'hash_key' => 'wigbble',
'lifetime' => Date::HOUR * 2,
'session_key' => 'auth_user',
); |
Schema for mysql / postgresql located:
modules/orm/auth-schema-mysql.sql
Change the rules if you don’t want to required an email (you will also need to remove the index in mysql: uniq_email – BTREE)
Copy modules/orm/classes/model/auth/user.php to application/classes/model/auth/user.php and change the public function rules() to your needs
It’s a good idea to add a new role for your normal user, that way you can list them easily:
1
| $p = ORM ::factory('role', array('name' => 'participant'))->users->find_all(); |
Create application/messages/models/user.php
1 2 3 4 5
| <?php defined('SYSPATH') or die('No direct script access.');
return array(
'username.unique' => 'Username must be unique',
'email.unique' => 'Email must be unique',
); |
If you want to use the remember feature:
1 2
| $remember = isset($post['remember']);
Auth ::instance()->login($post['username'], $post['password'], $remember) |
then you need to be sure to have a cookie salt in application/bootstrap.php
1 2 3 4
| /**
* Cookie salt for remember user info
*/
Cookie::$salt = 'fdsh-tretgd-re-gfds-gt-erg-fdg-'; |
Some useful stuff:
1 2 3 4 5 6 7 8 9 10 11 12 13
| // Add an administrator (in a temporary controller)
$model = ORM ::factory('user');
$model->values(array(
'username' => 'admin',
'password' => 'admin',
'password_confirm' => 'admin',
'email' => 'your@email.com',
));
$model->save();
// remember to add the login role AND the admin role
// add a role; add() executes the query immediately
$model->add('roles', ORM ::factory('role')->where('name', '=', 'login')->find());
$model->add('roles', ORM ::factory('role')->where('name', '=', 'admin')->find()); |
1 2 3 4 5 6 7 8 9
| // If this user doesn't have the admin role, and is not trying to login, redirect to login
public function before ()
{
parent ::before();
if ( ! Auth ::instance()->logged_in('admin') AND Request ::current()->uri() !== 'manage')
{
$this->request->redirect('/manage');
}
} |
1 2 3 4
| // Administrator already logged in, redirect to dashboard
if (Auth::instance()->logged_in('admin')) {
$this->request->redirect('manage/dashboard');
} |
1 2
| // Log the user
Auth::instance()->login($post['username'], $post['password'], FALSE) |
1 2
| // Check if the user have the admin permission
if(!Auth::instance()->logged_in('admin')) { |
1 2
| // Log user out
Auth::instance()->logout(); |
1 2 3 4
| // check if email or username (automagic) is already taken
if(ORM::factory('user')->unique_key_exists($_POST['username'])) {
echo "FOUND";
} |
ORM
http://kohanaframework.org/3.2/guide/orm/
http://karlsheen.com/kohana/kohana-3-orm-tutorial-and-samples/
http://kohanaframework.blogspot.com/2010/12/kohana-3-orm-simple-example.html
http://www.geekgumbo.com/2011/05/24/kohana-3-orm-a-working-example/
http://kohanaframework.org/3.2/guide/api/ORM
ORM is included with the Kohana 3.x install but needs to be enabled before you can use it. In your application/bootstrap.php file modify the call to Kohana::modules and include the ORM modules:
The table name must be in plural;
The table must have an id with auto increment (required);
You must create a Model that extends ORM class (this one not in plural)
1)
Create a table with a “s” as the end:
tracking -> trackings
category -> categories
2)
Create a model (application/classes/model) without the “s”
tracking.php
category.php
1 2 3 4 5
| <?php defined('SYSPATH') or die('No direct access allowed.');
class Model_Tracking extends ORM
{
...
} |
1 2 3 4 5
| <?php defined('SYSPATH') or die('No direct access allowed.');
class Model_Category extends ORM
{
...
} |
3)
Establish your relation (one-to-one, one-to-many etc…)
4)
Use your model / ORM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| try
{
$tracking = ORM ::factory('tracking');
$tracking->user_id = Auth ::instance()->get_user()->id;
$tracking->session_id = Session ::instance()->id();
$tracking->title = ' fdsfdsf ';
if($tracking->save()) {
echo "save";
} else {
echo "for some reason, there's an error";
}
}
catch (ORM_Validation_Exception $e) {
echo "error";
var_dump($e->errors());
} |
Some useful stuff:
1 2 3
| $user = ORM::factory('user');
echo $user->count_all();
echo $user->last_query(); |
1 2 3 4
| $playlists = ORM::factory('playlist')->where('week_id', '=', 1)->find_all();
foreach ($playlists as $playlist) {
echo $playlist->url;
} |
Last ID from ->save();
1 2
| $myormmodel->save();
echo $myormmodel->id(); |
ORM Validation
http://kohanaframework.org/3.2/guide/orm/examples/validation
http://kohanaframework.org/3.2/guide/kohana/security/validation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <?php defined('SYSPATH') or die('No direct access allowed.');
class Model_Member extends ORM {
public function rules ()
{
return array(
'username' => array(
array('not_empty'),
array('min_length', array(':value', 4)),
array('max_length', array(':value', 32)),
array(array($this, 'username_available')),
),
'password' => array(
array('not_empty'),
),
);
}
public function filters ()
{
return array(
'password' => array(
array(array($this, 'hash_password')),
),
);
}
public function username_available ($username)
{
// There are simpler ways to do this, but I will use ORM for the sake of the example
return ORM ::factory('member', array('username' => $username))->loaded();
}
public function hash_password ($password)
{
// Do something to hash the password
}
} |
Database:
http://kohanaframework.org/3.2/guide/database/
http://kohanaframework.org/3.2/guide/api/Database
There’s 2 ways to query a database: prepared (normal SQL) and query builder (dynamic)
Prepared:
1 2 3 4 5 6
| $query = DB ::query(Database ::SELECT, 'SELECT * FROM users WHERE username = :user AND status = :status');
$query->parameters(array(
':user' => 'john',
':status' => 'active',
)); |
Query builder:
1 2 3 4
| $query = DB::select()->from('users')->where('username', '=', 'john');
$query = DB::select('username')->distinct(TRUE)->from('posts');
$query = DB::select()->from(`posts`)->limit(10)->offset(30);
… |
Results:
1 2 3 4 5 6
| $results = DB::select()->from('users')->where('verified', '=', 0)->execute();
foreach($results as $user)
{
// Send reminder email to $user['email']
echo $user['email']." needs to verify his/her account\n";
} |
1 2 3 4 5 6
| $results = DB::select()->from('users')->where('verified', '=', 0)->as_object()->execute();
foreach($results as $user)
{
// Send reminder email to $user->email
echo $user->email." needs to verify his/her account\n";
} |
Only get 1 result:
1
| $total_users = DB ::select(array('COUNT("username")', 'total_users'))->from('users')->execute()->get('total_users', 0); |
1 2 3
| // Get the total number of records in the "users" table
$db = Database::instance();
$count = $db->count_records('testi'); |
3rd party libraries
The convention is to place 3rd party files in application/vendor. For instance, if you had an installation of Doctrine, you would place it in application/vendor/doctrine.
1 2
| require Kohana::find_file('vendor', 'Swift-4.0.5/lib/swift_required');
$transport = Swift_SmtpTransport::newInstance(...); // This is autoloaded for me by Swiftmailer |
PHPExcel – create PDF, CSV, Excel:
application/vendor/phpexcel/PHPExcel.php & PHPExcel
then in your controller:
1 2
| require Kohana::find_file('vendor', 'phpexcel/PHPExcel');
$objPHPExcel = new PHPExcel(); |
Email – you can use this module:
https://github.com/Luwe/Kohana-Email
or directly use swiftmailer:
http://swiftmailer.org/
1 2 3 4 5 6 7 8 9 10 11 12
| require Kohana ::find_file('vendor', 'swift/swift_required');
//Create the Transport
$transport = Swift_SmtpTransport ::newInstance('localhost', 25);
//Create the Mailer using your created Transport
$mailer = Swift_Mailer ::newInstance($transport);
//Create a message
$message = Swift_Message ::newInstance('Email')
->setFrom(array('from@email.net' => 'From'))
->setTo(array('to@email.net'))
->setBody('An email');
//Send the message
$result = $mailer->send($message); |
Helper
http://kohanaframework.org/3.2/guide/api/Arr
If you want to add some custom helper (generally used statically) or library (instantiated / object), for example: application/classes/participants.php
1 2 3 4 5
| <?php defined('SYSPATH') or die('No direct script access.');
class Participant {
static function currentweek () {
}
} |
in your controller:
1
| $weektodisplay = Participant::currentweek(); |
Tips
To get the params in a controller (depending on your routes in application/bootstrap.php)
1
| $this->request->param('id') |
Debug:
To get the current controller:
To point at the right directory use:
1
| <?php echo URL::base(); ?> |
To get a custom column from users (auth):
1
| echo Auth::instance()->get_user()->week; |
Date:
1 2
| Date::formatted_time('now', 'm-d-Y');
//constant Date::WEEK Date::YEAR |
Way to use the model and the post for edition in form:
1 2 3 4 5
| // Received the POST
if (isset($_POST) && Valid ::not_empty($_POST)) {
// keep but not saved
$participant->values($_POST, array('email', 'username','password'))
} |
To redirect use:
1
| $this->request->redirect('manage/dashboard'); |
To make a link use:
1
| <?php echo HTML ::anchor('playlist', 'Playlist', array('style' => 'color: #FFF')); ?> |
Function inside controller:
inside action_x():
outside action_x():
1 2 3
| static function _replaceplaylistendtime(&$value, $key, $p) {
...
} |
Jquery
Use the latest minified version on google server:
http://code.jquery.com/jquery.min.js
User interface:
http://ninjaui.com/
http://jqueryui.com/
http://flowplayer.org/tools/index.html
Ajax:
In your “ajax” controller / action
1 2 3 4 5
| if ($this->request->is_ajax()) {
$id = json_decode($_POST['refresh']);
$this->auto_render = FALSE;
echo json_encode(array('result' => $id));
} |
In your jquery:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| $.ajax({
type: "POST",
url: "<?php echo URL::base(); ?>home/refresh",
data: "refresh=1",
async: true,
dataType: "json",
success: function(resultArray, textStatus, XMLHttpRequest)
{
var result = parseInt(resultArray['result']);
alert(result);
},
error: function(request, textStatus, errorThrown)
{
alert('error refreshing the session');
}
}); |
Bookmarks
http://kohanaframework.org/3.2/guide/kohana/tutorials/
http://kohanaframework.org/3.2/guide/api or http://kohana.nerdblog.pl/api/
Deploying:
See this for more information about deploying Kohana application
http://nerdblog.pl/2011/09/05/deploying-kohana-3-2-application-in-production/