mirror of
https://github.com/codeigniter4/CodeIgniter4.git
synced 2025-02-20 11:44:28 +08:00
Adding validation to Models. Needs docs.
This commit is contained in:
parent
59a3fe2a1f
commit
a5f4f8bc5c
@ -513,6 +513,25 @@ class Services
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The Validation class provides tools for validating input data.
|
||||
*/
|
||||
public static function validation(Validation $config = null, $getShared = true)
|
||||
{
|
||||
if ($getShared)
|
||||
{
|
||||
return self::getSharedInstance('validation', $config);
|
||||
}
|
||||
|
||||
if (is_null($config))
|
||||
{
|
||||
$config = new Validation();
|
||||
}
|
||||
|
||||
return new \CodeIgniter\Validation\Validation($config);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Utility Methods - DO NOT EDIT
|
||||
|
149
system/Model.php
149
system/Model.php
@ -37,9 +37,9 @@
|
||||
*/
|
||||
|
||||
use CodeIgniter\Pager\Pager;
|
||||
use CodeIgniter\Validation\ValidationInterface;
|
||||
use Config\App;
|
||||
use Config\Database;
|
||||
//use Config\Services;
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
use CodeIgniter\Database\BaseBuilder;
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
@ -191,6 +191,38 @@ class Model
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* Rules used to validate data in insert, update, and save methods.
|
||||
* The array must match the format of data passed to the Validation
|
||||
* library.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $validationRules = [];
|
||||
|
||||
/**
|
||||
* Contains any custom error messages to be
|
||||
* used during data validation.
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
protected $validationMessages = null;
|
||||
|
||||
/**
|
||||
* Skip the model's validation. Used in conjunction with skipValidation()
|
||||
* to skip data validation for any future calls.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $skipValidation = false;
|
||||
|
||||
/**
|
||||
* Our validator instance.
|
||||
*
|
||||
* @var \CodeIgniter\Validation\ValidationInterface
|
||||
*/
|
||||
protected $validation;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@ -199,7 +231,7 @@ class Model
|
||||
* @param ConnectionInterface $db
|
||||
* @param BaseConfig $config Config/App()
|
||||
*/
|
||||
public function __construct(ConnectionInterface &$db = null, BaseConfig $config = null)
|
||||
public function __construct(ConnectionInterface &$db = null, BaseConfig $config = null, ValidationInterface $validation = null)
|
||||
{
|
||||
if ($db instanceof ConnectionInterface)
|
||||
{
|
||||
@ -220,6 +252,12 @@ class Model
|
||||
|
||||
$this->tempReturnType = $this->returnType;
|
||||
$this->tempUseSoftDeletes = $this->useSoftDeletes;
|
||||
|
||||
if (is_null($validation))
|
||||
{
|
||||
$validation = \Config\Services::validation();
|
||||
}
|
||||
$this->validation = $validation;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
@ -532,6 +570,15 @@ class Model
|
||||
*/
|
||||
public function insert($data)
|
||||
{
|
||||
// Validate data before saving.
|
||||
if ($this->skipValidation === false)
|
||||
{
|
||||
if ($this->validate($data) === false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called first so we don't
|
||||
// strip out created_at values.
|
||||
$data = $this->doProtectFields($data);
|
||||
@ -569,6 +616,15 @@ class Model
|
||||
*/
|
||||
public function update($id, $data)
|
||||
{
|
||||
// Validate data before saving.
|
||||
if ($this->skipValidation === false)
|
||||
{
|
||||
if ($this->validate($data) === false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called first so we don't
|
||||
// strip out updated_at values.
|
||||
$data = $this->doProtectFields($data);
|
||||
@ -953,6 +1009,95 @@ class Model
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Grabs the last error(s) that occurred. If data was validated,
|
||||
* it will first check for errors there, otherwise will try to
|
||||
* grab the last error from the Database connection.
|
||||
*
|
||||
* @param bool $forceDB Always grab the db error, not validation
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function errors(bool $forceDB = false)
|
||||
{
|
||||
// Do we have validation errors?
|
||||
if ($forceDB === false && $this->skipValidation === false)
|
||||
{
|
||||
$errors = $this->validation->getErrors();
|
||||
|
||||
if (! empty($errors))
|
||||
{
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
|
||||
// Still here? Grab the database-specific error, if any.
|
||||
$error = $this->db->getError();
|
||||
|
||||
return $error['message'] ?? null;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Validation
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set the value of the skipValidation flag.
|
||||
*
|
||||
* @param bool $skip
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function skipValidation(bool $skip = true)
|
||||
{
|
||||
$this->skipValidation = $skip;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Validate the data against the validation rules (or the validation group)
|
||||
* specified in the class property, $validationRules.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($data): bool
|
||||
{
|
||||
if ($this->skipValidation === true || empty($this->validationRules))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Query Builder works with objects as well as arrays,
|
||||
// but validation requires array, so cast away.
|
||||
if (is_object($data))
|
||||
{
|
||||
$data = (array)$data;
|
||||
}
|
||||
|
||||
// ValidationRules can be either a string, which is the group name,
|
||||
// or an array of rules.
|
||||
if (is_string($this->validationRules))
|
||||
{
|
||||
$valid = $this->validation->run($data, $this->validationRules);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->validation->setRules($this->validationRules, $this->validationMessages);
|
||||
$valid = $this->validation->run($data);
|
||||
}
|
||||
|
||||
return (bool)$valid;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Magic
|
||||
|
27
tests/_support/Models/ValidModel.php
Normal file
27
tests/_support/Models/ValidModel.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php namespace Tests\Support\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class ValidModel extends Model
|
||||
{
|
||||
protected $table = 'job';
|
||||
|
||||
protected $returnType = 'object';
|
||||
|
||||
protected $useSoftDeletes = false;
|
||||
|
||||
protected $dateFormat = 'integer';
|
||||
|
||||
protected $allowedFields = ['name', 'description'];
|
||||
|
||||
protected $validationRules = [
|
||||
'name' => 'required|min_length[3]'
|
||||
];
|
||||
|
||||
protected $validationMessages = [
|
||||
'name' => [
|
||||
'required' => 'You forgot to name the baby.',
|
||||
'min_length' => 'Too short, man!'
|
||||
]
|
||||
];
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
use CodeIgniter\Model;
|
||||
use Tests\Support\Models\JobModel;
|
||||
use Tests\Support\Models\UserModel;
|
||||
use Tests\Support\Models\ValidModel;
|
||||
|
||||
/**
|
||||
* @group DatabaseLive
|
||||
@ -260,7 +261,7 @@ class ModelTest extends \CIDatabaseTestCase
|
||||
$data = new \stdClass();
|
||||
$data->name = 'Magician';
|
||||
$data->description = 'Makes peoples things dissappear.';
|
||||
|
||||
|
||||
$model->protect(false)->save($data);
|
||||
|
||||
$this->seeInDatabase('job', ['name' => 'Magician']);
|
||||
@ -443,5 +444,35 @@ class ModelTest extends \CIDatabaseTestCase
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
public function testValidationBasics()
|
||||
{
|
||||
$model = new ValidModel($this->db);
|
||||
|
||||
$data = [
|
||||
'description' => 'some great marketing stuff'
|
||||
];
|
||||
|
||||
$this->assertFalse($model->insert($data));
|
||||
|
||||
$errors = $model->errors();
|
||||
|
||||
$this->assertEquals('You forgot to name the baby.', $errors['name']);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
public function testSkipValidation()
|
||||
{
|
||||
$model = new ValidModel($this->db);
|
||||
|
||||
$data = [
|
||||
'name' => '2',
|
||||
'description' => 'some great marketing stuff'
|
||||
];
|
||||
|
||||
$this->assertTrue(is_numeric($model->skipValidation(true)->insert($data)));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user