Url Segment Validation Helper Function For CodeIgniter
by Henry Weismann on Feb.22, 2011, under Web Development
Here is a snippet for validating url segments. 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 or they don’t check a passed argument is non zero number. For example it’s also handy for things like checking that a passed user id is the current logged in user too. 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 or TRUE result if fails or passes validation.
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. You can redirect to an error page to show the message or a pretty oops error page.
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 but here goes a barebone helper function:
/**
* 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.
A recursive method to storing hierarchical data without multiple calls to the database
by Henry Weismann on Feb.22, 2011, under Web Development
So here goes my first code snippet post. I recently needed to create a hierarchical list of categories. Since I am no genius and I don’t want to recreate the wheel I looked at all the methods I could find in a google search. This brought me to Evolt.org which mentioned:
- Recursion
- Stack
- Flat Table
- Modified Preorder Tree Traversal Algorithm
Then I found an article on sitepoint.om which got me stoked cause sitepoint always has the best articles. All these articles and numerous other results left me wanting to use the data structure I see most apps using with a parent_id and recursion but all the examples, even on sitepoint, used a database call inside the recursive function which I thought was a really big no no. I couldn’t believe all these sites were discarding recursion as too much overhead because of the database call when they just needed to rework it a bit to get rid of that overhead.
So here is the recursive method, named the adjacency list model by sitepoint, to storing hierarchical data without multiple calls to the database.
First get your categories from the database and sort using the parent id, then the sort column. Then go through the result array and create an array with each row having the parent_id as the key. Here is how that would look in codeigniter:
$this->db->order_by('parent_id, display_order', $direction);
$categories = $this->db->get('categories');
foreach($categories->result() as $category)
{
$organized_categories[$category->parent_id][] = $category;
}
return $organized_categories;
Then use a function like this to output the hierarchy:
function display_categories_list_options($categories, $group, $indent_level, $selected='')
{
foreach($group as $row)
{
$html = '<option value="'.$row->id.'" '.set_select('parent_id',$row->id,($row->id==$selected)).'>'.str_repeat('--',$indent_level).$row->name.'</option>';
echo $html;
if(isset($categories[$row->id]))
{
display_categories_list_options($categories, $categories[$row->id], $indent_level+1,$selected);
}
}
}
You could also load a view, if your using MVC, in the $html variable. That should do it. This is not fully tested yet but it works for me so far. Let me know if you find this helpful.
Hello world!
by Henry Weismann on Apr.30, 2009, under Everything Else
Welcome to my blog. Please bear with me as I find time to get this off and running.
If you came here looking for Weismann Web Hosting please go to the new domain: http://www.weismannwebhosting.com
If you are looking for web development and marketing services please see my main website: http://www.weismannweb.com