Several functions are provided for doing basic CRUD work on your tables, including find(),
insert(), update(), delete() and more.
Returns a single row where the primary key matches the value passed in as the first parameter:
<?php
$user = $userModel->find($userId);
The value is returned in the format specified in $returnType.
You can specify more than one row to return by passing an array of primaryKey values instead
of just one:
<?php
$users = $userModel->find([1, 2, 3]);
Note
If no parameters are passed in, find() will return all rows in that model’s table,
effectively acting like findAll(), though less explicit.
Returns null or an indexed array of column values:
<?php
$user = $userModel->findColumn($columnName);
$columnName should be a name of single column else you will get the DataException.
Returns all results:
<?php
$users = $userModel->findAll();
This query may be modified by interjecting Query Builder commands as needed prior to calling this method:
<?php
$users = $userModel->where('active', 1)->findAll();
You can pass in a limit and offset values as the first and second
parameters, respectively:
<?php
$users = $userModel->findAll($limit, $offset);
Returns the first row in the result set. This is best used in combination with the query builder.
<?php
$user = $userModel->where('deleted', 0)->first();
If $useSoftDeletes is true, then the find*() methods will not return any rows where deleted_at IS NOT NULL.
To temporarily override this, you can use the withDeleted() method prior to calling the find*() method.
<?php
// Only gets non-deleted rows (deleted = 0)
$activeUsers = $userModel->findAll();
// Gets all rows
$allUsers = $userModel->withDeleted()->findAll();
Whereas withDeleted() will return both deleted and not-deleted rows, this method modifies
the next find*() methods to return only soft deleted rows:
<?php
$deletedUsers = $userModel->onlyDeleted()->findAll();
The first parameter is an associative array of data to create a new row of data in the database.
If an object is passed instead of an array, it will attempt to convert it to an array.
The array’s keys must match the name of the columns in the $table, while the array’s values are the values to save for that key.
The optional second parameter is of type boolean, and if it is set to false, the method will return a boolean value,
which indicates the success or failure of the query.
You can retrieve the last inserted row’s primary key using the getInsertID() method.
<?php
$data = [
'username' => 'darth',
'email' => 'd.vader@theempire.com',
];
// Inserts data and returns inserted row's primary key
$userModel->insert($data);
// Inserts data and returns true on success and false on failure
$userModel->insert($data, false);
// Returns inserted row's primary key
$userModel->getInsertID();
Added in version 4.3.0.
You can use allowEmptyInserts() method to insert empty data. The Model throws an exception when you try to insert empty data by default. But if you call this method, the check will no longer be performed.
<?php
$userModel->allowEmptyInserts()->insert([]);
You may also change this setting with the $allowEmptyInserts property.
You can enable the check again by calling allowEmptyInserts(false).
Updates an existing record in the database. The first parameter is the $primaryKey of the record to update.
An associative array of data is passed into this method as the second parameter. The array’s keys must match the name
of the columns in a $table, while the array’s values are the values to save for that key:
<?php
$data = [
'username' => 'darth',
'email' => 'd.vader@theempire.com',
];
$userModel->update($id, $data);
Important
Since v4.3.0, this method raises a DatabaseException
if it generates an SQL statement without a WHERE clause.
In previous versions, if it is called without $primaryKey specified and
an SQL statement was generated without a WHERE clause, the query would still
execute and all records in the table would be updated.
Multiple records may be updated with a single call by passing an array of primary keys as the first parameter:
<?php
$data = [
'active' => 1,
];
$userModel->update([1, 2, 3], $data);
When you need a more flexible solution, you can leave the parameters empty and it functions like the Query Builder’s
update command, with the added benefit of validation, events, etc:
<?php
$userModel
->whereIn('id', [1, 2, 3])
->set(['active' => 1])
->update();
This is a wrapper around the insert() and update() methods that handle inserting or updating the record
automatically, based on whether it finds an array key matching the primary key value:
<?php
// Defined as a model property
$primaryKey = 'id';
// Does an insert()
$data = [
'username' => 'darth',
'email' => 'd.vader@theempire.com',
];
$userModel->save($data);
// Performs an update, since the primary key, 'id', is found.
$data = [
'id' => 3,
'username' => 'darth',
'email' => 'd.vader@theempire.com',
];
$userModel->save($data);
The save method also can make working with custom class result objects much simpler by recognizing a non-simple
object and grabbing its public and protected values into an array, which is then passed to the appropriate
insert or update method. This allows you to work with Entity classes in a very clean way. Entity classes are
simple classes that represent a single instance of an object type, like a user, a blog post, a job, etc. This
class is responsible for maintaining the business logic surrounding the object itself, like formatting
elements in a certain way, etc. They shouldn’t have any idea about how they are saved to the database. At their
simplest, they might look like this:
<?php
namespace App\Entities;
class Job
{
protected $id;
protected $name;
protected $description;
public function __get($key)
{
if (property_exists($this, $key)) {
return $this->{$key};
}
}
public function __set($key, $value)
{
if (property_exists($this, $key)) {
$this->{$key} = $value;
}
}
}
A very simple model to work with this might look like:
<?php
namespace App\Models;
use CodeIgniter\Model;
class JobModel extends Model
{
protected $table = 'jobs';
protected $returnType = \App\Entities\Job::class;
protected $allowedFields = [
'name', 'description',
];
}
This model works with data from the jobs table, and returns all results as an instance of App\Entities\Job.
When you need to persist that record to the database, you will need to either write custom methods, or use the
model’s save() method to inspect the class, grab any public and private properties, and save them to the database:
<?php
// Retrieve a Job instance
$job = $model->find(15);
// Make some changes
$job->name = 'Foobar';
// Save the changes
$model->save($job);
Note
If you find yourself working with Entities a lot, CodeIgniter provides a built-in Entity class
that provides several handy features that make developing Entities simpler.
Added in version 4.5.0.
When saving data, if you pass Time instances, they are
converted to strings with the format defined in dateFormat['datetime'] and
dateFormat['date'] in the
database configuration.
Note
Prior to v4.5.0, the date/time formats were hard coded as Y-m-d H:i:s
and Y-m-d in the Model class.
Added in version 4.7.0.
The insert(), insertBatch() (when $useAutoIncrement is false), update(),
and delete() methods validate primary key values before executing database queries.
Invalid values such as null, 0, '0', empty strings, booleans, empty arrays,
or nested arrays will throw an InvalidArgumentException with a specific error message.
If you need to customize this behavior (e.g., to allow 0 as a valid primary key for
legacy systems), you can override the validateID() method in your model.
Warning
In-Model validation is performed just before data is stored in the
database. Prior to that point, the data has not yet been validated. Processing
user-input data prior to validation may introduce vulnerabilities.
The Model class provides a way to automatically have all data validated
prior to saving to the database with the insert(), update(), or save() methods.
Important
When you update data, by default, the validation in the model class only
validates provided fields. This is to avoid validation errors when updating only some fields.
However, this means that not all validation rules you set will be checked
during updates. Thus, incomplete data may pass the validation.
For example, required* rules or is_unique rule that require the
values of other fields may not work as expected.
To avoid such glitches, this behavior can be changed by configuration. See
$cleanValidationRules for details.
The first step is to fill out the $validationRules class property with the
fields and rules that should be applied.
If you have custom error message that you want to use, place them in the $validationMessages array:
<?php
namespace App\Models;
use CodeIgniter\Model;
class UserModel extends Model
{
// ...
protected $validationRules = [
'username' => 'required|max_length[30]|alpha_numeric_space|min_length[3]',
'email' => 'required|max_length[254]|valid_email|is_unique[users.email]',
'password' => 'required|max_length[255]|min_length[8]',
'pass_confirm' => 'required_with[password]|max_length[255]|matches[password]',
];
protected $validationMessages = [
'email' => [
'is_unique' => 'Sorry. That email has already been taken. Please choose another.',
],
];
}
If you’d rather organize your rules and error messages within the
Validation Config File, you can
do that and simply set $validationRules to the name of the validation rule
group you created:
<?php
namespace App\Models;
use CodeIgniter\Model;
class UserModel extends Model
{
// ...
protected $validationRules = 'users';
}
The other way to set the validation rules to fields by functions,
-
class CodeIgniter\Model
-
CodeIgniter\Model::setValidationRule($field, $fieldRules)
- Parameters:
$field (string)
$fieldRules (array)
This function will set the field validation rules.
Usage example:
<?php
$fieldName = 'username';
$fieldRules = 'required|max_length[30]|alpha_numeric_space|min_length[3]';
$model->setValidationRule($fieldName, $fieldRules);
-
CodeIgniter\Model::setValidationRules($validationRules)
- Parameters:
-
This function will set the validation rules.
Usage example:
<?php
$validationRules = [
'username' => 'required|max_length[30]|alpha_numeric_space|min_length[3]',
'email' => [
'rules' => 'required|max_length[254]|valid_email|is_unique[users.email]',
'errors' => [
'required' => 'We really need your email.',
],
],
];
$model->setValidationRules($validationRules);
The other way to set the validation message to fields by functions,
-
CodeIgniter\Model::setValidationMessage($field, $fieldMessages)
- Parameters:
$field (string)
$fieldMessages (array)
This function will set the field wise error messages.
Usage example:
<?php
$fieldName = 'name';
$fieldValidationMessage = [
'required' => 'Your name is required here',
];
$model->setValidationMessage($fieldName, $fieldValidationMessage);
-
CodeIgniter\Model::setValidationMessages($validationMessages)
- Parameters:
-
This function will set the field messages.
Usage example:
<?php
$fieldValidationMessage = [
'name' => [
'required' => 'Your baby name is missing.',
'min_length' => 'Too short, man!',
],
];
$model->setValidationMessages($fieldValidationMessage);
Now, whenever you call the insert(), update(), or save() methods, the data will be validated. If it fails,
the model will return boolean false.
You can use the errors() method to retrieve the validation errors:
<?php
if ($model->save($data) === false) {
return view('updateUser', ['errors' => $model->errors()]);
}
This returns an array with the field names and their associated errors that can be used to either show all of the
errors at the top of the form, or to display them individually:
<?php if (! empty($errors)): ?>
<div class="alert alert-danger">
<?php foreach ($errors as $field => $error): ?>
<p><?= esc($error) ?></p>
<?php endforeach ?>
</div>
<?php endif ?>
You can retrieve a model’s validation rules by accessing its validationRules
property:
<?php
$rules = $model->validationRules;
You can also retrieve just a subset of those rules by calling the accessor
method directly, with options:
<?php
$rules = $model->getValidationRules($options);
The $options parameter is an associative array with one element,
whose key is either 'except' or 'only', and which has as its
value an array of fieldnames of interest:
<?php
// get the rules for all but the "username" field
$rules = $model->getValidationRules(['except' => ['username']]);
// get the rules for only the "city" and "state" fields
$rules = $model->getValidationRules(['only' => ['city', 'state']]);
The model provides a simple method to replace parts of your rules based on data that’s being passed into it. This
sounds fairly obscure but can be especially handy with the is_unique validation rule. Placeholders are simply
the name of the field (or array key) that was passed in as $data surrounded by curly brackets. It will be
replaced by the value of the matched incoming field. An example should clarify this:
<?php
namespace App\Models;
use CodeIgniter\Model;
class MyModel extends Model
{
// ...
protected $validationRules = [
'id' => 'max_length[19]|is_natural_no_zero',
'email' => 'required|max_length[254]|valid_email|is_unique[users.email,id,{id}]',
];
}
Note
Since v4.3.5, you must set the validation rules for the placeholder
field (id).
In this set of rules, it states that the email address should be unique in the database, except for the row
that has an id matching the placeholder’s value. Assuming that the form POST data had the following:
<?php
$_POST = [
'id' => 4,
'email' => 'foo@example.com',
];
then the {id} placeholder would be replaced with the number 4, giving this revised rule:
<?php
namespace App\Models;
use CodeIgniter\Model;
class MyModel extends Model
{
// ...
protected $validationRules = [
'id' => 'max_length[19]|is_natural_no_zero',
'email' => 'required|max_length[254]|valid_email|is_unique[users.email,id,4]',
];
}
So it will ignore the row in the database that has id=4 when it verifies the email is unique.
Note
Since v4.3.5, if the placeholder (id) value does not pass the
validation, the placeholder would not be replaced.
This can also be used to create more dynamic rules at runtime, as long as you take care that any dynamic
keys passed in don’t conflict with your form data.
To help protect against Mass Assignment Attacks, the Model class requires that you list all of the field names
that can be changed during inserts and updates in the $allowedFields class property. Any data provided
in addition to these will be removed prior to hitting the database. This is great for ensuring that timestamps,
or primary keys do not get changed.
<?php
namespace App\Models;
use CodeIgniter\Model;
class MyModel extends Model
{
// ...
protected $allowedFields = ['name', 'email', 'address'];
}
Occasionally, you will find times where you need to be able to change these elements. This is often during
testing, migrations, or seeds. In these cases, you can turn the protection on or off:
<?php
$model->protect(false)
->insert($data)
->protect(true);
You can specify the format that data should be returned as when using the find*() methods as the class property,
$returnType. There may be times that you would like the data back in a different format, though. The Model
provides methods that allow you to do just that.
Note
These methods only change the return type for the next find*() method call. After that,
it is reset to its default value.
Returns data from the next find*() method as associative arrays:
<?php
$users = $userModel->asArray()->where('status', 'active')->findAll();
Returns data from the next find*() method as standard objects or custom class instances:
<?php
// Return as standard objects
$users = $userModel->asObject()->where('status', 'active')->findAll();
// Return as custom class instances
$users = $userModel->asObject('User')->where('status', 'active')->findAll();
Sometimes, you need to process large amounts of data and would run the risk of running out of memory.
To make this simpler, you may use the chunk() method to get smaller chunks of data that you can then
do your work on. The first parameter is the number of rows to retrieve in a single chunk. The second
parameter is a Closure that will be called for each row of data.
This is best used during cronjobs, data exports, or other large tasks.
<?php
$userModel->chunk(100, static function ($data) {
// do something.
// $data is a single row of data.
});