Welcome Guest, Not a member yet? Register   Sign In
rails-like before_filter
#1

[eluser]dioony[/eluser]
Hi there! Now i want to thank you all for the great ideas and solutions and want to share my code with you too.

I was searching for a filter-mechanism like in ruby on rails, but i only found the filter-system in the wiki. But i think that solution is to huge and could be more easier. so i written my own solution. Because there are some more requests for an rails-like-before-filter, i thought, it would be nice to share this.

my solution exists only of one hook-class.

1. Configure the Hooks-Config
first of all you have to configure the application/config/hooks.php. Add the following code :
Code:
$hook['post_controller_constructor'][] = array(
                                'class'    => 'Filter',
                                'function' => 'doBeforeFilter',
                                'filename' => 'Filter.php',
                                'filepath' => 'hooks'                                
                                );

2. Add the Filter-Class
add a new file to your CI-App called: application/hooks/Filter.php
add the following code into this file:
Code:
<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
* Filter Class
*
* This class enables you to integrate filters like in rails into your web apps.
*
* @package     CodeIgniter
* @subpackage  Hooks
* @category    Hooks
* @author      dioony
* @version     1.0
*/
class Filter
{


    function doBeforeFilter(){
        $CI =& get_instance();
        $router =& load_class('Router');
        $called_function = $router->fetch_method();
        if(isset($CI->before_filter)){
            if(!isset($CI->before_filter["name"])){
                show_error("BeforeFilter: Name must be set");
            }else{
                if(method_exists($CI,$CI->before_filter["name"])){
                    if(isset($CI->before_filter["except"]) && isset($CI->before_filter["only"])){
                        show_error("BeforeFilter: Filter can only run either \"except\" or \"only\"");
                    }else{
                        if(isset($CI->before_filter["except"])){
                            if(!empty($CI->before_filter["except"])){
                                if(!in_array($called_function, $CI->before_filter["except"])){
                                    call_user_func(array($CI,$CI->before_filter["name"]));
                                }
                            }else{
                                call_user_func(array($CI,$CI->before_filter["name"]));
                            }
                        }else{
                            if(isset($CI->before_filter["only"])){
                                if(!empty($CI->before_filter["only"])){
                                    if(in_array($called_function, $CI->before_filter["except"])){
                                        call_user_func(array($CI,$CI->before_filter["name"]));
                                    }
                                }else{
                                    call_user_func(array($CI,$CI->before_filter["name"]));
                                }
                            }else{
                                call_user_func(array($CI,$CI->before_filter["name"]));
                            }
                        }
                    }
                }else{
                    show_error("BeforeFilter: Function \"".$CI->before_filter["name"]."\" does not exists");
                }
            }
        }
    }
    
}

?>

3.Setting up the Controller
Now you can set up you're controller to run the before_filter.
Code:
<?
class Start extends Controller {

    
    var $before_filter = array('name' => 'authorization');
    
    function Start() {
        parent::Controller();
    }
    
    function index(){
        //... the index ...
    }
    
    function authorization(){
        if(user_not_logged()){
            redirect('other_ctrl/login');
        }
    }
        
}

?>
now, if anybody runs a function from the Start-controller, automatically the authorization-function will be called before this function and will redirect the user to another controller if he is not logged in. note that it have to be another controller and not the same, because elsewise you will generate an endless loop.

now, it is also possible to exclude some functions to be filtered. (e.g. if you want to redirect to the same controller)
Code:
var $before_filter = array('name' => 'authorization', 'except' => array('index'));


another way is to specify only the functions which have to be filterd
Code:
var $before_filter = array('name' => 'authorization', 'only' => array('index'));

4. Annotations and Thoughts
This solution only accepts one filter per controller. there are two reasons:
1. i think, that there should not be more than one filter to keep the code clear
2. i never needed more than one in rails or ci.
But i think, it should be very easy to change it to a multiple-filter-hook. if someone take an interest in it, i could change the code.

in rails you have to put the before_filter-method in the application-controller. in theory it should also be possible with CI, if you have written an application-controller and each of your controllers extends this one. Then you can put the filter-method into the application-controller. But i didn't test it!

it should also be possible to write an after_filter. you only have to replace "post_controller_constructor" with "post_controller" in the hooks.php and change the variable "before_filter" to "after_filter" to keep the code clear.

if you have any feedback, comments, bugs or something like that, feel free to reply


Messages In This Thread
rails-like before_filter - by El Forum - 04-08-2008, 09:49 AM
rails-like before_filter - by El Forum - 04-08-2008, 09:53 AM
rails-like before_filter - by El Forum - 04-08-2008, 11:16 AM
rails-like before_filter - by El Forum - 04-09-2008, 09:52 AM
rails-like before_filter - by El Forum - 07-03-2008, 12:03 PM



Theme © iAndrew 2016 - Forum software by © MyBB