Browse Source

changed the default behavior of scenarios()

tags/2.0.0-beta
Qiang Xue 12 years ago
parent
commit
e828cc6654
  1. 0
      docs/internals/ar.md
  2. 0
      docs/internals/database.md
  3. 77
      framework/base/Model.php
  4. 52
      framework/db/ar/ActiveRecord.php
  5. 1
      framework/db/dao/Query.php

0
docs/internals/ar.md

0
docs/internals/database.md

77
framework/base/Model.php

@ -119,7 +119,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
} }
/** /**
* Returns a list of scenarios and the corresponding relevant attributes. * Returns a list of scenarios and the corresponding active attributes.
* The returned array should be in the following format: * The returned array should be in the following format:
* *
* ~~~ * ~~~
@ -130,27 +130,14 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
* ) * )
* ~~~ * ~~~
* *
* Attributes relevant to the current scenario are considered safe and can be
* massively assigned. When [[validate()]] is invoked, these attributes will
* be validated using the rules declared in [[rules()]].
*
* If an attribute should NOT be massively assigned (thus considered unsafe), * If an attribute should NOT be massively assigned (thus considered unsafe),
* please prefix the attribute with an exclamation character (e.g. '!attribute'). * please prefix the attribute with an exclamation character (e.g. '!attribute').
* *
* WARNING: The default implementation returns the 'default' scenario and the result of
* [[attributes()]]. This means if the model is in 'default' scenario, all
* public member variables can be massively assigned and will be validated when
* calling [[validate()]]. Make sure you override this method if you do not want
* this behavior (e.g. you only want some of the attributes to be massively assigned
* and validated.)
*
* @return array a list of scenarios and the corresponding relevant attributes. * @return array a list of scenarios and the corresponding relevant attributes.
*/ */
public function scenarios() public function scenarios()
{ {
return array( return array();
'default' => $this->attributes(),
);
} }
/** /**
@ -354,8 +341,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
*/ */
public function isAttributeSafe($attribute) public function isAttributeSafe($attribute)
{ {
$scenarios = $this->scenarios(); return in_array($attribute, $this->safeAttributes(), true);
return in_array($attribute, $scenarios[$this->getScenario()], true);
} }
/** /**
@ -481,22 +467,20 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
* @param array $names list of attributes whose value needs to be returned. * @param array $names list of attributes whose value needs to be returned.
* Defaults to null, meaning all attributes listed in [[attributes()]] will be returned. * Defaults to null, meaning all attributes listed in [[attributes()]] will be returned.
* If it is an array, only the attributes in the array will be returned. * If it is an array, only the attributes in the array will be returned.
* @param array $except list of attributes whose value should NOT be returned.
* @return array attribute values (name=>value). * @return array attribute values (name=>value).
*/ */
public function getAttributes($names = null) public function getAttributes($names = null, $except = array())
{ {
$values = array(); $values = array();
if ($names === null) {
if (is_array($names)) { $names = $this->attributes();
foreach ($this->attributes() as $name) { }
if (in_array($name, $names, true)) { foreach ($names as $name) {
$values[$name] = $this->$name; $values[$name] = $this->$name;
} }
} foreach ($except as $name) {
} else { unset($values[$name]);
foreach ($this->attributes() as $name) {
$values[$name] = $this->$name;
}
} }
return $values; return $values;
@ -567,14 +551,19 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
*/ */
public function safeAttributes() public function safeAttributes()
{ {
$scenario = $this->getScenario();
$scenarios = $this->scenarios(); $scenarios = $this->scenarios();
$attributes = array(); if (isset($scenarios[$scenario])) {
foreach ($scenarios[$this->getScenario()] as $attribute) { $attributes = array();
if ($attribute[0] !== '!') { foreach ($scenarios[$scenario] as $attribute) {
$attributes[] = $attribute; if ($attribute[0] !== '!') {
$attributes[] = $attribute;
}
} }
return $attributes;
} else {
return $this->activeAttributes();
} }
return $attributes;
} }
/** /**
@ -583,11 +572,23 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
*/ */
public function activeAttributes() public function activeAttributes()
{ {
$scenario = $this->getScenario();
$scenarios = $this->scenarios(); $scenarios = $this->scenarios();
$attributes = $scenarios[$this->getScenario()]; if (isset($scenarios[$scenario])) {
foreach ($attributes as $i => $attribute) { // scenario declared in scenarios()
if ($attribute[0] === '!') { $attributes = $scenarios[$this->getScenario()];
$attributes[$i] = substr($attribute, 1); foreach ($attributes as $i => $attribute) {
if ($attribute[0] === '!') {
$attributes[$i] = substr($attribute, 1);
}
}
} else {
// use validators to determine active attributes
$attributes = array();
foreach ($this->attributes() as $attribute) {
if ($this->getActiveValidators($attribue) !== array()) {
$attributes[] = $attribute;
}
} }
} }
return $attributes; return $attributes;

52
framework/db/ar/ActiveRecord.php

@ -44,6 +44,10 @@ use yii\util\StringHelper;
abstract class ActiveRecord extends Model abstract class ActiveRecord extends Model
{ {
/** /**
* @var ActiveRecord[] global model instances indexed by model class names
*/
private static $_models = array();
/**
* @var array attribute values indexed by attribute names * @var array attribute values indexed by attribute names
*/ */
private $_attributes = array(); private $_attributes = array();
@ -56,6 +60,21 @@ abstract class ActiveRecord extends Model
*/ */
private $_related; private $_related;
/**
* Returns a model instance to support accessing non-static methods such as [[table()]], [[primaryKey()]].
* @return ActiveRecord
*/
public static function model()
{
$className = get_called_class();
if (isset(self::$_models[$className])) {
return self::$_models[$className];
} else {
return self::$_models[$className] = new static;
}
}
/** /**
* Returns the metadata for this AR class. * Returns the metadata for this AR class.
* @param boolean $refresh whether to rebuild the metadata. * @param boolean $refresh whether to rebuild the metadata.
@ -194,7 +213,7 @@ abstract class ActiveRecord extends Model
public static function updateAll($attributes, $condition = '', $params = array()) public static function updateAll($attributes, $condition = '', $params = array())
{ {
$query = new Query; $query = new Query;
$query->update(static::tableName(), $attributes, $condition, $params); $query->update(static::model()->tableName(), $attributes, $condition, $params);
return $query->createCommand(static::getDbConnection())->execute(); return $query->createCommand(static::getDbConnection())->execute();
} }
@ -215,7 +234,7 @@ abstract class ActiveRecord extends Model
$counters[$name] = new Expression($value >= 0 ? "$quotedName+$value" : "$quotedName$value"); $counters[$name] = new Expression($value >= 0 ? "$quotedName+$value" : "$quotedName$value");
} }
$query = new Query; $query = new Query;
$query->update(static::tableName(), $counters, $condition, $params); $query->update(static::model()->tableName(), $counters, $condition, $params);
return $query->createCommand($db)->execute(); return $query->createCommand($db)->execute();
} }
@ -229,7 +248,7 @@ abstract class ActiveRecord extends Model
public static function deleteAll($condition = '', $params = array()) public static function deleteAll($condition = '', $params = array())
{ {
$query = new Query; $query = new Query;
$query->delete(static::tableName(), $condition, $params); $query->delete(static::model()->tableName(), $condition, $params);
return $query->createCommand(static::getDbConnection())->execute(); return $query->createCommand(static::getDbConnection())->execute();
} }
@ -250,9 +269,9 @@ abstract class ActiveRecord extends Model
* You may override this method if the table is not named after this convention. * You may override this method if the table is not named after this convention.
* @return string the table name * @return string the table name
*/ */
public static function tableName() public function tableName()
{ {
return StringHelper::camel2id(basename(get_called_class()), '_'); return StringHelper::camel2id(basename(get_class($this)), '_');
} }
/** /**
@ -266,7 +285,7 @@ abstract class ActiveRecord extends Model
* If the key is a composite one consisting of several columns, it should * If the key is a composite one consisting of several columns, it should
* return the array of the key column names. * return the array of the key column names.
*/ */
public static function primaryKey() public function primaryKey()
{ {
} }
@ -633,27 +652,6 @@ abstract class ActiveRecord extends Model
$this->_attributes[$name] = $value; $this->_attributes[$name] = $value;
} }
/**
* Returns all column attribute values.
* Note, related objects are not returned.
* @param null|array $names names of attributes whose value needs to be returned.
* If this is true (default), then all attribute values will be returned, including
* those that are not loaded from DB (null will be returned for those attributes).
* If this is null, all attributes except those that are not loaded from DB will be returned.
* @return array attribute values indexed by attribute names.
*/
public function getAttributes($names = null)
{
if ($names === null) {
$names = $this->attributes();
}
$values = array();
foreach ($names as $name) {
$values[$name] = isset($this->_attributes[$name]) ? $this->_attributes[$name] : null;
}
return $values;
}
public function getChangedAttributes($names = null) public function getChangedAttributes($names = null)
{ {
if ($names === null) { if ($names === null) {

1
framework/db/dao/Query.php

@ -75,6 +75,7 @@ class Query extends BaseQuery
$qb->query = $this; $qb->query = $this;
return call_user_func_array(array($qb, $method), $params); return call_user_func_array(array($qb, $method), $params);
} else { } else {
/** @var $qb QueryBuilder */
return $qb->build($this); return $qb->build($this);
} }
} }

Loading…
Cancel
Save