Overview

Packages

  • application
    • commands
    • components
      • actions
      • filters
      • leftWidget
      • permissions
      • sortableWidget
      • util
      • webupdater
      • x2flow
        • actions
        • triggers
      • X2GridView
      • X2Settings
    • controllers
    • models
      • embedded
    • modules
      • accounts
        • controllers
        • models
      • actions
        • controllers
        • models
      • calendar
        • controllers
        • models
      • charts
        • models
      • contacts
        • controllers
        • models
      • docs
        • components
        • controllers
        • models
      • groups
        • controllers
        • models
      • marketing
        • components
        • controllers
        • models
      • media
        • controllers
        • models
      • mobile
        • components
      • opportunities
        • controllers
        • models
      • products
        • controllers
        • models
      • quotes
        • controllers
        • models
      • services
        • controllers
        • models
      • template
        • models
      • users
        • controllers
        • models
      • workflow
        • controllers
        • models
      • x2Leads
        • controllers
        • models
  • Net
  • None
  • PHP
  • system
    • base
    • caching
      • dependencies
    • collections
    • console
    • db
      • ar
      • schema
        • cubrid
        • mssql
        • mysql
        • oci
        • pgsql
        • sqlite
    • i18n
      • gettext
    • logging
    • test
    • utils
    • validators
    • web
      • actions
      • auth
      • filters
      • form
      • helpers
      • renderers
      • services
      • widgets
        • captcha
        • pagers
  • Text
    • Highlighter
  • zii
    • behaviors
    • widgets
      • grid
      • jui

Classes

  • BaseDocsMassAction
  • CApplication
  • CApplicationComponent
  • CBehavior
  • CComponent
  • CEnumerable
  • CErrorEvent
  • CErrorHandler
  • CEvent
  • CExceptionEvent
  • CModel
  • CModelBehavior
  • CModelEvent
  • CModule
  • CommonFieldsBehavior
  • CSecurityManager
  • CStatePersister
  • Expression
  • MassAction
  • MassAddToList
  • MassCompleteAction
  • MassMoveFileSysObjToFolder
  • MassRemoveFromList
  • MassRenameFileSysObj
  • MassUncompleteAction
  • MobileRecentItems
  • ModulePanelItem
  • NewListFromSelection
  • PanelItem
  • QuickCRUDBehavior
  • RecentItemPanelItem
  • ServiceRoutingBehavior
  • SettingsPanelItem
  • X2AddressBehavior
  • X2AuthCache
  • X2BaseListViewBehavior

Interfaces

  • IAction
  • IApplicationComponent
  • IAuthManager
  • IBehavior
  • IFilter
  • IStatePersister
  • IUserIdentity
  • IViewRenderer
  • IWebServiceProvider
  • IWebUser

Exceptions

  • CException
  • CHttpException
  • TwitterFeedWidgetException
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * CModel class file.
  4:  *
  5:  * @author Qiang Xue <qiang.xue@gmail.com>
  6:  * @link http://www.yiiframework.com/
  7:  * @copyright 2008-2013 Yii Software LLC
  8:  * @license http://www.yiiframework.com/license/
  9:  */
 10: 
 11: 
 12: /**
 13:  * CModel is the base class providing the common features needed by data model objects.
 14:  *
 15:  * CModel defines the basic framework for data models that need to be validated.
 16:  *
 17:  * @property CList $validatorList All the validators declared in the model.
 18:  * @property array $validators The validators applicable to the current {@link scenario}.
 19:  * @property array $errors Errors for all attributes or the specified attribute. Empty array is returned if no error.
 20:  * @property array $attributes Attribute values (name=>value).
 21:  * @property string $scenario The scenario that this model is in.
 22:  * @property array $safeAttributeNames Safe attribute names.
 23:  * @property CMapIterator $iterator An iterator for traversing the items in the list.
 24:  *
 25:  * @author Qiang Xue <qiang.xue@gmail.com>
 26:  * @package system.base
 27:  * @since 1.0
 28:  */
 29: abstract class CModel extends CComponent implements IteratorAggregate, ArrayAccess
 30: {
 31:     private $_errors=array();   // attribute name => array of errors
 32:     private $_validators;       // validators
 33:     private $_scenario='';      // scenario
 34: 
 35:     /**
 36:      * Returns the list of attribute names of the model.
 37:      * @return array list of attribute names.
 38:      */
 39:     abstract public function attributeNames();
 40: 
 41:     /**
 42:      * Returns the validation rules for attributes.
 43:      *
 44:      * This method should be overridden to declare validation rules.
 45:      * Each rule is an array with the following structure:
 46:      * <pre>
 47:      * array('attribute list', 'validator name', 'on'=>'scenario name', ...validation parameters...)
 48:      * </pre>
 49:      * where
 50:      * <ul>
 51:      * <li>attribute list: specifies the attributes (separated by commas) to be validated;</li>
 52:      * <li>validator name: specifies the validator to be used. It can be the name of a model class
 53:      *   method, the name of a built-in validator, or a validator class (or its path alias).
 54:      *   A validation method must have the following signature:
 55:      * <pre>
 56:      * // $params refers to validation parameters given in the rule
 57:      * function validatorName($attribute,$params)
 58:      * </pre>
 59:      *   A built-in validator refers to one of the validators declared in {@link CValidator::builtInValidators}.
 60:      *   And a validator class is a class extending {@link CValidator}.</li>
 61:      * <li>on: this specifies the scenarios when the validation rule should be performed.
 62:      *   Separate different scenarios with commas. If this option is not set, the rule
 63:      *   will be applied in any scenario that is not listed in "except". Please see {@link scenario} for more details about this option.</li>
 64:      * <li>except: this specifies the scenarios when the validation rule should not be performed.
 65:      *   Separate different scenarios with commas. Please see {@link scenario} for more details about this option.</li>
 66:      * <li>additional parameters are used to initialize the corresponding validator properties.
 67:      *   Please refer to individual validator class API for possible properties.</li>
 68:      * </ul>
 69:      *
 70:      * The following are some examples:
 71:      * <pre>
 72:      * array(
 73:      *     array('username', 'required'),
 74:      *     array('username', 'length', 'min'=>3, 'max'=>12),
 75:      *     array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'),
 76:      *     array('password', 'authenticate', 'on'=>'login'),
 77:      * );
 78:      * </pre>
 79:      *
 80:      * Note, in order to inherit rules defined in the parent class, a child class needs to
 81:      * merge the parent rules with child rules using functions like array_merge().
 82:      *
 83:      * @return array validation rules to be applied when {@link validate()} is called.
 84:      * @see scenario
 85:      */
 86:     public function rules()
 87:     {
 88:         return array();
 89:     }
 90: 
 91:     /**
 92:      * Returns a list of behaviors that this model should behave as.
 93:      * The return value should be an array of behavior configurations indexed by
 94:      * behavior names. Each behavior configuration can be either a string specifying
 95:      * the behavior class or an array of the following structure:
 96:      * <pre>
 97:      * 'behaviorName'=>array(
 98:      *     'class'=>'path.to.BehaviorClass',
 99:      *     'property1'=>'value1',
100:      *     'property2'=>'value2',
101:      * )
102:      * </pre>
103:      *
104:      * Note, the behavior classes must implement {@link IBehavior} or extend from
105:      * {@link CBehavior}. Behaviors declared in this method will be attached
106:      * to the model when it is instantiated.
107:      *
108:      * For more details about behaviors, see {@link CComponent}.
109:      * @return array the behavior configurations (behavior name=>behavior configuration)
110:      */
111:     public function behaviors()
112:     {
113:         return array();
114:     }
115: 
116:     /**
117:      * Returns the attribute labels.
118:      * Attribute labels are mainly used in error messages of validation.
119:      * By default an attribute label is generated using {@link generateAttributeLabel}.
120:      * This method allows you to explicitly specify attribute labels.
121:      *
122:      * Note, in order to inherit labels defined in the parent class, a child class needs to
123:      * merge the parent labels with child labels using functions like array_merge().
124:      *
125:      * @return array attribute labels (name=>label)
126:      * @see generateAttributeLabel
127:      */
128:     public function attributeLabels()
129:     {
130:         return array();
131:     }
132: 
133:     /**
134:      * Performs the validation.
135:      *
136:      * This method executes the validation rules as declared in {@link rules}.
137:      * Only the rules applicable to the current {@link scenario} will be executed.
138:      * A rule is considered applicable to a scenario if its 'on' option is not set
139:      * or contains the scenario.
140:      *
141:      * Errors found during the validation can be retrieved via {@link getErrors}.
142:      *
143:      * @param array $attributes list of attributes that should be validated. Defaults to null,
144:      * meaning any attribute listed in the applicable validation rules should be
145:      * validated. If this parameter is given as a list of attributes, only
146:      * the listed attributes will be validated.
147:      * @param boolean $clearErrors whether to call {@link clearErrors} before performing validation
148:      * @return boolean whether the validation is successful without any error.
149:      * @see beforeValidate
150:      * @see afterValidate
151:      */
152:     public function validate($attributes=null, $clearErrors=true)
153:     {
154:         if($clearErrors)
155:             $this->clearErrors();
156:         if($this->beforeValidate())
157:         {
158:             foreach($this->getValidators() as $validator)
159:                 $validator->validate($this,$attributes);
160:             $this->afterValidate();
161:             return !$this->hasErrors();
162:         }
163:         else
164:             return false;
165:     }
166: 
167:     /**
168:      * This method is invoked after a model instance is created by new operator.
169:      * The default implementation raises the {@link onAfterConstruct} event.
170:      * You may override this method to do postprocessing after model creation.
171:      * Make sure you call the parent implementation so that the event is raised properly.
172:      */
173:     protected function afterConstruct()
174:     {
175:         if($this->hasEventHandler('onAfterConstruct'))
176:             $this->onAfterConstruct(new CEvent($this));
177:     }
178: 
179:     /**
180:      * This method is invoked before validation starts.
181:      * The default implementation calls {@link onBeforeValidate} to raise an event.
182:      * You may override this method to do preliminary checks before validation.
183:      * Make sure the parent implementation is invoked so that the event can be raised.
184:      * @return boolean whether validation should be executed. Defaults to true.
185:      * If false is returned, the validation will stop and the model is considered invalid.
186:      */
187:     protected function beforeValidate()
188:     {
189:         $event=new CModelEvent($this);
190:         $this->onBeforeValidate($event);
191:         return $event->isValid;
192:     }
193: 
194:     /**
195:      * This method is invoked after validation ends.
196:      * The default implementation calls {@link onAfterValidate} to raise an event.
197:      * You may override this method to do postprocessing after validation.
198:      * Make sure the parent implementation is invoked so that the event can be raised.
199:      */
200:     protected function afterValidate()
201:     {
202:         $this->onAfterValidate(new CEvent($this));
203:     }
204: 
205:     /**
206:      * This event is raised after the model instance is created by new operator.
207:      * @param CEvent $event the event parameter
208:      */
209:     public function onAfterConstruct($event)
210:     {
211:         $this->raiseEvent('onAfterConstruct',$event);
212:     }
213: 
214:     /**
215:      * This event is raised before the validation is performed.
216:      * @param CModelEvent $event the event parameter
217:      */
218:     public function onBeforeValidate($event)
219:     {
220:         $this->raiseEvent('onBeforeValidate',$event);
221:     }
222: 
223:     /**
224:      * This event is raised after the validation is performed.
225:      * @param CEvent $event the event parameter
226:      */
227:     public function onAfterValidate($event)
228:     {
229:         $this->raiseEvent('onAfterValidate',$event);
230:     }
231: 
232:     /**
233:      * Returns all the validators declared in the model.
234:      * This method differs from {@link getValidators} in that the latter
235:      * would only return the validators applicable to the current {@link scenario}.
236:      * Also, since this method return a {@link CList} object, you may
237:      * manipulate it by inserting or removing validators (useful in behaviors).
238:      * For example, <code>$model->validatorList->add($newValidator)</code>.
239:      * The change made to the {@link CList} object will persist and reflect
240:      * in the result of the next call of {@link getValidators}.
241:      * @return CList all the validators declared in the model.
242:      * @since 1.1.2
243:      */
244:     public function getValidatorList()
245:     {
246:         if($this->_validators===null)
247:             $this->_validators=$this->createValidators();
248:         return $this->_validators;
249:     }
250: 
251:     /**
252:      * Returns the validators applicable to the current {@link scenario}.
253:      * @param string $attribute the name of the attribute whose validators should be returned.
254:      * If this is null, the validators for ALL attributes in the model will be returned.
255:      * @return array the validators applicable to the current {@link scenario}.
256:      */
257:     public function getValidators($attribute=null)
258:     {
259:         if($this->_validators===null)
260:             $this->_validators=$this->createValidators();
261: 
262:         $validators=array();
263:         $scenario=$this->getScenario();
264:         foreach($this->_validators as $validator)
265:         {
266:             if($validator->applyTo($scenario))
267:             {
268:                 if($attribute===null || in_array($attribute,$validator->attributes,true))
269:                     $validators[]=$validator;
270:             }
271:         }
272:         return $validators;
273:     }
274: 
275:     /**
276:      * Creates validator objects based on the specification in {@link rules}.
277:      * This method is mainly used internally.
278:      * @throws CException if current class has an invalid validation rule
279:      * @return CList validators built based on {@link rules()}.
280:      */
281:     public function createValidators()
282:     {
283:         $validators=new CList;
284:         foreach($this->rules() as $rule)
285:         {
286:             if(isset($rule[0],$rule[1]))  // attributes, validator name
287:                 $validators->add(CValidator::createValidator($rule[1],$this,$rule[0],array_slice($rule,2)));
288:             else
289:                 throw new CException(Yii::t('yii','{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.',
290:                     array('{class}'=>get_class($this))));
291:         }
292:         return $validators;
293:     }
294: 
295:     /**
296:      * Returns a value indicating whether the attribute is required.
297:      * This is determined by checking if the attribute is associated with a
298:      * {@link CRequiredValidator} validation rule in the current {@link scenario}.
299:      * @param string $attribute attribute name
300:      * @return boolean whether the attribute is required
301:      */
302:     public function isAttributeRequired($attribute)
303:     {
304:         foreach($this->getValidators($attribute) as $validator)
305:         {
306:             if($validator instanceof CRequiredValidator)
307:                 return true;
308:         }
309:         return false;
310:     }
311: 
312:     /**
313:      * Returns a value indicating whether the attribute is safe for massive assignments.
314:      * @param string $attribute attribute name
315:      * @return boolean whether the attribute is safe for massive assignments
316:      * @since 1.1
317:      */
318:     public function isAttributeSafe($attribute)
319:     {
320:         $attributes=$this->getSafeAttributeNames();
321:         return in_array($attribute,$attributes);
322:     }
323: 
324:     /**
325:      * Returns the text label for the specified attribute.
326:      * @param string $attribute the attribute name
327:      * @return string the attribute label
328:      * @see generateAttributeLabel
329:      * @see attributeLabels
330:      */
331:     public function getAttributeLabel($attribute)
332:     {
333:         $labels=$this->attributeLabels();
334:         if(isset($labels[$attribute]))
335:             return $labels[$attribute];
336:         else
337:             return $this->generateAttributeLabel($attribute);
338:     }
339: 
340:     /**
341:      * Returns a value indicating whether there is any validation error.
342:      * @param string $attribute attribute name. Use null to check all attributes.
343:      * @return boolean whether there is any error.
344:      */
345:     public function hasErrors($attribute=null)
346:     {
347:         if($attribute===null)
348:             return $this->_errors!==array();
349:         else
350:             return isset($this->_errors[$attribute]);
351:     }
352: 
353:     /**
354:      * Returns the errors for all attribute or a single attribute.
355:      * @param string $attribute attribute name. Use null to retrieve errors for all attributes.
356:      * @return array errors for all attributes or the specified attribute. Empty array is returned if no error.
357:      */
358:     public function getErrors($attribute=null)
359:     {
360:         if($attribute===null)
361:             return $this->_errors;
362:         else
363:             return isset($this->_errors[$attribute]) ? $this->_errors[$attribute] : array();
364:     }
365: 
366:     /**
367:      * Returns the first error of the specified attribute.
368:      * @param string $attribute attribute name.
369:      * @return string the error message. Null is returned if no error.
370:      */
371:     public function getError($attribute)
372:     {
373:         return isset($this->_errors[$attribute]) ? reset($this->_errors[$attribute]) : null;
374:     }
375: 
376:     /**
377:      * Adds a new error to the specified attribute.
378:      * @param string $attribute attribute name
379:      * @param string $error new error message
380:      */
381:     public function addError($attribute,$error)
382:     {
383:         $this->_errors[$attribute][]=$error;
384:     }
385: 
386:     /**
387:      * Adds a list of errors.
388:      * @param array $errors a list of errors. The array keys must be attribute names.
389:      * The array values should be error messages. If an attribute has multiple errors,
390:      * these errors must be given in terms of an array.
391:      * You may use the result of {@link getErrors} as the value for this parameter.
392:      */
393:     public function addErrors($errors)
394:     {
395:         foreach($errors as $attribute=>$error)
396:         {
397:             if(is_array($error))
398:             {
399:                 foreach($error as $e)
400:                     $this->addError($attribute, $e);
401:             }
402:             else
403:                 $this->addError($attribute, $error);
404:         }
405:     }
406: 
407:     /**
408:      * Removes errors for all attributes or a single attribute.
409:      * @param string $attribute attribute name. Use null to remove errors for all attribute.
410:      */
411:     public function clearErrors($attribute=null)
412:     {
413:         if($attribute===null)
414:             $this->_errors=array();
415:         else
416:             unset($this->_errors[$attribute]);
417:     }
418: 
419:     /**
420:      * Generates a user friendly attribute label.
421:      * This is done by replacing underscores or dashes with blanks and
422:      * changing the first letter of each word to upper case.
423:      * For example, 'department_name' or 'DepartmentName' becomes 'Department Name'.
424:      * @param string $name the column name
425:      * @return string the attribute label
426:      */
427:     public function generateAttributeLabel($name)
428:     {
429:         return ucwords(trim(strtolower(str_replace(array('-','_','.'),' ',preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $name)))));
430:     }
431: 
432:     /**
433:      * Returns all attribute values.
434:      * @param array $names list of attributes whose value needs to be returned.
435:      * Defaults to null, meaning all attributes as listed in {@link attributeNames} will be returned.
436:      * If it is an array, only the attributes in the array will be returned.
437:      * @return array attribute values (name=>value).
438:      */
439:     public function getAttributes($names=null)
440:     {
441:         $values=array();
442:         foreach($this->attributeNames() as $name)
443:             $values[$name]=$this->$name;
444: 
445:         if(is_array($names))
446:         {
447:             $values2=array();
448:             foreach($names as $name)
449:                 $values2[$name]=isset($values[$name]) ? $values[$name] : null;
450:             return $values2;
451:         }
452:         else
453:             return $values;
454:     }
455: 
456:     /**
457:      * Sets the attribute values in a massive way.
458:      * @param array $values attribute values (name=>value) to be set.
459:      * @param boolean $safeOnly whether the assignments should only be done to the safe attributes.
460:      * A safe attribute is one that is associated with a validation rule in the current {@link scenario}.
461:      * @see getSafeAttributeNames
462:      * @see attributeNames
463:      */
464:     public function setAttributes($values,$safeOnly=true)
465:     {
466:         if(!is_array($values))
467:             return;
468:         $attributes=array_flip($safeOnly ? $this->getSafeAttributeNames() : $this->attributeNames());
469:         foreach($values as $name=>$value)
470:         {
471:             if(isset($attributes[$name]))
472:                 $this->$name=$value;
473:             elseif($safeOnly)
474:                 $this->onUnsafeAttribute($name,$value);
475:         }
476:     }
477: 
478:     /**
479:      * Sets the attributes to be null.
480:      * @param array $names list of attributes to be set null. If this parameter is not given,
481:      * all attributes as specified by {@link attributeNames} will have their values unset.
482:      * @since 1.1.3
483:      */
484:     public function unsetAttributes($names=null)
485:     {
486:         if($names===null)
487:             $names=$this->attributeNames();
488:         foreach($names as $name)
489:             $this->$name=null;
490:     }
491: 
492:     /**
493:      * This method is invoked when an unsafe attribute is being massively assigned.
494:      * The default implementation will log a warning message if YII_DEBUG is on.
495:      * It does nothing otherwise.
496:      * @param string $name the unsafe attribute name
497:      * @param mixed $value the attribute value
498:      * @since 1.1.1
499:      */
500:     public function onUnsafeAttribute($name,$value)
501:     {
502:         if(YII_DEBUG)
503:             Yii::log(Yii::t('yii','Failed to set unsafe attribute "{attribute}" of "{class}".',array('{attribute}'=>$name, '{class}'=>get_class($this))),CLogger::LEVEL_WARNING);
504:     }
505: 
506:     /**
507:      * Returns the scenario that this model is used in.
508:      *
509:      * Scenario affects how validation is performed and which attributes can
510:      * be massively assigned.
511:      *
512:      * A validation rule will be performed when calling {@link validate()}
513:      * if its 'except' value does not contain current scenario value while
514:      * 'on' option is not set or contains the current scenario value.
515:      *
516:      * And an attribute can be massively assigned if it is associated with
517:      * a validation rule for the current scenario. Note that an exception is
518:      * the {@link CUnsafeValidator unsafe} validator which marks the associated
519:      * attributes as unsafe and not allowed to be massively assigned.
520:      *
521:      * @return string the scenario that this model is in.
522:      */
523:     public function getScenario()
524:     {
525:         return $this->_scenario;
526:     }
527: 
528:     /**
529:      * Sets the scenario for the model.
530:      * @param string $value the scenario that this model is in.
531:      * @see getScenario
532:      */
533:     public function setScenario($value)
534:     {
535:         $this->_scenario=$value;
536:     }
537: 
538:     /**
539:      * Returns the attribute names that are safe to be massively assigned.
540:      * A safe attribute is one that is associated with a validation rule in the current {@link scenario}.
541:      * @return array safe attribute names
542:      */
543:     public function getSafeAttributeNames()
544:     {
545:         $attributes=array();
546:         $unsafe=array();
547:         foreach($this->getValidators() as $validator)
548:         {
549:             if(!$validator->safe)
550:             {
551:                 foreach($validator->attributes as $name)
552:                     $unsafe[]=$name;
553:             }
554:             else
555:             {
556:                 foreach($validator->attributes as $name)
557:                     $attributes[$name]=true;
558:             }
559:         }
560: 
561:         foreach($unsafe as $name)
562:             unset($attributes[$name]);
563:         return array_keys($attributes);
564:     }
565: 
566:     /**
567:      * Returns an iterator for traversing the attributes in the model.
568:      * This method is required by the interface IteratorAggregate.
569:      * @return CMapIterator an iterator for traversing the items in the list.
570:      */
571:     public function getIterator()
572:     {
573:         $attributes=$this->getAttributes();
574:         return new CMapIterator($attributes);
575:     }
576: 
577:     /**
578:      * Returns whether there is an element at the specified offset.
579:      * This method is required by the interface ArrayAccess.
580:      * @param mixed $offset the offset to check on
581:      * @return boolean
582:      */
583:     public function offsetExists($offset)
584:     {
585:         return property_exists($this,$offset);
586:     }
587: 
588:     /**
589:      * Returns the element at the specified offset.
590:      * This method is required by the interface ArrayAccess.
591:      * @param integer $offset the offset to retrieve element.
592:      * @return mixed the element at the offset, null if no element is found at the offset
593:      */
594:     public function offsetGet($offset)
595:     {
596:         return $this->$offset;
597:     }
598: 
599:     /**
600:      * Sets the element at the specified offset.
601:      * This method is required by the interface ArrayAccess.
602:      * @param integer $offset the offset to set element
603:      * @param mixed $item the element value
604:      */
605:     public function offsetSet($offset,$item)
606:     {
607:         $this->$offset=$item;
608:     }
609: 
610:     /**
611:      * Unsets the element at the specified offset.
612:      * This method is required by the interface ArrayAccess.
613:      * @param mixed $offset the offset to unset element
614:      */
615:     public function offsetUnset($offset)
616:     {
617:         unset($this->$offset);
618:     }
619: }
620: 
API documentation generated by ApiGen 2.8.0