This is documentation for Kohana v2.3.x.
Todo | Proof read this page, add many more examples .. validation |
---|
ORM and Pagination can be combined quickly by using the count_last_query
method that just executes the original query again without limit and offset. The following example would be used in a controller.
$per_page = $this->input->get('limit', 1); $page_num = $this->input->get('page', 1); $offset = ($page_num - 1) * $per_page; $user = ORM::factory('user', 'john.smith'); $posts = $user->limit($per_page, $offset)->blog_posts; $pages = Pagination::factory(array ( 'style' => 'digg', 'items_per_page' => $per_page, 'query_string' => 'page', 'total_items' => $user->count_last_query() )); foreach ($posts as $post) { echo $post->title, ' by ', $post->author->username, '<br/>'; } echo $pages;
Here is another example of pagination that comes from Oscar Bajner's Kohana 101 guide after being adapted to ORM. This example uses the count_all() method to find the total number of items.
public function page($pagenum) { $this->template->title = 'L33t Str33t::Products'; $this->template->content = new View('pages/products'); // Instantiate Pagination, passing it the total number of product rows. $paging = new Pagination(array ( 'total_items' => ORM::factory('product')->with('category')->count_all(), )); // render the page links $this->template->content->pagination = $paging->render(); // Display X items per page, from offset = page number $this->template->content->products = ORM::factory('product') ->with('category') ->orderby(array('category:description' => 'ASC', 'code' => 'ASC')) ->limit($paging->items_per_page, $paging->sql_offset) ->find_all(); }
ORM has the ability to validate and save data automatically. Any errors encountered during validation can be used to feedback to the view using the standard Validation Library error reporting method.
To use Validation in an ORM model a set of validation rules and filters must be defined within a public method called validate, which overloads the ORM::validate() method.
class Person_Model extends ORM { /** * Validates and optionally saves a new user record from an array. * * @param array values to check * @param boolean save[Optional] the record when validation succeeds * @return boolean */ public function validate(array & $array, $save = FALSE) { // Initialise the validation library and setup some rules $array = Validation::factory($array) ->pre_filter('trim') ->add_rules('tel', 'required', 'phone[7,10,11,14]') ->add_rules('name', 'required', array($this, '_name_exists')); return parent::validate($array, $save); } /** * Tests if a username exists in the database. This can be used as a * Validation rule. * * @param mixed name to check * @return boolean */ public function _name_exists($name) { // Uses a ternary operator to ensure that no records returns as TRUE, some records as FALSE return (bool) ! $this->db ->where(array('name' => $name, 'id !=' => $this->id)) ->count_records($this->table_name); } }
The Validation library is used to validate the data using the rules supplied. For this reason, if using custom rules, callbacks or filters they must be publicly accessible. If a callback method is not required elsewhere, it is sensible to prefix the method name with an underscore as shown above.
Using ORM validation within controllers is simple. The ORM::validate() method will only ever return a boolean TRUE or FALSE. The array supplied to the ORM::validate() method is symbolically linked and will be transformed into a Validation object. You can also pass TRUE or a string as second parameter to save automatically the data (this means that if validation was successful, the save method will be called right after). If a string is passed, the validate() method will then perform a redirection (url::redirect($string_passed)). Note that the validate() method only populates your model with fields that actually have validation rules, so if you have fields that aren't being validated, you need to explicitly set the model values to the form fields before saving (or before calling validate with the auto-save option) – see http://forum.kohanaphp.com/comments.php?DiscussionID=2101 and http://forum.kohanaphp.com/comments.php?DiscussionID=1426 for more details.
class Person_Controller extends Controller { public function index() { // Create a new person $person = ORM::factory('person'); // If there is a post and $_POST is not empty if ($this->input->post()) { //Pull out fields we want from POST. We do this for 2 reasons: // 1) Manually set non-validated fields (address1 and address2) because validate() won't do it for us. // 2) Safety precaution -- only set fields we're expecting (otherwise someone could inject a different "id" into the POST data, for example). $data = arr::extract($this->input->post(), 'name', 'tel', 'address1', 'address2'); // If the post data validates using the rules setup in the person model if ($person->validate($data)) { //Successfully validated! $person->save(); url::redirect('some/other/page'); //Note that we could have passed TRUE to validate() to auto-save, or we could pass the redirect path to auto-save-and-redirect. } else { // Otherwise use the $data->errors() array to output the errors echo '<h1>Submitted data had errors</h1><ul>'; foreach ($data->errors() as $key => $value) echo '<li><strong>'.$key.' :</strong> '.$value.'</li>'; echo '</ul>'; } } // Create an input form (and populate the fields with last submitted values if there were errors) echo form::open(); echo form::input('name', $person->name); echo form::input('tel', $person->tel); echo form::input('address1', $person->address1); echo form::input('address2', $person->address2); echo form::submit('submit', 'Save'); echo form::close(); } }