Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
18d7224a
Commit
18d7224a
authored
Jan 27, 2014
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixes #2149: Added `yii\base\DynamicModel` to support ad-hoc data validation
parent
0a638c1a
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
255 additions
and
5 deletions
+255
-5
CHANGELOG.md
framework/CHANGELOG.md
+1
-0
DynamicModel.php
framework/base/DynamicModel.php
+197
-0
Model.php
framework/base/Model.php
+2
-2
Validator.php
framework/validators/Validator.php
+3
-3
DynamicModelTest.php
tests/unit/framework/base/DynamicModelTest.php
+52
-0
No files found.
framework/CHANGELOG.md
View file @
18d7224a
...
...
@@ -146,6 +146,7 @@ Yii Framework 2 Change Log
-
New #1393:
[
Codeception testing framework integration
](
https://github.com/yiisoft/yii2-codeception
)
(
Ragazzo
)
-
New #1438:
[
MongoDB integration
](
https://github.com/yiisoft/yii2-mongodb
)
ActiveRecord and Query (klimov-paul)
-
New #1956: Implemented test fixture framework (qiangxue)
-
New #2149: Added
`yii\base\DynamicModel`
to support ad-hoc data validation (qiangxue)
-
New: Yii framework now comes with core messages in multiple languages
-
New: Added yii
\c
odeception
\D
bTestCase (qiangxue)
...
...
framework/base/DynamicModel.php
0 → 100644
View file @
18d7224a
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace
yii\base
;
use
yii\validators\Validator
;
/**
* DynamicModel is a model class primarily used to support ad-hoc data validation.
*
* The typical usage of DynamicModel is as follows,
*
* ```php
* public function actionSearch($name, $email)
* {
* $model = DynamicModel::validateData(compact('name', 'email'), [
* [['name', 'email'], 'string', 'max' => 128]],
* ['email', 'email'],
* ]);
* if ($model->hasErrors()) {
* // validation fails
* } else {
* // validation succeeds
* }
* }
* ```
*
* The above example shows how to validate `$name` and `$email` with the help of DynamicModel.
* The [[validateData()]] method creates an instance of DynamicModel, defines the attributes
* using the given data (`name` and `email` in this example), and then calls [[Model::validate()]].
*
* You can check the validation result by [[hasErrors()]], like you do with a normal model.
* You may also access the dynamic attributes defined through the model instance, e.g.,
* `$model->name` and `$model->email`.
*
* Alternatively, you may use the following more "classic" syntax to perform ad-hoc data validation:
*
* ```php
* $model = new DynamicModel(compact('name', 'email'));
* $model->addRule(['name', 'email'], 'string', ['max' => 128])
* ->addRule('email', 'email')
* ->validate();
* ```
*
* DynamicModel implements the above ad-hoc data validation feature by supporting the so-called
* "dynamic attributes". It basically allows an attribute to be defined dynamically through its constructor
* or [[defineAttribute()]].
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class
DynamicModel
extends
Model
{
private
$_attributes
=
[];
/**
* Constructors.
* @param array $attributes the dynamic attributes (name-value pairs, or names) being defined
* @param array $config the configuration array to be applied to this object.
*/
public
function
__construct
(
array
$attributes
,
$config
=
[])
{
foreach
(
$attributes
as
$name
=>
$value
)
{
if
(
is_integer
(
$name
))
{
$this
->
_attributes
[
$value
]
=
null
;
}
else
{
$this
->
_attributes
[
$name
]
=
$value
;
}
}
}
/**
* @inheritdoc
*/
public
function
__get
(
$name
)
{
if
(
array_key_exists
(
$name
,
$this
->
_attributes
))
{
return
$this
->
_attributes
[
$name
];
}
else
{
return
parent
::
__get
(
$name
);
}
}
/**
* @inheritdoc
*/
public
function
__set
(
$name
,
$value
)
{
if
(
array_key_exists
(
$name
,
$this
->
_attributes
))
{
$this
->
_attributes
[
$name
]
=
$value
;
}
else
{
parent
::
__set
(
$name
,
$value
);
}
}
/**
* @inheritdoc
*/
public
function
__isset
(
$name
)
{
if
(
array_key_exists
(
$name
,
$this
->
_attributes
))
{
return
isset
(
$this
->
_attributes
[
$name
]);
}
else
{
return
parent
::
__isset
(
$name
);
}
}
/**
* @inheritdoc
*/
public
function
__unset
(
$name
)
{
if
(
array_key_exists
(
$name
,
$this
->
_attributes
))
{
unset
(
$this
->
_attributes
[
$name
]);
}
else
{
parent
::
__unset
(
$name
);
}
}
/**
* Defines an attribute.
* @param string $name the attribute name
* @param mixed $value the attribute value
*/
public
function
defineAttribute
(
$name
,
$value
=
null
)
{
$this
->
_attributes
[
$name
]
=
$value
;
}
/**
* Undefines an attribute.
* @param string $name the attribute name
*/
public
function
undefineAttribute
(
$name
)
{
unset
(
$this
->
_attributes
[
$name
]);
}
/**
* Adds a validation rule to this model.
* You can also directly manipulate [[validators]] to add or remove validation rules.
* This method provides a shortcut.
* @param string|array $attributes the attribute(s) to be validated by the rule
* @param mixed $validator the validator for the rule.This can be a built-in validator name,
* a method name of the model class, an anonymous function, or a validator class name.
* @param array $options the options (name-value pairs) to be applied to the validator
* @return static the model itself
*/
public
function
addRule
(
$attributes
,
$validator
,
$options
=
[])
{
$validators
=
$this
->
getValidators
();
$validators
->
append
(
Validator
::
createValidator
(
$validator
,
$this
,
(
array
)
$attributes
,
$options
));
return
$this
;
}
/**
* Validates the given data with the specified validation rules.
* This method will create a DynamicModel instance, populate it with the data to be validated,
* create the specified validation rules, and then validate the data using these rules.
* @param array $data the data (name-value pairs) to be validated
* @param array $rules the validation rules. Please refer to [[Model::rules()]] on the format of this parameter.
* @return static the model instance that contains the data being validated
* @throws InvalidConfigException if a validation rule is not specified correctly.
*/
public
static
function
validateData
(
array
$data
,
$rules
=
[])
{
/** @var DynamicModel $model */
$model
=
new
static
(
$data
);
if
(
!
empty
(
$rules
))
{
$validators
=
$model
->
getValidators
();
foreach
(
$rules
as
$rule
)
{
if
(
$rule
instanceof
Validator
)
{
$validators
->
append
(
$rule
);
}
elseif
(
is_array
(
$rule
)
&&
isset
(
$rule
[
0
],
$rule
[
1
]))
{
// attributes, validator type
$validator
=
Validator
::
createValidator
(
$rule
[
1
],
$model
,
(
array
)
$rule
[
0
],
array_slice
(
$rule
,
2
));
$validators
->
append
(
$validator
);
}
else
{
throw
new
InvalidConfigException
(
'Invalid validation rule: a rule must specify both attribute names and validator type.'
);
}
}
$model
->
validate
();
}
return
$model
;
}
/**
* @inheritdoc
*/
public
function
attributes
()
{
return
array_keys
(
$this
->
_attributes
);
}
}
framework/base/Model.php
View file @
18d7224a
...
...
@@ -102,8 +102,8 @@ class Model extends Component implements IteratorAggregate, ArrayAccess, Arrayab
* where
*
* - attribute list: required, specifies the attributes array to be validated, for single attribute you can pass string;
* - validator type: required, specifies the validator to be used. It can be
the name of a model
*
class method, the name of a built-in validator, or a validator class name (or its path alias)
.
* - validator type: required, specifies the validator to be used. It can be
a built-in validator name,
*
a method name of the model class, an anonymous function, or a validator class name
.
* - on: optional, specifies the [[scenario|scenarios]] array when the validation
* rule can be applied. If this option is not set, the rule will apply to all scenarios.
* - additional name-value pairs can be specified to initialize the corresponding validator properties.
...
...
framework/validators/Validator.php
View file @
18d7224a
...
...
@@ -124,8 +124,8 @@ class Validator extends Component
/**
* Creates a validator object.
* @param
string $type the validator type. This can be a method
name,
* a
built-in validator name, a class name, or a path alias of the validator class
.
* @param
mixed $type the validator type. This can be a built-in validator
name,
* a
method name of the model class, an anonymous function, or a validator class name
.
* @param \yii\base\Model $object the data object to be validated.
* @param array|string $attributes list of attributes to be validated. This can be either an array of
* the attribute names or a string of comma-separated attribute names.
...
...
@@ -136,7 +136,7 @@ class Validator extends Component
{
$params
[
'attributes'
]
=
$attributes
;
if
(
method_exists
(
$object
,
$type
))
{
if
(
$type
instanceof
\Closure
||
method_exists
(
$object
,
$type
))
{
// method-based validator
$params
[
'class'
]
=
__NAMESPACE__
.
'\InlineValidator'
;
$params
[
'method'
]
=
$type
;
...
...
tests/unit/framework/base/DynamicModelTest.php
0 → 100644
View file @
18d7224a
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace
yiiunit\framework\base
;
use
yii\base\DynamicModel
;
use
yiiunit\TestCase
;
/**
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class
DynamicModelTest
extends
TestCase
{
protected
function
setUp
()
{
parent
::
setUp
();
$this
->
mockApplication
();
}
public
function
testValidateData
()
{
$email
=
'invalid'
;
$name
=
'long name'
;
$age
=
''
;
$model
=
DynamicModel
::
validateData
(
compact
(
'name'
,
'email'
,
'age'
),
[
[[
'email'
,
'name'
,
'age'
],
'required'
],
[
'email'
,
'email'
],
[
'name'
,
'string'
,
'max'
=>
3
],
]);
$this
->
assertTrue
(
$model
->
hasErrors
());
$this
->
assertTrue
(
$model
->
hasErrors
(
'email'
));
$this
->
assertTrue
(
$model
->
hasErrors
(
'name'
));
$this
->
assertTrue
(
$model
->
hasErrors
(
'age'
));
}
public
function
testDynamicProperty
()
{
$email
=
'invalid'
;
$name
=
'long name'
;
$model
=
new
DynamicModel
(
compact
(
'name'
,
'email'
));
$this
->
assertEquals
(
$email
,
$model
->
email
);
$this
->
assertEquals
(
$name
,
$model
->
name
);
$this
->
setExpectedException
(
'yii\base\UnknownPropertyException'
);
$age
=
$model
->
age
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment