Saturday, April 20, 2013

Yii create a new model with common attributes

The rules() method, like most of the Yii methods, returns an array of data:
public function rules()
{
    return array(/* actual rules */);
}
The first, most obvious, restriction is to indicate that a field is required. Just use a comma-separated string of field names as the first returned value and the word required as the second:
array('name, email, subject, body', 'required'),
You can also specify that a value must be a number or, more specifically, an integer. This syntax is slightly different. Here, I indicate that the ext field must be an integer:
array('ext', 'numerical', 'integerOnly'=>true),
For strings, you can restrict the length to a maximum value:
array('name','length','max'=>40),
Or a minimum value:
array('name','length','min'=>6),
Or both:
array('name','length','min'=>6, 'max'=>40),
Another useful validation routine is to check that a string is an email address. I do that here, to a userEmail field:
array('userEmail', 'email'),
To indicate that a string needs to be a URL, use:
array('link', 'url'),
Another useful rule is for comparisons, like when a user registers and you have to make sure that the confirmed password matches the password:
array('password1', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'),
There is also the “safe” rule. This rule is used to provide access to data that isn’t otherwise validated. For example, an email address is already considered to be “safe” because it must abide by the email rule, but the Employee Model has the leaveDate field which won’t have any rules applied to it (in part, because there are no date-specific rules and also because the field can be null). To be able to refer to that value, it must be declared as safe:
array('leaveDate', 'safe'),
If there are multiple fields to make safe, just separate them with commas.
There’s also a rule to indicate which fields should be safe to search on. By default, every rule is made safe in a search, but you may want to change that behavior by removing fields from the list:
array('id, departmentId, firstName, lastName, email, ext, hireDate, leaveDate', 'safe', 'on'=>'search'),
So, using this information, the complete rules() method for my Employee Model is:
public function rules()
{
    return array(
        array('departmentId, firstName, lastName, email, hireDate', 'required'),
        array('departmentId, ext', 'numerical', 'integerOnly'=>true),
        array('firstName', 'length', 'max'=>20),
        array('lastName', 'length', 'max'=>40),
        array('email', 'length', 'max'=>60),
        array('email', 'email'),
        array('leaveDate', 'safe'),
        array('id, departmentId, firstName, lastName, email, ext, hireDate, leaveDate', 'safe', 'on'=>'search'),
 );
}
Moving on, another key Model method is relations(), which indicates the relationship between Models. If your database is designed properly, this method will already be properly filled out, again thanks to Gii. Here’s how the relations() method in the Employee Model looks:
public function relations()
{
    return array( 
        'department' => array(self::BELONGS_TO, 'Department', 'departmentId'
    );
}
The relation is given a name, here department. The relation indicates that the departmentId column in the Employee Model (i.e., this one) belongs to the Department Model. Here’s how this will come into play: When loading the information for an employee, you can also load any of its relations. By doing so, references to department will equate to the Department Model record that is the employee’s department. So if the $model object represents the Employee being viewed, then $model->department->name would be the name of the department that the employee is associated with.
In the Department Model, this relation is defined:
public function relations()
{
    return array('employees' => array(self::HAS_MANY, 'Employee', 'departmentId') );
}
So if $model represents a specific Department being viewed, then $model->employees is an array of Employee objects, each of which representing one Employee in that department.
The relations between Models is a key player in complex MVC sites. Through properly defined relations, associated content can be retrieved. You’ll learn more about this in the next couple of posts.
Moving on, a more trivial, but still nice, method is attributeLabels(). This method returns an associative array of fields and the labels to use for those fields in forms, error messages, and so forth. The Yii framework does a great job of making these conversations automatically, like firstName becoming First Name and departmentId becoming just Department. But you may want to still customize these. For the Employee Model, here’s what I have:
public function attributeLabels()
{
    return array(
        'id' => 'Employee ID',
        'departmentId' => 'Department',
        'firstName' => 'First Name',
        'lastName' => 'Last Name',
        'email' => 'Email',
        'ext' => 'Ext',
        'hireDate' => 'Hire Date',
        'leaveDate' => 'Leave Date',
    );
}

Complete Example


<?php
class PasswordReset extends CActiveRecord {
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
    public function tableName()
    {
        return 'password_reset';
    }
    public function rules()
    {
        return array(
            array('user_user_id, request_time, request_hash, request_done', 'required'),
            array('user_user_id, request_time, request_done', 'numerical'),
            array('request_done','length','min'=>6, 'max'=>1),
            array('request_time','length','min'=>6, 'max'=>10),
            array('request_hash','length','max'=>100),
            array('user_user_id, request_time, request_hash, request_done', 'safe', 'on'=>'search')
        );
    }
    public function relations()
    {
        return array(
            'User' => array(self::BELONGS_TO, 'User', 'user_user_id')
        );
    }
    public function attributeLabels()
    {
        return array(
            'request_time' => 'Request Time',
            'request_hash' => 'Request Hash',
            'request_done' => 'Request Done'	
        );
    }
    public function search()
    {
        $criteria=new CDbCriteria;

        $criteria->compare('request_time', $this->request_time, true);
        $criteria->compare('request_hash', $this->request_hash, true);
        $criteria->compare('request_done', $this->request_done, true);
        $criteria->compare('User.id', $this->User->id);
        $criteria->compare('request_done', '0', true);

        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria
        ));
    }
    public function findByParameter($fieldname, $fieldvalue)
    {
        $criteria=new CDbCriteria;
        $criteria->compare($fieldname, $fieldvalue, true);		
        return new CActiveDataProvider($this, array(
            'criteria' => $criteria
        ));
    }
    public function findByParameters($parameters)
    {
        $criteria=new CDbCriteria;
        foreach ($parameters as $key => $value) {
            $criteria->compare($key, $value, true);
        }                
        return new CActiveDataProvider($this, array(
            'criteria' => $criteria,
        ));
    }
    public function getRequestList() {
        $parameters = array('request_done' => '0');
        $requests = PasswordReset::model()->findByParameters($parameters);
        return CHtml::listData($requests->getData(), 'password_reset_id', 'request_hash');
    }
}
?>

No comments:

Post a Comment