TÌM HIỂU VỀ MODEL TRONG YII FRAMEWORK

1. Giới thiệu

Yii được phát âm là Yee hoặc [ji:], Yii là viết tắt của “Yes It Is!”. Ý nghĩa của nó là “Is it fast? ... Is it secure? ... Is it professional? ... Is it right for my next project? ... Yes, it is!”

Yii hoàn toàn miễn phí, là ứng dụng Web mã nguồn mở được phát triển bằng ngôn ngữ PHP5. Yii giúp cho việc phát triển ứng dụng Web tuân theo một khuôn khổ nhằm đảm bảo tính hiệu quả, tính mở rộng, và tính bảo trì của sản phẩm.

Tối ưu hiệu suất, Yii là sự lựa chọn hoàn hảo cho các dự án có quy mô. Yii cho phép nhà phát triển kiểm soát toàn bộ cấu hình. Yii cung cấp các công cụ giúp kiểm tra và sửa lỗi ứng dụng dễ dàng.

Yii kết hợp nhiều ý tưởng từ các framework và các ứng dựng Web nổi tiếng khác như Prado, Ruby on Rails, Joomla,.. Vì thế Yii cũng có cấu trúc MVC, và Model là phần rất quan trọng, nó có quan hệ mật thiết với cơ sở dữ liệu.

Yii có 2 loại model: form model là lớp (CFormModel) và active record model là lớp ( CActiveRecord ). Cả hai được mở rộng từ lớp ( CModel ). CFormModel đại diện cho mô hình dữ liệu do người dùng nhập vào ở dạng HTML. Sau đó lưu dữ liệu này vào bộ nhớ và thông qua CActiveRecord dữ liệu được lưu vào CSDL.

2. Model trong Yii Framework

2.1 CFormModel

CFormModel đại diện cho một mô hình dữ liệu thu thập được từ form inputs HTML, Các dữ liệu thu được chỉ lưu vào bộ nhớ tạm thời, để xác thực dữ liệu, tìm kiếm,... chứ không cần phải lưu vào database

2.1.1. Defining Model Class

class LoginForm extends CFormModel
{
  public $username;
  public $password;
  public $rememberMe=false;
}

Ba thuộc tính được khai báo trong LoginForm: $ username, $password và $ rememberMe. Chúng được sử dụng để giữ cho tên người dùng người dùng nhập vào và mật khẩu, và các tùy chọn xem người dùng muốn ghi nhớ thông tin đăng nhập của mình.

2.1.2. Declaring Validation Rules

class LoginForm extends CFormModel
{
    public $username;
    public $password;
    public $rememberMe=false;
    private$_identity;
    publicfunctionrules()
    {
        returnarray(
            array('username, password', 'required'),
            array('rememberMe', 'boolean'),
            array('password', 'authenticate'),
        );
    }
    publicfunctionauthenticate($attribute,$params)
    {
        $this->_identity=newUserIdentity($this->username,$this->password);
        if(!$this->_identity->authenticate())
        $this->addError(‘password’,’Incorrect username or password.);
    }
}

Đoạn mã trên chỉ rõ username và password là thuộc tính bắt buộc, rememberMe có kiểu boolean và password phải được xác thực.

Ví dụ một số validators được định nghĩa trước:

// 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'),

2.1.3 Create Action

public function actionLogin()
{
    $model = new LoginForm;
    if(isset($_POST['LoginForm']))
    {
        // collects user input data
        $model->attributes=$_POST['LoginForm'];
        // validates user input and redirect to previous page if validated
        if($model->validate())
            $this->redirect(Yii::app()->user->returnUrl);
    }
    // displays the login form
    $this->render('login',array('model'=>$model));
}

Ở trên, ta tạo ra một đối tượng LoginForm, nếu có yêu cầu POST , thì ta sẽ thu thu thập dữ liệu, rồi xác thực chúng trước khi chuyển hướng trình duyệt.

2.1.4 Create Form

Chúng ta sẽ dùng CHtml để tạo ra form đăng nhập:

<div class="form">
    <?php echo CHtml::beginForm(); ?>
    <?php echo CHtml::errorSummary($model); ?>

    <div class=”row”>
        <?php echo CHtml::activeLabel($model,’username’); ?>
        <?php echo CHtml::activeTextField($model,’username’)?>
    </div>

    <div class=”row”>
        <?php echo CHtml::activeLabel($model,’password’); ?>
        <?php echo CHtml::activePasswordField($model,’password’)?>
    </div>

    <div class=”row rememberMe”>
        <?php echo CHtml::activeCheckBox($model,’rememberMe’); ?>
        <?php echo CHtml::activeLabel($model,’rememberMe’); ?>
    </div>

    <div class=”row submit”>
        <?php echo CHtml::submitButton(‘Login’); ?>
    </div>

    <?php echo CHtml::endForm(); ?>
</div>

2.2 Active Record

ActiveRecord (AR) là một mô hình được sử dụng để truy cập cơ sở dữ liệu theo hướng đối tượng. Mỗi đối tượng AR trong Yii là một thể hiện của CActiveRecord là kết quả của 1 dòng dữ liệu của bảng được tạo trong CSDL.

2.2.1 Thiết lập kết nối DB

Tạo bảng (sử dụng Mysql)

CREATETABLE tbl_post(
    id INTEGERNOTNULLPRIMARYKEY AUTOINCREMENT,
    title VARCHAR(128) NOTNULL,
    contentTEXT NOTNULL,
    create_time INTEGERNOTNULL
);

Config database:

returnarray(
    'components'=>array(
        'db'=>array(
        'class'=>'system.db.CDbConnection',
        'connectionString'=>'mysql:path/to/dbfile',
        // turn on schema caching to improve performance
        // 'schemaCachingDuration'=>3600,
        ),
    ),
);

2.2.2 Defining AR Class

Mỗi lớp AR đại diện cho một bảng cơ sở dữ liệu duy nhất, và một đối tượng AR biểu diễn một dòng trong bảng đó. Theo mặc định tên của AR cũng chính là tên của bảng cơ sở dữ liệu:

class Post extends CActiveRecord
{
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

        publicfunctiontableName()
        {
            return‘tbl_post’;
        }
}

2.2.3 Creating Record

Để chèn một bản ghi mới vào bảng, ta tạo một đối tượng AR mới và thiết lập các thuộc tính, sau đó gọi phương thức save() :

$post = new Post;
$post->title='sample post';
$post->content='content for the sample post';
$post->create_time=time();
$post->save();

Nếu khóa chính của bảng là tự động tăng thì khi đối tượng AR được chèn vào bảng cơ sở dữ liệu khóa chính sẽ được tự động gia tăng, trong trường hợp này trường “id” sẽ tự động tăng.

Ngoài ra nếu muốn một trường có giá trị mặc định khi đối tượng AR được tạo ra, ta có thể định nghĩa như sau:


class Post extends CActiveRecord
{
    public $title='please enter a title';
    ......
}

$post= new Post;
echo $post->title;  // this would display: please enter a title

2.2.4. Reading Record

Để đọc dữ liệu từ một bảng cơ sở dữ liệu, ta gọi một trong những phương thức sau:


// find the first row satisfying the specified condition
$post=Post::model()->find($condition,$params);
// find the row with the specified primary key
$post=Post::model()->findByPk($postID,$condition,$params);
// find the row with the specified attribute values
$post=Post::model()->findByAttributes($attributes,$condition,$params);
// find the first row using the specified SQL statement
$post=Post::model()->findBySql($sql,$params);

Nếu các phương thức tìm thấy một hàng đáp ứng các điều kiện truy vấn, nó sẽ trả lại một đối tượng Post có giá trị tương ứng với các cột của một bảng ghi trong cơ sở dữ liệu.

Phương thức find sẽ trả về null nếu không tìm thấy bản ghi trong cơ sở dữ liệu tương ứng với diều kiện truy vấn nhất định.

Các đối số $condition, $params để xác định diều kiện truy vấn, ở đây $condition tương ứng với mệnh đề WHERE trong câu lệnh SQL và $param là một mảng các tham số có giá trị ràng buộc trong câu điều kiện $condition.

VD:

// find the row with postID=10
$post=Post::model()->find('postID=:postID', array(':postID'=>10))

Ngoài ra ta cũng có thể sử dụng đối tượng CDbCriteria, để thực hiện những cầu truy vấn phức tạp hơn:

$criteria= new CDbCriteria;
$criteria->select='title';  // only select the 'title' column
$criteria->condition='postID=:postID';
$criteria->params=array(':postID'=>10);
$post=Post::model()->find($criteria); // $params is not needed

Hoặc ta có thể viết lại một cách đơn giải hơn:


$post=Post::model()->find(array(
    'select'=>'title',
    'condition'=>'postID=:postID',
    'params'=>array(':postID'=>10),
));

Khi cơ sở dữ liệu có nhiều bản ghi phù hợp với điều kiện truy vấn, ta có thể lấy hết các bản ghi đó bằng cách dùng phương thức FindAll:


// find all rows satisfying the specified condition
$posts=Post::model()->findAll($condition,$params);
// find all rows with the specified primary keys
$posts=Post::model()->findAllByPk($postIDs,$condition,$params);
// find all rows with the specified attribute values
$posts=Post::model()->findAllByAttributes($attributes,$condition,$params);
// find all rows using the specified SQL statement
$posts=Post::model()->findAllBySql($sql,$params);

Khác với phương thức Find, phương thức FindAll sẽ trả về mảng rỗng khi không có bản ghi nào phù hợp thay vì NULL như Find.

Ngoài ra còn một số phương thức hữu hiệu khác:


// get the number of rows satisfying the specified condition
$n=Post::model()->count($condition,$params);
// get the number of rows using the specified SQL statement
$n=Post::model()->countBySql($sql,$params);
// check if there is at least a row satisfying the specified condition
$exists=Post::model()->exists($condition,$params);

2.2.5 Updating Record

Sau khi tìm được bản ghi thỏa mãm điều kiện mong muốn, ta có thể thiết lập lại các giá trị cột và gọi hàm Save() để cập nhập bản ghi:

$post=Post::model()->findByPk(10);
$post->title='new post title';
$post->save(); _// save the change to database_

Active Record cũng cung cấp cho ta các phương thức thuận tiện cho việc cập nhật nhiều bản ghi:

// update the rows matching the specified condition_
Post::model()->updateAll($attributes,$condition,$params);
// update the rows matching the specified condition and primary key(s)_
Post::model()->updateByPk($pk,$attributes,$condition,$params);
// update counter columns in the rows satisfying the specified conditions_
Post::model()->updateCounters($counters,$condition,$params);

2.2.6 Deleting Record

Để xóa một bản ghi trong cơ sở dữ liệu ta sẽ dùng phương thức delete():

$post=Post::model()->findByPk(10); // assuming there is a post whose ID is 10
$post->delete(); // delete the row from the database table

Ngoài ra còn một số phương thức hữu hiệu khác:

// delete the rows matching the specified condition_
Post::model()->deleteAll($condition,$params);
// delete the rows matching the specified condition and primary key(s)_
Post::model()->deleteByPk($pk,$condition,$params);

2.2.7 Data Validation

Khi chèn hoặc cập nhật bản ghi, ta cần phải kiểm tra các trường đã tuân thủ đúng quy tắc nhất định hay chưa. AR sẽ thực hiện việc xác nhận dữ liệu tự động khi ta gọi phương thức Save(), các quy tắc được thiết lập trong phương thức rules()

(Tham khảo trong phần trên: 2.1.2. Declaring Validation Rules)

if($post->save()) {
    // data is valid and is successfully inserted/updated
} else {
    // data is invalid. call getErrors() to retrieve error messages
}