PicoraController
Container and support for your business logic.
The PicoraController class should be the parent class of all of your PicoraController sub classes that contain the business logic of your application (render a blog post, log a user in, delete something and redirect, etc).
In the Dispatcher class you can define what urls / routes map to what Controllers and methods. Each method must do any of the following:
- return a string response
- redirect to another method
- execute any code and exit()
If the method returns null or false, the PicoraDispatcher will keep looking for another method that returns a response or redirects, calling the error callback if no method responds to the requested URL.
Each controller can have a beforeCall() and afterCall() method which will be called before a method inside the Controller is called (even if no method returns a valid response), and after a method inside the PicoraController is called (only if the method returns a valid response).
Additionally, you can flash() variables that will appear as local variables in a View object if one is rendered on the next request.
Method Overview
Return | Visibility | Name | Parameters |
unknown | final static public | flash | (string $key, mixed $value, boolean $now) |
array | final static public | getFlash | () |
unknown | final static public | redirect | (mixed $controller_and_method, mixed $arguments) |
unknown | final static public | render | (string $file, mixed $local_variables) |
string | final static protected | renderRSS | (string $feed, boolean $print) |
unknown | final static protected | renderJSON | (mixed $data_to_encode) |
unknown | final static protected | sendFile | (string $file, mixed $download_as_filename) |
mixed | public | afterCall | (string $response, string $method_name) |
unknown | public | beforeCall | (string $method_name) |
Method Detail
final static public flash()
Parameter Type | Name | Description |
string | $key | |
mixed | $value | Can be any data type or object that is serializable. |
boolean | $now | Flash the value during the current request only? Defaults to false (so it will be available on this request, and the next). |
Serializes $value and makes it available as a local variable with $key name on the next request in the rendered view. self::flash('message','Your post has been saved.'); self::redirect('post',array('postid'=>$postid)); //in the view file that the method post renders...
final static public getFlash()
final static public redirect()
Parameter Type | Name | Description |
mixed | $controller_and_method | String method name if redirecting to a method in the current controller or array('ControllerName','methodName') if redirecting to a method in another controller. |
mixed | $arguments | Array arguments to resolve the route,or boolean false. |
Redirects to another method, and terminates the current request. Putting the word "Controller" at the end of each controller name is optional. self::redirect('about'); self::redirect(array('BlogController','post'),array('postid'=>5)); self::redirect(array('Blog','post'),array('postid'=>5)); self::redirect('http://google.com/');
final static public render()
Parameter Type | Name | Description |
string | $file | Path to the file to render. Path will be relative to the file that handles the request. |
mixed | $local_variables | Key => value pairs to pass to the View object that is rendered. |
self::render('views/blog/post.php',array('post'=>$post));
final static protected renderRSS()
Parameter Type | Name | Description |
string | $feed | Array of RSS data. |
boolean | Defaults to true. Print the feed complete with the appropriate header. |
Renders an RSS feed from an array of data. Note that this is not an all in one cure all solution for RSS, it is merely a way to quickly create an RSS feed that fits most basic uses. $feed should contain the following keys: - string "title" - string "link" - timestamp "date" - optional string "description" - optional string "language" - array "items"
Each item in "items" should contain: - string "title" - string "link" - optional string "description" - optional timestamp "date" - optional string "guid"
final static protected renderJSON()
Parameter Type | Name | Description |
mixed | $data_to_encode |
Renders $datatoencode as JSON with the appropriate headers, outputs this to the browser and terminates the current request.
final static protected sendFile()
Parameter Type | Name | Description |
string | $file | Local file name |
mixed | $download_as_filename | Filename that the browser will save the file as. Defaults to the specified file name. |
public afterCall()
Parameter Type | Name | Description |
string | $response | The response that was returned from $method_name. |
string | $method_name |
After a method sucessfully responds to a requested url, this method is called. It is designed to be overriden by a subclass and does nothing by default.
public beforeCall()
Parameter Type | Name | Description |
string | $method_name |
This is a callback function that will be called each time any method of the controller is called. This method may be called multiple times while the dispatcher is searching for a method that returns a response. It is designed to be overriden by a subclass and does nothing by default.
This class triggers the following events, which you can observe with the following syntax:
PicoraEvent::observe('event_name','my_function'); //or
PicoraEvent::observe('event_name',array($my_object,'my_instance_method')); //or
PicoraEvent::observe('event_name',array('MyClass','my_static_method'));
Return | Name | Signature | Description |
bool | ControllerName.beforeCall | (PicoraController object,string method_name) | applies to any PicoraController subclass. |
mixed | ControllerName.afterCall | (PicoraController object,mixed response,string method_name) | applies to any PicoraController subclass. |
void | PicoraController.afterRender | (PicoraView object) | Called after the PicoraView object is created, but before display() is called. |
Declared in: PicoraController.php
abstract class PicoraController {
const FLASH_SESSION_KEY_NAME = 'PicoraController.flash';
/**
* This is a callback function that will be called each time any method of the controller is called. This method may be called multiple times while the dispatcher is searching for a method that returns a response. It is designed to be overriden by a subclass and does nothing by default.
* @param string $method_name
*/
public function beforeCall($method_name){}
/**
* After a method sucessfully responds to a requested url, this method is called. It is designed to be overriden by a subclass and does nothing by default.
* @param string $response The response that was returned from $method_name.
* @param string $method_name
* @return mixed Method should return null to leave $response untouched, otherwise the return value from the method becomes the response.
*/
public function afterCall($response,$method_name){}
/**
* self::render('views/blog/post.php',array('post'=>$post));
* @param string $file Path to the file to render. Path will be relative to the file that handles the request.
* @param mixed $local_variables Key => value pairs to pass to the View object that is rendered.
*/
final static public function render($file,$local_variables = false){
$view_instance = new PicoraView($file,$local_variables);
foreach(PicoraEvent::getObserverList('PicoraController.afterRender') as $callback)
call_user_func($callback,$view_instance);
return $view_instance;
}
/**
* Renders $data_to_encode as JSON with the appropriate headers, outputs this to the browser and terminates the current request.
* @param mixed $data_to_encode
*/
final static protected function renderJSON($data_to_encode,$use_standard = false){
if(function_exists('json_encode'))
$output = json_encode($data_to_encode);
elseif(class_exists('PicoraJSON'))
$output = PicoraJSON::encode($data_to_encode);
else
throw new Exception('No function or class found to render JSON data.');
if($use_standard){
header('X-JSON: ('.$output.')');
print ' ';
}else
print '('.$output.')';
exit;
}
/**
* Renders an RSS feed from an array of data. Note that this is not an all in one cure all solution for RSS, it is merely a way to quickly create an RSS feed that fits most basic uses. $feed should contain the following keys:
*
* - string "title"
* - string "link"
* - timestamp "date"
* - optional string "description"
* - optional string "language"
* - array "items"
*
* Each item in "items" should contain:
*
* - string "title"
* - string "link"
* - optional string "description"
* - optional timestamp "date"
* - optional string "guid"
*
* @param string $feed Array of RSS data.
* @param boolean $print Defaults to true. Print the feed complete with the appropriate header.
* @return string RSS feed, or null if $print is true.
*/
final static protected function renderRSS($feed,$print = true){
$tab = chr(9);
$nl = chr(10);
if(!isset($feed['description']))
$feed['description'] = '';
$output = '<?xml version="1.0" encoding="UTF-8"?>'.$nl;
$output .= '<rss version="2.0">'.$nl.
$tab.'<channel>'.$nl.
$tab.$tab.PicoraView::tag('title',$feed['title']).$nl.
$tab.$tab.PicoraView::tag('link',$feed['link']).$nl.
$tab.$tab.PicoraView::tag('lastBuildDate',gmdate(DATE_RFC822,$feed['date'])).$nl.
$tab.$tab.PicoraView::tag('description',$feed['description']).$nl.
(isset($feed['language']) ? $tab.$tab.PicoraView::tag('language',$feed['language']).$nl : '')
;
foreach($feed['items'] as $item){
if(!isset($item['guid']))
$item['guid'] = md5($item['title'].$item['link']);
$output .= $tab.'<item>'.$nl.
$tab.$tab.$tab.PicoraView::tag('title',$item['title']).$nl.
$tab.$tab.$tab.PicoraView::tag('link',$item['link']).$nl.
(isset($item['description']) ? $tab.$tab.$tab.PicoraView::tag('description','<![CDATA['.$item['description'].']]>').$nl : '').
(isset($item['date']) ? $tab.$tab.$tab.PicoraView::tag('pubDate',gmdate(DATE_RFC822,$item['date'])).$nl : '').
$tab.$tab.$tab.'<guid isPermaLink="false">'.$item['guid'].'</guid>'.$nl.
$tab.$tab.'</item>'.$nl;
}
$output .= $tab.'</channel>'.$nl.'</rss>';
if($print){
header('Content-type: application/rss+xml');
print $output;
}else
return $output;
}
/**
* Redirects to another method, and terminates the current request.
*
* Putting the word "Controller" at the end of each controller name is optional.
*
* self::redirect('about');
* self::redirect(array('BlogController','post'),array('post_id'=>5));
* self::redirect(array('Blog','post'),array('post_id'=>5));
* self::redirect('http://google.com/');
* @param mixed $controller_and_method String method name if redirecting to a method in the current controller or array('ControllerName','methodName') if redirecting to a method in another controller.
* @param mixed $arguments Array arguments to resolve the route,or boolean false.
*/
final static public function redirect($controller_and_method,$arguments = false,$include_base_url = true){
header('Location: '.(is_string($controller_and_method) && (strpos($controller_and_method,'http://') === 0 || strpos($controller_and_method,'https://' === 0)) ? $controller_and_method : PicoraDispatcher::getUrl($controller_and_method,$arguments,$include_base_url)));
exit;
}
/**
* Serializes $value and makes it available as a local variable with $key name on the next request in the rendered view.
* self::flash('message','Your post has been saved.');
* self::redirect('post',array('post_id'=>$post_id));
* //in the view file that the method post renders...
* <?php if(isset($message)):?><p class="message"><?php print $message;?></p><?php endif;?>
* @param string $key
* @param mixed $value Can be any data type or object that is serializable.
* @param boolean $now Flash the value during the current request only? Defaults to false (so it will be available on this request, and the next).
*/
final static public function flash($key,$value,$now = false){
$_SESSION[PicoraController::FLASH_SESSION_KEY_NAME]['values'][$key] = serialize($value);
$_SESSION[PicoraController::FLASH_SESSION_KEY_NAME]['gc'][$key] = ($now ? 0 : 1);
}
/**
* @return array Flash values.
*/
final static public function getFlash(){
return (isset($_SESSION[PicoraController::FLASH_SESSION_KEY_NAME])) ? $_SESSION[PicoraController::FLASH_SESSION_KEY_NAME]['values'] : false;
}
/**
* @param string $file Local file name
* @param mixed $download_as_filename Filename that the browser will save the file as. Defaults to the specified file name.
*/
final static protected function sendFile($file,$download_as_filename = false){
if(!file_exists($file))
return false;
$size = filesize($file);
header('Content-Type: '.(preg_match('/Opera/',$_SERVER['HTTP_USER_AGENT'] || preg_match('/MSIE/',$_SERVER['HTTP_USER_AGENT'])) ? 'application/octetstream' : 'application/octet-stream'));
header('Content-Disposition: attachment; filename="'.($download_as_filename ? $download_as_filename : array_pop(explode('/',$file))).'"');
header('Expires: Mon, 26 Jul 2024 05:00:00 GMT');
header("Cache-control: private");
header('Pragma: private');
header('Content-Length: '.$size);
readfile($file);
}
}