Skip to content

Commit

Permalink
merge from 1.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
qiang.xue committed Jan 15, 2009
1 parent 5b7d35c commit 8ebf686
Show file tree
Hide file tree
Showing 25 changed files with 843 additions and 548 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG
Expand Up @@ -15,6 +15,7 @@ Version 1.0.2 to be released
- Bug: CDbAuthManager::saveAuthAssignment() causes updating all rows (Qiang)
- Bug: Fixed an issue in CUrlManager::createUrl when GET parameters contain arrays (Qiang)
- New #88: Added public properties to CActiveRecord::safeAttributes() (Qiang)
- New #92: Empty error messages in models are handled better when being displayed (Qiang)
- New: Added CActiveRecord::getRelated() (Qiang)
- New: Added 'return' option to HTML options in CHtml (Qiang)
- New: Refactored CSS-dependent widgets by adding registerCssFile static methods (Qiang)
Expand All @@ -23,7 +24,7 @@ Version 1.0.2 to be released
- New: Added scenario-based massive model attribute assignment (Qiang)
- New: Added support to specify views in terms of path aliases (Qiang)
- New: Enhanced getBaseUrl to allow it to return an absolute URL (Qiang)

- New: Allow flash message to be deleted right after its first access (Qiang)

Version 1.0.1 January 4, 2009
-----------------------------
Expand Down
58 changes: 3 additions & 55 deletions UPGRADE
Expand Up @@ -12,66 +12,14 @@ for both A and B.

Upgrading from v1.0.1
---------------------
- CActiveRecord::saveAttributes() is removed. Please use the following alternative:

$model->setAttributes($values,false);
$model->update();


- Due to the introduction of the scenario-based massive assignment feature,
we have to make the following BC breaking changes. Please be very careful
if you want to upgrade, as the changes will most likely affect or break
your existing code.

The signature of the following methods in CModel (inheirted by CFormModel
and CActiveRecord) is changed:

public function validate($scenario='',$attributes=null)
public function setAttributes($values,$scenario='')

And the following methods are removed from CActiveRecord:

public function protectedAttributes()
public function safeAttributes()


The above changes will affect your code if you call any of the above
methods or if your code contains the following assignment statements:

$model->attributes=$data;


Starting from version 1.0.2, massive attribute assignment is based on
validation rules and scenarios. In particular, an attribute can be
massively assigned if it meets both of the following conditions:

* The attribute name appears in the attribute list of some validation rule
which applies to the current scenario. A validation rule applies to
a specified scenario if the `on` option of the rule is not set or
contains the specified scenario name.

* The attribute name is a valid model attribute. For CFormModel,
this means the entry name must refer to a public member variable of
the model class; while for CActiveRecord, this means the entry name
must refer to either a column of the associated DB table or a member
variable of the class.

As a result, if you previously used either protectedAttributes() or
safeAttributes() to limit massive assignments, you should change to
use validation rules to specify this limit. For attributes that don't
need validation but still need massive assignments, they can be listed
in a 'safe' validation rule.
we removed CActiveRecord::protectedAttributes(). Please use safeAttributes()
to specify which attributes are safe to be massively assigned.

For more details about the scenario-based assignment and validation,
please read the following tutorial sections:
please read the following tutorial section:

http://www.yiiframework.com/doc/guide/form.model#securing-attribute-assignments
http://www.yiiframework.com/doc/guide/form.model#triggering-validation


- The methods CActiveRecord::protectedAttributes() and CActiveRecord::safeAttributes()
are removed due to the introduction of the above feature. You may need
to adjust your code by changing the validation rules accordingly.


Upgrading from v1.0.0
Expand Down
2 changes: 0 additions & 2 deletions demos/blog/protected/models/LoginForm.php
Expand Up @@ -23,8 +23,6 @@ public function rules()
array('username, password', 'required'),
// password needs to be authenticated
array('password', 'authenticate'),
// rememberMe does not need validation. it can be massively assigned
array('rememberMe', 'safe'),
);
}

Expand Down
12 changes: 9 additions & 3 deletions demos/blog/protected/models/Post.php
Expand Up @@ -36,10 +36,17 @@ public function rules()
array('title', 'length', 'max'=>128),
array('title, content, status', 'required'),
array('status', 'numerical', 'min'=>0, 'max'=>3),
array('tagInput', 'safe'),
);
}

/**
* @return array attributes that can be massively assigned
*/
public function safeAttributes()
{
return 'title, content, status, tagInput';
}

/**
* @return array relational rules.
*/
Expand Down Expand Up @@ -122,8 +129,7 @@ protected function afterSave()
{
if(($tag=Tag::model()->findByAttributes(array('name'=>$name)))===null)
{
$tag=new Tag;
$tag->name=$name;
$tag=new Tag(array('name'=>$name));
$tag->save();
}
$this->dbConnection->createCommand("INSERT INTO PostTag (postId, tagId) VALUES ({$this->id},{$tag->id})")->execute();
Expand Down
7 changes: 0 additions & 7 deletions demos/phonebook/protected/models/Contact.php
Expand Up @@ -22,11 +22,4 @@ public static function model($className=__CLASS__)
{
return parent::model($className);
}

public function rules()
{
return array(
array('id, name, phone', 'required'),
);
}
}
108 changes: 61 additions & 47 deletions docs/guide/form.model.txt
Expand Up @@ -169,9 +169,6 @@ valid number.
- `required`: alias of [CRequiredValidator], ensuring the attribute is
not empty.

- `safe`: alias of [CSafeValidator], marking that the attribute is safe
to be assigned in a massive manner.

- `type`: alias of [CTypeValidator], ensuring the attribute is of
specific data type.

Expand All @@ -184,18 +181,22 @@ Below we list some examples of using the predefined validators:

~~~
[php]
// ensure password attribute is the same as password2 attribute
array('password', 'compare', 'compareAttribute'=>'password2')
// ensure username's length is between 3 and 12
array('username', 'length', 'min'=>3, 'max'=>12)
// ensure age is a non-negative integer
array('age', 'numeric', 'integerOnly'=>true, 'min'=>0)
// username is required
array('username', 'required'),
// username must be between 3 and 12 characters
array('username', 'length', 'min'=>3, 'max'=>12),
// when in register scenario, password must match password2
array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'),
// when in login scenario, password must be authenticated
array('password', 'authenticate', 'on'=>'login'),
~~~


Securing Attribute Assignments
------------------------------

> Note: scenario-based attribute assignment has been available since version 1.0.2.

After a model instance is created, we often need to populate its
attributes with the data submitted by end-users. This can be done
conveniently using the following massive assignment:
Expand All @@ -221,49 +222,62 @@ foreach($_POST['LoginForm'] as $name=>$value)
}
~~~

The task of deciding whether a data entry is safe or not is based on
the validation rules that we just described. In particular, a data entry
is considered to be safe if it meets both of the following conditions:

- The entry name appears in the attribute list of some validation rule
which applies to the current scenario. A validation rule applies to
a specified scenario if the `on` option of the rule is not set or
contains the specified scenario name.

- The entry name is a valid model attribute. For [CFormModel], this means
the entry name must refer to a public member variable of the model class;
while for [CActiveRecord], this means the entry name must refer to either
a column of the associated DB table or a member variable of the class.


> Tip: If the scenario is empty, only the validation rules with empty `on`
> option will be applied. In this case, we can write the massive assignment
> statement as follows,
>
> ~~~
> [php]
> $model->attributes=$_POST['LoginForm'];
> // equivalent to: $model->setAttributes($_POST['LoginForm']);
> ~~~
>
> If an attribute does not need any validation but we still want to massively
> assign it, we can use the following `safe` validation rule to mark it:
>
> ~~~
> [php]
> array('AttributeName', 'safe')
> ~~~
>

To assign a data entry that does not meet the first condition, we need to
use the following individual assignment:
The task of deciding whether a data entry is safe or not is based
the return value of a method named `safeAttributes` and the specified
scenario. By default, the method returns all public member variables
as safe attributes for [CFormModel], while it returns all table columns
except the primary key as safe attributes for [CActiveRecord]. We may
override this method to limit safe attributes according to scenarios.
For example, a user model may contain many attributes, but in `login`
scenario we only need to use `username` and `password` attributes.
We can specify this limit as follows:

~~~
[php]
$model->permission='admin';
public function safeAttributes()
{
return array(
parent::safeAttributes(),
'login' => 'username, password',
);
}
~~~

> Note: scenario-based attribute assignment has been available since version 1.0.2.
More accurately, the return value of the `safeAttributes` method should be
of the following structure:

~~~
[php]
array(
// these attributes can be massively assigned in any scenario
// that is not explicitly specified below
'attr1, attr2, ...',
*
// these attributes can be massively assigned only in scenario 1
'scenario1' => 'attr2, attr3, ...',
*
// these attributes can be massively assigned only in scenario 2
'scenario2' => 'attr1, attr3, ...',
)
~~~

If the model is not scenario-sensitive (i.e., it is only used
in one scenario, or all scenarios share the same set of safe attributes),
the return value can be simplified as a single string:

~~~
[php]
'attr1, attr2, ...'
~~~

For data entries that are not safe, we need to assign them to the corresponding
attributes using individual assign statements, like the following:

~~~
[php]
$model->permission='admin';
$model->id=1;
~~~


Triggering Validation
Expand Down
2 changes: 1 addition & 1 deletion framework/YiiBase.php
Expand Up @@ -479,6 +479,7 @@ public static function t($category,$message,$params=array(),$source=null)
'CLogger' => '/logging/CLogger.php',
'CProfileLogRoute' => '/logging/CProfileLogRoute.php',
'CWebLogRoute' => '/logging/CWebLogRoute.php',
'ControllerGenerator' => '/rad/controller/ControllerGenerator.php',
'CDateParser' => '/utils/CDateParser.php',
'CFileHelper' => '/utils/CFileHelper.php',
'CMarkdownParser' => '/utils/CMarkdownParser.php',
Expand All @@ -494,7 +495,6 @@ public static function t($category,$message,$params=array(),$source=null)
'CRangeValidator' => '/validators/CRangeValidator.php',
'CRegularExpressionValidator' => '/validators/CRegularExpressionValidator.php',
'CRequiredValidator' => '/validators/CRequiredValidator.php',
'CSafeValidator' => '/validators/CSafeValidator.php',
'CStringValidator' => '/validators/CStringValidator.php',
'CTypeValidator' => '/validators/CTypeValidator.php',
'CUniqueValidator' => '/validators/CUniqueValidator.php',
Expand Down

0 comments on commit 8ebf686

Please sign in to comment.