Commit 81692447 by Qiang Xue

w

parent 7a37bbf1
...@@ -372,10 +372,18 @@ class YiiBase ...@@ -372,10 +372,18 @@ class YiiBase
$object = new $type; $object = new $type;
} }
if ($object instanceof \yii\base\Component) {
$object->preinit();
}
foreach ($config as $key => $value) { foreach ($config as $key => $value) {
$object->$key = $value; $object->$key = $value;
} }
if ($object instanceof \yii\base\Component) {
$object->init();
}
return $object; return $object;
} }
......
...@@ -101,6 +101,8 @@ namespace yii\base; ...@@ -101,6 +101,8 @@ namespace yii\base;
* [[disableBehavior]], respectively. When disabled, the behavior's public properties and methods * [[disableBehavior]], respectively. When disabled, the behavior's public properties and methods
* cannot be accessed via the component. * cannot be accessed via the component.
* *
* Components created via [[\Yii::createComponent]] have life cycles. In particular,
*
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
...@@ -170,17 +172,17 @@ class Component ...@@ -170,17 +172,17 @@ class Component
public function __set($name, $value) public function __set($name, $value)
{ {
$setter = 'set' . $name; $setter = 'set' . $name;
if (method_exists($this, $setter)) { if (method_exists($this, $setter)) { // write property
return $this->$setter($value); return $this->$setter($value);
} }
elseif (method_exists($this, $name) && strncasecmp($name, 'on', 2) === 0) { elseif (method_exists($this, $name) && strncasecmp($name, 'on', 2) === 0) { // event
$name = strtolower($name); $name = strtolower($name);
if (!isset($this->_e[$name])) { if (!isset($this->_e[$name])) {
$this->_e[$name] = new Vector; $this->_e[$name] = new Vector;
} }
return $this->_e[$name]->add($value); return $this->_e[$name]->add($value);
} }
elseif (is_array($this->_b)) { elseif (is_array($this->_b)) { // behavior
foreach ($this->_b as $object) { foreach ($this->_b as $object) {
if ($object->getEnabled() && (property_exists($object, $name) || $object->canSetProperty($name))) { if ($object->getEnabled() && (property_exists($object, $name) || $object->canSetProperty($name))) {
return $object->$name = $value; return $object->$name = $value;
...@@ -247,16 +249,16 @@ class Component ...@@ -247,16 +249,16 @@ class Component
public function __unset($name) public function __unset($name)
{ {
$setter = 'set' . $name; $setter = 'set' . $name;
if (method_exists($this, $setter)) { if (method_exists($this, $setter)) { // write property
$this->$setter(null); $this->$setter(null);
} }
elseif (method_exists($this, $name) && strncasecmp($name, 'on', 2) === 0) { elseif (method_exists($this, $name) && strncasecmp($name, 'on', 2) === 0) { // event
unset($this->_e[strtolower($name)]); unset($this->_e[strtolower($name)]);
} }
elseif (isset($this->_b[$name])) { elseif (isset($this->_b[$name])) { // behavior
$this->detachBehavior($name); $this->detachBehavior($name);
} }
elseif (is_array($this->_b)) { elseif (is_array($this->_b)) { // behavior property
foreach ($this->_b as $object) { foreach ($this->_b as $object) {
if ($object->getEnabled()) { if ($object->getEnabled()) {
if (property_exists($object, $name)) { if (property_exists($object, $name)) {
...@@ -308,6 +310,46 @@ class Component ...@@ -308,6 +310,46 @@ class Component
} }
/** /**
* Initializes this component.
* This method is invoked by [[\Yii::createComponent]] after its creates the new
* component instance and initializes the component properties. In other words,
* at this stage, the component has been fully configured.
*
* The default implementation calls [[behaviors]] and registers any available behaviors.
* You may override this method with additional initialization logic (e.g. establish DB connection).
* Make sure you call the parent implementation.
*/
public function init()
{
$this->attachBehaviors($this->behaviors());
}
/**
* Returns a list of behaviors that this component should behave as.
* The return value should be an array of behavior configurations indexed by
* behavior names. Each behavior configuration can be either a string specifying
* the behavior class or an array of the following structure:
*
* ~~~
* 'behaviorName' => array(
* 'class' => 'BehaviorClass',
* 'property1' => 'value1',
* 'property2' => 'value2',
* )
* ~~~
*
* Note that the behavior classes must extend from [[Behavior]]. Behaviors declared
* in this method will be attached to the model when [[init]] is invoked.
*
* @return array the behavior configurations.
* @see init
*/
public function behaviors()
{
return array();
}
/**
* Returns a value indicating whether a property is defined. * Returns a value indicating whether a property is defined.
* A property is defined if there is a getter or setter method * A property is defined if there is a getter or setter method
* defined in the class. Note, property names are case-insensitive. * defined in the class. Note, property names are case-insensitive.
......
...@@ -42,8 +42,9 @@ class Event extends Component ...@@ -42,8 +42,9 @@ class Event extends Component
* Constructor. * Constructor.
* @param mixed $sender sender of the event * @param mixed $sender sender of the event
*/ */
public function __construct($sender=null) public function __construct($sender=null, $params=null)
{ {
$this->sender = $sender; $this->sender = $sender;
$this->params = $params;
} }
} }
...@@ -31,22 +31,10 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -31,22 +31,10 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
public function __construct($scenario='') public function __construct($scenario='')
{ {
$this->_scenario = $scenario; $this->_scenario = $scenario;
$this->init();
$this->attachBehaviors($this->behaviors());
$this->afterConstruct(); $this->afterConstruct();
} }
/** /**
* Initializes this model.
* This method is invoked in the constructor right after [[scenario]] is set.
* You may override this method to provide code that is needed to initialize the model (e.g. setting
* initial property values.)
*/
public function init()
{
}
/**
* Returns the list of attribute names. * Returns the list of attribute names.
* By default, this method returns all public non-static properties of the class. * By default, this method returns all public non-static properties of the class.
* You may override this method to change the default. * You may override this method to change the default.
...@@ -73,7 +61,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -73,7 +61,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
/** /**
* Returns the validation rules for attributes. * Returns the validation rules for attributes.
* *
* Validation rules are used by [[validate()]] to check if attribute values are valid. * Validation rules are used by [[validate]] to check if attribute values are valid.
* Child classes may override this method to declare different validation rules. * Child classes may override this method to declare different validation rules.
* *
* Each rule is an array with the following structure: * Each rule is an array with the following structure:
...@@ -131,32 +119,6 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -131,32 +119,6 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
} }
/** /**
* Returns a list of behaviors that this model should behave as.
* The return value should be an array of behavior configurations indexed by
* behavior names. Each behavior configuration can be either a string specifying
* the behavior class or an array of the following structure:
*
* ~~~
* 'behaviorName' => array(
* 'class' => 'BehaviorClass',
* 'property1' => 'value1',
* 'property2' => 'value2',
* )
* ~~~
*
* Note, the behavior classes must extend from [[Behavior]]. Behaviors declared
* in this method will be attached to the model when it is instantiated.
*
* For more details about behaviors, see [[Component]].
*
* @return array the behavior configurations.
*/
public function behaviors()
{
return array();
}
/**
* Returns the attribute labels. * Returns the attribute labels.
* *
* Attribute labels are mainly used for display purpose. For example, given an attribute * Attribute labels are mainly used for display purpose. For example, given an attribute
...@@ -215,8 +177,8 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -215,8 +177,8 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
} }
/** /**
* This method is invoked after a model instance is created by new operator. * This method is invoked at the end of model constructor.
* The default implementation raises the {@link onAfterConstruct} event. * The default implementation raises the [[onAfterConstruct]] event.
* You may override this method to do postprocessing after model creation. * You may override this method to do postprocessing after model creation.
* Make sure you call the parent implementation so that the event is raised properly. * Make sure you call the parent implementation so that the event is raised properly.
*/ */
...@@ -229,7 +191,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -229,7 +191,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
/** /**
* This method is invoked before validation starts. * This method is invoked before validation starts.
* The default implementation calls {@link onBeforeValidate} to raise an event. * The default implementation raises the [[onBeforeValidate]] event.
* You may override this method to do preliminary checks before validation. * You may override this method to do preliminary checks before validation.
* Make sure the parent implementation is invoked so that the event can be raised. * Make sure the parent implementation is invoked so that the event can be raised.
* @return boolean whether validation should be executed. Defaults to true. * @return boolean whether validation should be executed. Defaults to true.
...@@ -247,7 +209,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -247,7 +209,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
/** /**
* This method is invoked after validation ends. * This method is invoked after validation ends.
* The default implementation calls {@link onAfterValidate} to raise an event. * The default implementation raises the [[onAfterValidate]] event.
* You may override this method to do postprocessing after validation. * You may override this method to do postprocessing after validation.
* Make sure the parent implementation is invoked so that the event can be raised. * Make sure the parent implementation is invoked so that the event can be raised.
*/ */
...@@ -353,7 +315,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -353,7 +315,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
* Returns a value indicating whether the attribute is required. * Returns a value indicating whether the attribute is required.
* This is determined by checking if the attribute is associated with a * This is determined by checking if the attribute is associated with a
* [[\yii\validators\RequiredValidator|required]] validation rule in the * [[\yii\validators\RequiredValidator|required]] validation rule in the
* current {@link scenario}. * current [[scenario]].
* @param string $attribute attribute name * @param string $attribute attribute name
* @return boolean whether the attribute is required * @return boolean whether the attribute is required
*/ */
...@@ -601,7 +563,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess ...@@ -601,7 +563,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
/** /**
* Returns the attribute names that are safe to be massively assigned. * Returns the attribute names that are safe to be massively assigned.
* A safe attribute is one that is associated with a validation rule in the current {@link scenario}. * A safe attribute is one that is associated with a validation rule in the current [[scenario]].
* @return array safe attribute names * @return array safe attribute names
*/ */
public function getSafeAttributeNames() public function getSafeAttributeNames()
......
- add more doc to Model
- CompareValidator::clientValidateAttribute(): search for "CHtml::activeId" - CompareValidator::clientValidateAttribute(): search for "CHtml::activeId"
- FileValidator, UniqueValidator, ExistValidator, DateValidator: TBD - FileValidator, UniqueValidator, ExistValidator, DateValidator: TBD
- Can consider merging UniqueValidator and ExistValidator and using a NOT property. - Can consider merging UniqueValidator and ExistValidator and using a NOT property.
...@@ -9,3 +10,5 @@ ...@@ -9,3 +10,5 @@
* init * init
* ... * ...
* destruct * destruct
- get/setFlash() should be moved to session component
- support optional parameter in URL patterns
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment