Yii Framework

Yii Framework

Giới thiệu về module trong Yii Framework

Module trong Yii có thể xem như một application thu nhỏ, bao gồm models, views, controller và các components tương tự như một application cơ bản được sinh ra bởi yiic. Module lớn có thể được triển khai độc lập như một application, hay kết hợp nhiều module với nhau xây dựng thành một application hoàn chỉnh.

 

Module rất hữu ích khi phát triển ứng dụng, giúp ta chia nhỏ ứng dụng thành các phần nhỏ hơn để dễ dàng phát triển và bảo trì. Những tính năng thường được sử dụng như quản lý người dùng, quản lý bình luận… có thể phát triển thành các module để dễ dàng tái sử dụng trong các dự án sau này.

 

Cấu trúc thư mục của module tương tự như cấu trúc thư mục của application. Tuy nhiên trong cấu trúc module mà tôi đang dùng sẽ có thêm một vài thành phần khác phục vụ cho nhu cầu của cá nhân tôi.

 

Đây là cấu trúc được trích ra từ module store (nó là trang ebook trên blog này)

store
-- assets
-- -- css
-- -- img
-- -- js
-- components
-- config
-- -- routes.php
-- controllers
-- -- backend
-- -- -- DefaultController.php
-- -- -- ItemController.php
-- -- frontend
-- -- -- AjaxController.php
-- -- -- ItemController.php
-- messages
-- -- vi
-- -- -- default
-- models
-- views
-- -- backend
-- -- -- default
-- -- -- -- admin.php
-- -- -- item
-- -- -- -- admin.php
-- -- -- -- create.php
-- -- -- -- update.php
-- -- frontend
-- -- -- ajax
-- -- -- -- comment.php
-- -- -- item
-- -- -- -- index.php
-- -- -- -- view.php
-- -- layouts
-- -- menu.php
-- StoreModule.php

 

- assets: được thêm nhằm mục đích lưu trữ các tập tin hình ảnh, css, js chỉ sử dụng riêng cho module này
- components: chứa các widget được viết cho module. Có thể gọi từ layout, module khác thông qua path alias
- config: chứa tất cả các thông tin cấu hình cho module. Hiện tại nó chỉ chứa file routes.php chứa các rule cho mục đích rewrite url
- controllers: Tôi tách biệt các controller trong mỗi module thành 2 nhóm: một cho frontend và một cho backend. Các controller được xử lý từ 1 file bootstrap index.php duy nhất. Chính vì thế sẽ cần đến các rule trong file routes.php để giúp yii biết chúng ta muốn gọi đến controller nào.
- messages: chứa các file ngôn ngữ khác nhau cho từng module
- models: không cần giải thích gì, chúng được chia sẽ trong nội bộ module hoặc có thể import qua path alias khi gọi từ module khác.
- views: cũng tách biệt giữa frontend và backend theo controller
- StoreModule.php Mỗi một module mặc định được sinh ra bởi gii đều được extends từ CWebModule. Nó chứa các attribute và các method được dùng chung trong module.

 

Tuy nhiên để tiện sử dụng và tùy biến sau này, tôi tạo thêm một class WebModule đặt trong protected/components extends từ CWebModule và tất cả các module tôi tạo thêm được extends từ class này. Bạn có thể xem class này bên dưới.

 

Để sử dụng module, đầu tiên chúng ta đặt module vào đúng thư mục modules của ứng dụng trong protected/modules. Sau đó khai báo module ID trong file cấu hình ứng dụng protected/config/main.php

return array(
    ......
    'modules' => array(
        'store'
    ),
    ......
);

 

Khi cấu hình module, chúng ta có thể cấu hình luôn giá trị mặc định của các tham số trong module, tương tự như tham số của các components. Ví dụ trong module có thuộc tính pageSizeBack trong class module, ta có thể câu hình như sau:

return array(
    ......
    'modules' => array(
        'store' => array(
            'pageSizeBack' => 20,
            'pageSizeFront' => 10,
        ),
    ),
    ......
);

 

Bạn có thể truy cập attribute trên bằng cách:

Yii::app()->getModule('moduleName')->pageSizeBack
// or
Yii::app()->controller->module->pageSizeBack

 

Người dùng có thể truy cập đến controller của module giống như controller bình thường. Chúng ta truy cập đến action trong module như sau moduleID/controllerID/actionID
Ví dụ: module store có controller tên ItemController chúng ta có thể sử dụng route store/item/index để tham chiếu tới action index trong controller này. URL tương ứng cho tuyến đường này sẽ là http://example.com/store/item/index

 

Các module có thể được lồng vào nhau không giới hạn cấp độ. Tuy nhiên tôi chưa test trường hợp này!

 

Mặc định khi truy cập module mà không chỉ định rõ controller nào thì hệ thống sẽ gọi DefaultController của module. Để thay đỗi controller mặc định ta khai báo như sau:

class StoreModule extends WebModule {
    //goes to ItemController instead of DefaultController
    public $defaultController = 'Item';
    ...
}

 

Đây là class WebModule của tôi. Còn tùy biến thế nào phụ thuộc vào yêu cầu trong dự án của bạn :D

// protected/components/WebModule.php
class WebModule extends CWebModule {

    public $appId = 0;
    public $appName = 'root';
    public $appTheme = 'default';
    public $appKeyword;
    public $appDescription;
    public $ajaxFull;
    private $_assets;

    public function getAssets() {
        if ($this->_assets === null)
            $this->_assets = Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias("$this->name.assets"));
        return $this->_assets;
    }

    public function beforeControllerAction($controller, $action) {
        if (parent::beforeControllerAction($controller, $action)) {
            $this->ajaxFull = (isset($_GET['ajax'])) ? 1 : 0;

            $request = strtolower(Yii::app()->request->getQuery('appName'));
            $appName = ($request == null) ? $this->appName : $request;

            $connection = Yii::app()->db;
            $sql = 'SELECT id, name, theme, keyword, description FROM {{app}} WHERE status=1 AND name=:name';
            $command = $connection->createCommand($sql);
            $command->bindParam(':name', $appName, PDO:: PARAM_STR);
            $row = $command->queryRow();

            if (!empty($row)) {
                $this->appId = $row['id'];
                $this->appName = $row['name'];
                $this->appTheme = $row['theme'];
                $this->appKeyword = $row['keyword'];
                $this->appDescription = $row['description'];
            }

            if (strstr($controller->id, '/', true) == 'backend') {
                Yii::app()->theme = (Yii::app()->user->checkAccess('admin')) ? 'admin' : 'login';
                $controller->widget('common.ext.jquery.Ajax');
            } else {
                // fix theme exist
                Yii::app()->theme = $this->appTheme;
                if (Yii::app()->theme == null)
                    Yii::app()->theme = Yii::app()->params['themeDefault'];
            }

            return true;
        }
        else
            return false;
    }
}

Bài đăng khác

HỖ TRỢ TRỰC TUYẾN

Mr. Lĩnh

0939.898.458

linhnp@panda.com.vn

Mr. Lai

0939.38.77.39

lainp@panda.com.vn

Processing...