diff --git a/modules/orm/guide/orm/examples/simple.md b/modules/orm/guide/orm/examples/simple.md index b8abe92..73cd010 100644 --- a/modules/orm/guide/orm/examples/simple.md +++ b/modules/orm/guide/orm/examples/simple.md @@ -1,119 +1,119 @@ # Simple Examples -This is a simple example of a single ORM model, that has no relationships, but uses validation on the fields. +This is a simple example of a single ORM model, that has no relationships, but uses validation on the fields. ## SQL schema - CREATE TABLE IF NOT EXISTS `members` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `username` varchar(32) NOT NULL, - `first_name` varchar(32) NOT NULL, - `last_name` varchar(32) NOT NULL, - `email` varchar(127) DEFAULT NULL, - PRIMARY KEY (`id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; + CREATE TABLE IF NOT EXISTS `members` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(32) NOT NULL, + `first_name` varchar(32) NOT NULL, + `last_name` varchar(32) NOT NULL, + `email` varchar(127) DEFAULT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; ## Model - - array( - array('not_empty'), - array('min_length', array(':value', 4)), - array('max_length', array(':value', 32)), - array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')), - ), - 'first_name' => array( - array('not_empty'), - array('min_length', array(':value', 4)), - array('max_length', array(':value', 32)), - array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')), - ), - 'last_name' => array( - array('not_empty'), - array('min_length', array(':value', 4)), - array('max_length', array(':value', 32)), - array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')), - ), - 'email' => array( - array('not_empty'), - array('min_length', array(':value', 4)), - array('max_length', array(':value', 127)), - array('email'), - ), - ); - } - } - -[!!] The array returned by `ORM::rules()` will be passed to a [Validation] object and tested when you call `ORM::save()`. + + array( + array('not_empty'), + array('min_length', array(':value', 4)), + array('max_length', array(':value', 32)), + array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')), + ), + 'first_name' => array( + array('not_empty'), + array('min_length', array(':value', 4)), + array('max_length', array(':value', 32)), + array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')), + ), + 'last_name' => array( + array('not_empty'), + array('min_length', array(':value', 4)), + array('max_length', array(':value', 32)), + array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')), + ), + 'email' => array( + array('not_empty'), + array('min_length', array(':value', 4)), + array('max_length', array(':value', 127)), + array('email'), + ), + ); + } + } + +[!!] The array returned by `ORM::rules()` will be passed to a [Validation] object and tested when you call `ORM::save()`. [!!] Please notice that defining the primary key "id" in the model is not necessary. Also the table name in the database is plural and the model name is singular. ## Controller - where('first_name', '=', 'Peter')->find_all(); - - // Count records in the $members object - $members->count_all(); - - /** - * Example 2 - */ - - // Create an instance of a model - $member = ORM::factory('Member'); - - // Get a member with the user name "bongo" find() means - // we only want the first record matching the query. - $member->where('username', '=', 'bongo')->find(); - - /** - * Example 3 - */ - - // Create an instance of a model - $member = ORM::factory('Member'); - - // Do an INSERT query - $member->username = 'bongo'; - $member->first_name = 'Peter'; - $member->last_name = 'Smith'; - $member->save(); - - /** - * Example 4 - */ - - // Create an instance of a model where the - // table field "id" is "1" - $member = ORM::factory('Member', 1); - - // Do an UPDATE query - $member->username = 'bongo'; - $member->first_name = 'Peter'; - $member->last_name = 'Smith'; - $member->save(); - } - } + where('first_name', '=', 'Peter')->find_all(); + + // Count records in the $members object + $members->count_all(); + + /** + * Example 2 + */ + + // Create an instance of a model + $member = ORM::factory('Member'); + + // Get a member with the user name "bongo" find() means + // we only want the first record matching the query. + $member->where('username', '=', 'bongo')->find(); + + /** + * Example 3 + */ + + // Create an instance of a model + $member = ORM::factory('Member'); + + // Do an INSERT query + $member->username = 'bongo'; + $member->first_name = 'Peter'; + $member->last_name = 'Smith'; + $member->save(); + + /** + * Example 4 + */ + + // Create an instance of a model where the + // table field "id" is "1" + $member = ORM::factory('Member', 1); + + // Do an UPDATE query + $member->username = 'bongo'; + $member->first_name = 'Peter'; + $member->last_name = 'Smith'; + $member->save(); + } + } [!!] $member will be a PHP object where you can access the values from the query e.g. echo $member->first_name diff --git a/modules/orm/guide/orm/examples/validation.md b/modules/orm/guide/orm/examples/validation.md index 0510a45..40ead7e 100644 --- a/modules/orm/guide/orm/examples/validation.md +++ b/modules/orm/guide/orm/examples/validation.md @@ -4,134 +4,134 @@ This example will create user accounts and demonstrate how to handle model and c ## SQL schema - CREATE TABLE IF NOT EXISTS `members` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `username` varchar(32) NOT NULL, - `password` varchar(100) NOT NULL, - PRIMARY KEY (`id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; + CREATE TABLE IF NOT EXISTS `members` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(32) NOT NULL, + `password` varchar(100) NOT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; ## Model - - array( - array('not_empty'), - array('min_length', array(':value', 4)), - array('max_length', array(':value', 32)), - array(array($this, 'username_available')), - ), - 'password' => array( - array('not_empty'), - ), - ); - } - - public function filters() - { - return array( - 'password' => array( - array(array($this, 'hash_password')), - ), - ); - } - - public function username_available($username) - { - // There are simpler ways to do this, but I will use ORM for the sake of the example - return ORM::factory('Member', array('username' => $username))->loaded(); - } - - public function hash_password($password) - { - // Do something to hash the password - } - } + + array( + array('not_empty'), + array('min_length', array(':value', 4)), + array('max_length', array(':value', 32)), + array(array($this, 'username_available')), + ), + 'password' => array( + array('not_empty'), + ), + ); + } + + public function filters() + { + return array( + 'password' => array( + array(array($this, 'hash_password')), + ), + ); + } + + public function username_available($username) + { + // There are simpler ways to do this, but I will use ORM for the sake of the example + return ORM::factory('Member', array('username' => $username))->loaded(); + } + + public function hash_password($password) + { + // Do something to hash the password + } + } ## HTML Form Please forgive my slightly ugly form. I am trying not to use any modules or unrelated magic. :) -
## Controller [!!] Remember that the `password` will be hashed as soon as it is set in the model, for this reason, it is impossible to validate it's length or the fact that it matches the `password_confirm` field. The model should not care about validating the `password_confirm` field, so we add that logic to the controller and simply ask the model to bundle the errors into one tidy array. Read the [filters](filters) section to understand how those work. - public function action_create() - { - $view = View::factory('members/create') - ->set('values', $_POST) - ->bind('errors', $errors); - - if ($_POST) - { - $member = ORM::factory('Member') - // The ORM::values() method is a shortcut to assign many values at once - ->values($_POST, array('username', 'password')); - - $external_values = array( - // The unhashed password is needed for comparing to the password_confirm field - 'password' => Arr::get($_POST, 'password'), - // Add all external values - ) + Arr::get($_POST, '_external', array()); - $extra = Validation::factory($external_values) - ->rule('password_confirm', 'matches', array(':validation', ':field', 'password')); - - try - { - $member->save($extra); - // Redirect the user to his page - $this->request->redirect('members/'.$member->id); - } - catch (ORM_Validation_Exception $e) - { - $errors = $e->errors('models'); - } - } - - $this->response->body($view); - } + public function action_create() + { + $view = View::factory('members/create') + ->set('values', $_POST) + ->bind('errors', $errors); + + if ($_POST) + { + $member = ORM::factory('Member') + // The ORM::values() method is a shortcut to assign many values at once + ->values($_POST, array('username', 'password')); + + $external_values = array( + // The unhashed password is needed for comparing to the password_confirm field + 'password' => Arr::get($_POST, 'password'), + // Add all external values + ) + Arr::get($_POST, '_external', array()); + $extra = Validation::factory($external_values) + ->rule('password_confirm', 'matches', array(':validation', ':field', 'password')); + + try + { + $member->save($extra); + // Redirect the user to his page + $this->request->redirect('members/'.$member->id); + } + catch (ORM_Validation_Exception $e) + { + $errors = $e->errors('models'); + } + } + + $this->response->body($view); + } ## Messages **application/messages/models/member.php** - return array( - 'username' => array( - 'not_empty' => 'You must provide a username.', - 'min_length' => 'The username must be at least :param2 characters long.', - 'max_length' => 'The username must be less than :param2 characters long.', - 'username_available' => 'This username is not available.', - ), - 'password' => array( - 'not_empty' => 'You must provide a password.', - ), - ); + return array( + 'username' => array( + 'not_empty' => 'You must provide a username.', + 'min_length' => 'The username must be at least :param2 characters long.', + 'max_length' => 'The username must be less than :param2 characters long.', + 'username_available' => 'This username is not available.', + ), + 'password' => array( + 'not_empty' => 'You must provide a password.', + ), + ); **application/messages/models/member/_external.php** - return array( - 'password_confirm' => array( - 'matches' => 'The password fields did not match.', - ), - ); + return array( + 'password_confirm' => array( + 'matches' => 'The password fields did not match.', + ), + ); diff --git a/modules/orm/guide/orm/filters.md b/modules/orm/guide/orm/filters.md index 218f0a4..1f09456 100644 --- a/modules/orm/guide/orm/filters.md +++ b/modules/orm/guide/orm/filters.md @@ -4,38 +4,38 @@ Filters in ORM work much like they used to when they were part of the Validate c Filters run as soon as the field is set in your model and should be used to format the data before it is inserted into the Database. Filters are defined the same way you define [rules](validation), as an array returned by the `ORM::filters()` method, like the following: - public function filters() - { - return array( - // Field Filters - // $field_name => array(mixed $callback[, array $params = array(':value')]), - 'username' => array( - // PHP Function Callback, default implicit param of ':value' - array('trim'), - ), - 'password' => array( - // Callback method with object context and params - array(array($this, 'hash_password'), array(':value', Model_User::salt())), - ), - 'created_on' => array( - // Callback static method with params - array('Format::date', array(':value', 'Y-m-d H:i:s')), - ), - 'other_field' => array( - // Callback static method with implicit param of ':value' - array('MyClass::static_method'), - // Callback method with object context with implicit param of ':value' - array(array($this, 'change_other_field')), - // PHP function callback with explicit params - array('str_replace', array('luango', 'thomas', ':value'), - // Function as the callback (PHP 5.3+) - array(function($value) { - // Do something to $value and return it. - return some_function($value); - }), - ), + public function filters() + { + return array( + // Field Filters + // $field_name => array(mixed $callback[, array $params = array(':value')]), + 'username' => array( + // PHP Function Callback, default implicit param of ':value' + array('trim'), + ), + 'password' => array( + // Callback method with object context and params + array(array($this, 'hash_password'), array(':value', Model_User::salt())), + ), + 'created_on' => array( + // Callback static method with params + array('Format::date', array(':value', 'Y-m-d H:i:s')), + ), + 'other_field' => array( + // Callback static method with implicit param of ':value' + array('MyClass::static_method'), + // Callback method with object context with implicit param of ':value' + array(array($this, 'change_other_field')), + // PHP function callback with explicit params + array('str_replace', array('luango', 'thomas', ':value'), + // Function as the callback (PHP 5.3+) + array(function($value) { + // Do something to $value and return it. + return some_function($value); + }), + ), - ); - } + ); + } [!!] When defining filters, you may use the parameters `:value`, `:field`, and `:model` to refer to the field value, field name, and the model instance respectively. diff --git a/modules/orm/guide/orm/index.md b/modules/orm/guide/orm/index.md index 681c190..dacba1c 100644 --- a/modules/orm/guide/orm/index.md +++ b/modules/orm/guide/orm/index.md @@ -10,12 +10,12 @@ ORM is included with the Kohana 3.x install but needs to be enabled before you c Before we use ORM, we must enable the modules required - Kohana::modules(array( - ... - 'database' => MODPATH.'database', - 'orm' => MODPATH.'orm', - ... - )); + Kohana::modules(array( + ... + 'database' => MODPATH.'database', + 'orm' => MODPATH.'orm', + ... + )); [!!] The database module is requried for the ORM module to work. Of course the database module has to be configured to use an existing database. diff --git a/modules/orm/guide/orm/models.md b/modules/orm/guide/orm/models.md index cffbcff..19c14d7 100644 --- a/modules/orm/guide/orm/models.md +++ b/modules/orm/guide/orm/models.md @@ -2,10 +2,10 @@ To create a model for the table `members` in your database, create the file `application/classes/model/member.php` with the following syntax: - class Model_Member extends ORM - { - ... - } + class Model_Member extends ORM + { + ... + } (this should provide more examples) @@ -13,16 +13,16 @@ To create a model for the table `members` in your database, create the file `app If you wish to change the database table that a model uses, just override the `$_table_name` variable like this: - protected $_table_name = 'strange_tablename'; + protected $_table_name = 'strange_tablename'; ## Changing the primary key ORM assumes each model (and database table) has an `id` column that is indexed and unique. If your primary key column isn't named `id`, that's fine - just override the `$_primary_key` variable like this: - protected $_primary_key = 'strange_pkey'; + protected $_primary_key = 'strange_pkey'; ## Use a non-default database For each model, you can define which database configuration ORM will run queries on. If you override the `$_db_group` variable in your model, ORM will connect to that database. Example: - protected $_db_group = 'alternate'; + protected $_db_group = 'alternate'; diff --git a/modules/orm/guide/orm/relationships.md b/modules/orm/guide/orm/relationships.md index 20f9901..faf6393 100644 --- a/modules/orm/guide/orm/relationships.md +++ b/modules/orm/guide/orm/relationships.md @@ -8,57 +8,57 @@ A `belongs_to` relation should be used when you have one model that belongs to a This is the base `belongs_to` relationship: - protected $_belongs_to = array( - '[alias name]' => array( - 'model' => '[model name]', - 'foreign_key' => '[column]', - ), - ); + protected $_belongs_to = array( + '[alias name]' => array( + 'model' => '[model name]', + 'foreign_key' => '[column]', + ), + ); You can omit any or all of the keys/values in the array on the right, in which case defaults are used: - protected $_belongs_to = array('[alias name]' => array()); + protected $_belongs_to = array('[alias name]' => array()); The **alias name** is what is used to access the related model in your code. If you had a `Post` model that belonged to a `User` model and wished to use the default values of the `belongs_to` configuration then your code would look like this: - protected $_belongs_to = array('user' => array()); + protected $_belongs_to = array('user' => array()); To access the user model, you would use `$post->user`. Since we're using the defaults above, the alias name will be used for the model name, and the foreign key in the posts table will be the alias name followed by `_id`, in this case it would be `user_id`. (You can change the `_id` suffix by modifying the `$foreign_key_suffix` variable in the model.) Let's say your `Post` database table schema doesn't have a `user_id` column but instead has an `author_id` column which is a foreign key for a record in the `User` table. You could use code like this: - protected $_belongs_to = array( - 'user' => array( - 'foreign_key' => 'author_id', - ), - ); + protected $_belongs_to = array( + 'user' => array( + 'foreign_key' => 'author_id', + ), + ); If you wanted access a post's author by using code like `$post->author` then you would simply need to change the alias and add the `model` index: - protected $_belongs_to = array( - 'author' => array( - 'model' => 'User', - ), - ); + protected $_belongs_to = array( + 'author' => array( + 'model' => 'User', + ), + ); ## has_many The standard `has_many` relationship will likely fall on the other side of a `belongs_to` relationship. In the above examples, a post belongs to a user. From the user's perspective, a user has many posts. A has_many relationship is defined below: - protected $_has_many = array( - '[alias name]' => array( - 'model' => '[model name]', - 'foreign_key' => '[column]', - ), - ); + protected $_has_many = array( + '[alias name]' => array( + 'model' => '[model name]', + 'foreign_key' => '[column]', + ), + ); Again, you can omit all keys in the right array to use the defaults: - protected $_has_many = array('[alias name]' => array()); + protected $_has_many = array('[alias name]' => array()); For our user and post example, this would look like the following in the user model: - protected $_has_many = array('posts' => array()); + protected $_has_many = array('posts' => array()); Using the above, the posts could be access using `$user->posts->find_all()`. Notice the `find_all()` used in this example. With `belongs_to` and `has_one` relationship types, the model is already loaded with necessary data. For `has_many` relationships, however, you may want to limit the number of results or add additional conditions to the SQL query; you can do so prior to the `find_all()`. @@ -66,23 +66,23 @@ The model name used by default will be the singular name of the alias using the Let's assume now you want to access the posts using the name `stories` instead, and are still using the `author_id` key as in the `belongs_to` example. You would define your has_many relationship as: - protected $_has_many = array( - 'stories' => array( - 'model' => 'Post', - 'foreign_key' => 'author_id', - ), - ); + protected $_has_many = array( + 'stories' => array( + 'model' => 'Post', + 'foreign_key' => 'author_id', + ), + ); ## has_one A `has_one` relationship is almost identical to a `has_many` relationship. In a `has_one` relationship, there can be 1 and only 1 relationship (rather than 1 or more in a has_many). If a user can only have one post or story, rather than many then the code would look like this: - protected $_has_one = array( - 'story' => array( - 'model' => 'Post', - 'foreign_key' => 'author_id', - ), - ); + protected $_has_one = array( + 'story' => array( + 'model' => 'Post', + 'foreign_key' => 'author_id', + ), + ); ## has_many "through" @@ -90,34 +90,34 @@ A `has_many "through"` relationship is used for many-to-many relationships. For To define the `has_many` "through" relationship, the same syntax for standard has_many relationships is used with the addition of a 'through' parameter. Let's assume we're working with the Post model: - protected $_has_many = array( - 'categories' => array( - 'model' => 'Category', - 'through' => 'categories_posts', - ), - ); + protected $_has_many = array( + 'categories' => array( + 'model' => 'Category', + 'through' => 'categories_posts', + ), + ); In the Category model: - protected $_has_many = array( - 'posts' => array( - 'model' => 'Post', - 'through' => 'categories_posts', - ), - ); + protected $_has_many = array( + 'posts' => array( + 'model' => 'Post', + 'through' => 'categories_posts', + ), + ); To access the categories and posts, you simply use `$post->categories->find_all()` and `$category->posts->find_all()` Methods are available to check for, add, and remove relationships for many-to-many relationships. Let's assume you have a $post model loaded, and a $category model loaded as well. You can check to see if the $post is related to this $category with the following call: - $post->has('categories', $category); + $post->has('categories', $category); The first parameter is the alias name to use (in case your post model has more than one relationship to the category model) and the second is the model to check for a relationship with. Assuming you want to add the relationship (by creating a new record in the categories_posts table), you would simply do: - $post->add('categories', $category); + $post->add('categories', $category); To remove: - $post->remove('categories', $category); + $post->remove('categories', $category); diff --git a/modules/orm/guide/orm/upgrading.md b/modules/orm/guide/orm/upgrading.md index ce5b540..ed44b5e 100644 --- a/modules/orm/guide/orm/upgrading.md +++ b/modules/orm/guide/orm/upgrading.md @@ -5,12 +5,12 @@ ORM will now alias the main table in a query to the model's singular object name. i.e. Prior to 3.2 ORM set the from table like so: - $this->_db_builder->from($this->_table_name); + $this->_db_builder->from($this->_table_name); As of 3.2 it is now aliased like so: - $this->_db_builder->from(array($this->_table_name, $this->_object_name)); + $this->_db_builder->from(array($this->_table_name, $this->_object_name)); If you have a model `Model_Order` then when building a query use the alias like so: - $model->where('order.id', '=', $id); + $model->where('order.id', '=', $id); diff --git a/modules/orm/guide/orm/using.md b/modules/orm/guide/orm/using.md index 9ef03cb..469a7ea 100644 --- a/modules/orm/guide/orm/using.md +++ b/modules/orm/guide/orm/using.md @@ -4,26 +4,26 @@ To create a new `Model_User` instance, you can do one of two things: - $user = ORM::factory('User'); - // Or - $user = new Model_User(); + $user = ORM::factory('User'); + // Or + $user = new Model_User(); ## Inserting To insert a new record into the database, create a new instance of the model: - $user = ORM::factory('User'); + $user = ORM::factory('User'); Then, assign values for each of the properties; - $user->first_name = 'Trent'; - $user->last_name = 'Reznor'; - $user->city = 'Mercer'; - $user->state = 'PA'; + $user->first_name = 'Trent'; + $user->last_name = 'Reznor'; + $user->city = 'Mercer'; + $user->state = 'PA'; Insert the new record into the database by running [ORM::save]: - $user->save(); + $user->save(); [ORM::save] checks to see if a value is set for the primary key (`id` by default). If the primary key is set, then ORM will execute an `UPDATE` otherwise it will execute an `INSERT`. @@ -32,36 +32,36 @@ Insert the new record into the database by running [ORM::save]: To find an object you can call the [ORM::find] method or pass the id into the ORM constructor: - // Find user with ID 20 - $user = ORM::factory('User') - ->where('id', '=', 20) - ->find(); - // Or - $user = ORM::factory('User', 20); + // Find user with ID 20 + $user = ORM::factory('User') + ->where('id', '=', 20) + ->find(); + // Or + $user = ORM::factory('User', 20); ## Check that ORM loaded a record Use the [ORM::loaded] method to check that ORM successfully loaded a record. - if ($user->loaded()) - { - // Load was successful - } - else - { - // Error - } + if ($user->loaded()) + { + // Load was successful + } + else + { + // Error + } ## Updating and Saving Once an ORM model has been loaded, you can modify a model's properties like this: - $user->first_name = "Trent"; - $user->last_name = "Reznor"; + $user->first_name = "Trent"; + $user->last_name = "Reznor"; And if you want to save the changes you just made back to the database, just run a `save()` call like this: - $user->save(); + $user->save(); @@ -70,25 +70,25 @@ And if you want to save the changes you just made back to the database, just run To delete an object, you can call the [ORM::delete] method on a loaded ORM model. - $user = ORM::factory('User', 20); - $user->delete(); + $user = ORM::factory('User', 20); + $user->delete(); + - ## Mass assignment - + To set multiple values at once, use [ORM::values] - - try - { - $user = ORM::factory('user') - ->values($this->request->post(), array('username','password')) - ->create(); - } - catch (ORM_Validation_Exception $e) - { - // Handle validation errors ... - } - + + try + { + $user = ORM::factory('user') + ->values($this->request->post(), array('username','password')) + ->create(); + } + catch (ORM_Validation_Exception $e) + { + // Handle validation errors ... + } + [!!] Although the second argument is optional, it is *highly recommended* to specify the list of columns you expect to change. Not doing so will leave your code _vulnerable_ in case the attacker adds fields you didn't expect. diff --git a/modules/orm/guide/orm/validation.md b/modules/orm/guide/orm/validation.md index 56a46ca..9d35869 100644 --- a/modules/orm/guide/orm/validation.md +++ b/modules/orm/guide/orm/validation.md @@ -6,24 +6,24 @@ ORM models are tightly integrated with the [Validation] library and the module c Validation rules are defined in the `ORM::rules()` method. This method returns the array of rules to be added to the [Validation] object like so: - public function rules() - { - return array( - 'username' => array( - // Uses Valid::not_empty($value); - array('not_empty'), - // Calls Some_Class::some_method('param1', 'param2'); - array('Some_Class::some_method', array('param1', 'param2')), - // Calls A_Class::a_method($value); - array(array('A_Class', 'a_method')), - // Calls the lambda function and passes the field value and the validation object - array(function($value, Validation $object) - { - $object->error('some_field', 'some_error'); - }, array(':value', ':validation')), - ), - ); - } + public function rules() + { + return array( + 'username' => array( + // Uses Valid::not_empty($value); + array('not_empty'), + // Calls Some_Class::some_method('param1', 'param2'); + array('Some_Class::some_method', array('param1', 'param2')), + // Calls A_Class::a_method($value); + array(array('A_Class', 'a_method')), + // Calls the lambda function and passes the field value and the validation object + array(function($value, Validation $object) + { + $object->error('some_field', 'some_error'); + }, array(':value', ':validation')), + ), + ); + } ### Bound Values @@ -37,19 +37,19 @@ ORM will automatically bind the following values with `Validation::bind()`: All models automatically validate their own data when `ORM::save()`, `ORM::update()`, or `ORM::create()` is called. Because of this, you should always expect these methods to throw an [ORM_Validation_Exception] when the model's data is invalid. - public function action_create() - { - try - { - $user = ORM::factory('User'); - $user->username = 'invalid username'; - $user->save(); - } - catch (ORM_Validation_Exception $e) - { - $errors = $e->errors(); - } - } + public function action_create() + { + try + { + $user = ORM::factory('User'); + $user->username = 'invalid username'; + $user->save(); + } + catch (ORM_Validation_Exception $e) + { + $errors = $e->errors(); + } + } ## Handling Validation Exceptions @@ -57,54 +57,54 @@ The [ORM_Validation_Exception] will give you access to the validation errors tha In the below example, the error messages will be defined in `application/messages/models/user.php` - public function action_create() - { - try - { - $user = ORM::factory('User'); - $user->username = 'invalid username'; - $user->save(); - } - catch (ORM_Validation_Exception $e) - { - $errors = $e->errors('models'); - } - } + public function action_create() + { + try + { + $user = ORM::factory('User'); + $user->username = 'invalid username'; + $user->save(); + } + catch (ORM_Validation_Exception $e) + { + $errors = $e->errors('models'); + } + } ## External Validation Certain forms contain information that should not be validated by the model, but by the controller. Information such as a [CSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) token, password verification, or a [CAPTCHA](http://en.wikipedia.org/wiki/CAPTCHA) should never be validated by a model. However, validating information in multiple places and combining the errors to provide the user with a good experience is often quite tedius. For this reason, the [ORM_Validation_Exception] is built to handle multiple Validation objects and namespaces the array of errors automatically for you. `ORM::save()`, `ORM::update()`, and `ORM::create()` all take an optional first parameter which is a [Validation] object to validate along with the model. - public function action_create() - { - try - { - $user = ORM::factory('User'); - $user->username = $_POST['username']; - $user->password = $_POST['password']; - - $extra_rules = Validation::factory($_POST) - ->rule('password_confirm', 'matches', array( - ':validation', ':field', 'password' - )); - - // Pass the extra rules to be validated with the model - $user->save($extra_rules); - } - catch (ORM_Validation_Exception $e) - { - $errors = $e->errors('models'); - } - } + public function action_create() + { + try + { + $user = ORM::factory('User'); + $user->username = $_POST['username']; + $user->password = $_POST['password']; + + $extra_rules = Validation::factory($_POST) + ->rule('password_confirm', 'matches', array( + ':validation', ':field', 'password' + )); + + // Pass the extra rules to be validated with the model + $user->save($extra_rules); + } + catch (ORM_Validation_Exception $e) + { + $errors = $e->errors('models'); + } + } Because the validation object was passed as a parameter to the model, any errors found in that check will be namespaced into a sub-array called `_external`. The array of errors would look something like this: - array( - 'username' => 'This field cannot be empty.', - '_external' => array( - 'password_confirm' => 'The values you entered in the password fields did not match.', - ), - ); + array( + 'username' => 'This field cannot be empty.', + '_external' => array( + 'password_confirm' => 'The values you entered in the password fields did not match.', + ), + ); This ensures that errors from multiple validation objects and models will never overwrite each other.