ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

Url Segment Validation

April 28, 2010 6:43am

Subscribe [8]
  • #1 / Apr 28, 2010 6:43am

    Henry Weismann's avatar

    Henry Weismann

    55 posts

    I wanted something similar to form validation for validating url segments.  Basically to be able to use any form validation function, helper, php or callback functions to validate passed data. 

    I have seen countless programmers not check data passed via the url and leading to broken CI pages…for example if they don’t check that they actually got a database result when using an id passed via the url that is not what was expected. 

    It’s handy for times you want to check that a passed user id is the current logged in user.  Any function you want to use you can…you can even use the 2nd argument like match[1].  You can also pass FALSE as the site url and it will return the FALSE result.

    In this example I immediately redirect with an error if one of the checks fails but it uses my set_message() function.  So just take that out or add your own function for setting the user message.

    This could be further enhanced to use the validation language capabilities and maybe added to the url class and allow you to save rules in a config file.

    /** 
    * Validates data passed via the url by segment number. 
    * Redirects on fail to specified site url or returns result
    * if the passed $site_url param is bool FALSE.  Returns the segment 
    * data on success or returns the formatted data if a prepping function was used.
    * @param string 
    * @param string 
    * @param string 
    * @return bool or data 
    */ 
     
    function validate_segment($segment, $rules, $site_url = TRUE)
    {
            $CI = &get;_instance();    
            $CI->load->library('form_validation');
            $data = $CI ->uri->segment($segment);
            
            $rules = explode('|',$rules);
            
            if(!in_array('required', $rules) && $data == '')
            {
                return $data;
            }        
        
            if (in_array('required', $rules) AND $data == '')
            {
                set_message('The url has missing data.','error');
                    
                if($site_url)
                {
                    $site_url = is_string($site_url) ? $site_url : '';
                    redirect($site_url);
                }
            }
            // --------------------------------------------------------------------
            // Cycle through each rule and run it
            foreach ($rules As $rule)
            {
                if($rule == 'required')
                {
                    continue;
                }
                
                // Is the rule a callback?            
                $callback = FALSE;
                if (substr($rule, 0, 9) == 'callback_')
                {
                    $rule = substr($rule, 9);
                    $callback = TRUE;
                }
                
                // Strip the parameter (if exists) from the rule
                // Rules can contain a parameter: max_length[5]
                $param = FALSE;
                if (preg_match("/(.*?)\[(.*?)\]/", $rule, $match))
                {
                    $rule    = $match[1];
                    $param    = $match[2];
                }
                
                // Call the function that corresponds to the rule
                if ($callback === TRUE)
                {
                    if ( ! method_exists($CI, $rule))
                    {         
                        $validates = FALSE;
                    }
                    
                    if($param)
                    {
                        $result = $CI->$rule($data, $param);    
                    }                        
                    else
                    {
                        $result = $CI->$rule($data);
                    }
        
                }
                else
                {                
                    if ( ! method_exists($CI->form_validation, $rule))
                    {
                        // If our own wrapper function doesn't exist we see if a native PHP function does. 
                        // Users can use any native PHP function call that has one param.
                        if (function_exists($rule))
                        {
                            if($param)
                            {
                                $result = $rule($data, $param);    
                            }                        
                            else
                            {
                                $result = $rule($data);    
                            }
                        }
                        
                    }
                    else
                    {
                        if($param)
                        {
                            $result = $CI->form_validation->$rule($data, $param);
                        }
                        else
                        {
                            $result = $CI->form_validation->$rule($data);
                        }
                        
                    }
                }
                
                //is it a bool or did the function change the data and send it back
                $data = (is_bool($result)) ? $data : $result;
                
                // Did the rule test negatively?  If so, grab the error.    
                if(is_bool($result) && $result === FALSE)
                {
                    if($site_url)
                    {
                        $site_url = is_string($site_url) ? $site_url : '';
                        set_message('The url has incorrect data.','error');
                        redirect($site_url);
                    }
                    
                    return $data;                
                }
        
            }
            
        return $data;
    }

    Usage:

    $id = validate_segment('3', 'required|is_natural_no_zero');
    $user_id = validate_segment('4', 'required|is_natural_no_zero|is_admin|is_current_user');
    $page_name = validate_segment('5', 'alpha_dash');

    That’s 3 short lines of code to run 7 validation functions and redirect with a message if any of the passed data is not what you wanted.

    Let me know if anyone finds it useful.  It’s not bug tested at all yet but seems to be working so far.

  • #2 / Jun 15, 2010 12:41am

    newtonianb

    14 posts

    This is great, thanks for sharing!

  • #3 / Jun 15, 2010 6:23am

    Clooner's avatar

    Clooner

    464 posts

    Thanks, this is great!

  • #4 / Apr 21, 2011 8:15pm

    deadelvis's avatar

    deadelvis

    24 posts

    Thanks!! This is exactly what I was looking for! Will give it a try!

  • #5 / Apr 22, 2011 1:37pm

    deadelvis's avatar

    deadelvis

    24 posts

    Hey!...

    After reviewing your helper and seeing it was pretty much a copy of form_validation->_execute(), I started hacking some code and ended up with my own version.

    I think it’s a bit simpler because I tried to keep code to a minimum by extending form_validation instead of writing a helper.
    I guess it could be considered a big hack / slimmed down version of form_validation->run()

    For flexibility I also added a callback and some default error message reformatting… but I guess that could be removed if not required.

    I have no idea if doing the same thing by extending uri class would be possible… (since form_validation->_execute() is private i guess not).

    Haven’t tested it too much yet but it seems to work fine on 2.0.2

    <?php if (!defined('BASEPATH')) { exit('No direct script access allowed'); }
    
    /**
     * MY_Form_Validation Class
     *
     * Extends Validation library
     *
     * Adds generic validation() method to allow variable validation.
     *
     */
    
    class MY_Form_validation extends CI_Form_validation
    {
    
        function __construct(){
            parent::__construct();
        }
    
        /**
         * Executes the Validation routines on a var instead of _POST
         *
         * @access    public
         * @param    mixed        Single value or array of values to validate.
         * @param    string        String of cascading rules.
         * @param    function    Callback function with error string as parameter.
         * @return    boolean        True on success, false on fail.
         */
        function validate($var, $rules, $callback=NULL)
        {
            // Load the language file containing error messages
            $this->CI->lang->load('form_validation');
        
            // Let's fake the required variables
            $is_array = FALSE;
            if(is_array($var))
            {
                $is_array = TRUE;
            }
            
            $row = array('field'=>'fake', 'label'=>'fake', 'rules'=>$rules, 'is_array'=>$is_array, 'keys'=>array(), 'postdata'=>NULL, 'error'=>'' );                
            $this->_field_data['fake']['postdata'] = $var;
            
            // Test for errors exactly like run() does…
            $this->_execute($row, explode('|', $row['rules']), $this->_field_data['fake']['postdata']);
            
            // We have an error!
            if ( isset($this->_field_data['fake']['error']) )
            {
                // Slightly reformat the default error messages
                $error = ucfirst( str_replace( 'The fake field ' , '' ,  $this->_field_data['fake']['error'] ));
                
                // Callback func
                if(is_callable($callback))
                {
                    call_user_func($callback, $error);
                }
                return FALSE;
            }
            return TRUE;
        }
    
    }
    
    /* end file */


    Simple usage with uri segment..

    if( !$this->form_validation->validate($this->uri->segment(n), 'required|numeric|less_than[100]') )
    {
        echo 'Less than 100 please!!';
    }

       
    and using callback to log & redirect…

    $this->form_validation->validate(array('10.0.0.z',''), 'required|valid_ip', function($error){ log_message('error', $error); show_error($error); } );
  • #6 / Feb 25, 2012 10:54am

    jwallz

    4 posts

    you can use the form validation class for this. just load it and call the validation function you need using it like any other class:
    $this->load->library(‘form_validation’);
    if($this->form_validation->alpha_numeric($this->uri->segment(2)))
    {
    //do something…
    }

  • #7 / Jun 28, 2012 5:15am

    satie

    39 posts

    I’ve just used your function. Simply perfect. Thanks for sharing

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases