• No results found

Vocabulary Yiiframework

N/A
N/A
Protected

Academic year: 2021

Share "Vocabulary Yiiframework"

Copied!
78
0
0

Loading.... (view fulltext now)

Full text

(1)

HTTP://SEODRUPAL.VN

Lập trình Drupal, Zend Framework, Yii Framework

Kiểm tra tương thích giữa Yii với máy chủ

http://yourhostname/path_to_yii/requirements/index.php http://localhost/softvn/requirements/index.php

Phần mềm chạy local: Xampp, Wamp, ko nên dùng appserv vì bị lỗi( nguyên nhân mình ko biết, tốt nhất nên tránh).

Hoặc xài luôn host thật nếu nhà có điều kiện. 1. Chuẩn bị

Trước tiên bạn phải cấu hình windows để sử dụng được php với cmd -Giả sử bạn cài apache mặc định trên WinXP (C:\xampp\htdocs).

-Bạn thiết lập lại biến môi trường (Environment Variables) bằng cách vào: Start -> My Computer (right click!) -> Advanced Tab -> Environment Variables -> Click Path in System variables (windows 7 là Path) -> Edit.

-Click vào biến PATH và chọn Edit. Lưu ý là đừng có xoá bỏ các đường dẫn đã tồn tại trong textbox mà ngăn cách chúng với nhau bằng dấu ";".

-Tiếp đó bạn thêm vào những đường dẫn sau: "C:\xampp\php" và "

C:\xampp\htdocs\yii\framework". Lưu ý sửa đường dẫn cho phù hợp với máy bạn nha .

(2)

-Khởi động máy tính lại. 2.Tạo ứng dụng Yii mới

-YiiRoot là thư mục nơi bạn đã cài đặt Yii -Webroot là thư mục góc chứa web

-Từ dòng lệnh, đến webroot của bạn và thực hiện: C:\

Cd\

Cd C:\xampp\htdocs\

C:\xampp\htdocs\>softvn/framework/yiic webapp demo [demo]-> Tên ứng dụng

Create a Web application under '/Webroot/demo'? [Yes|No] Yes[y]

Vậy là khung xương của Yii đã được tạo ra thành công Trích dẫn:demo/

index.php file ứng dụng

index-test.php file kiểm tra chức năng assets/ chứa tài nguyên ứng dụng css/ chứa CSS

images/ chứa hình ảnh themes/ chứa giao diện

(3)

protected/ chứa các file được bảo vệ

Bạn có thể truy cập vào ứng dụng từ trình duyệt

http://localhost/demo/index.php

copy framework sang demo.

Vào file index.php thay đổi đường dẫn thành :

$yii=dirname(__FILE__).'/framework/yii.php';

III. Tạo controller

-Vào thư mục ứng dụng Mã:

%cd /Webroot/demo

C:/

Cd C:/xampp/htdocs/demo -Khởi động Yii Shell Mã:

%YiiRoot/framework/yiic shell

Cd C:/xampp/htdocs/demo

C:/xampp/htdocs/demo> C:/xampp/htdocs/softvn/framework/yiic shell Tạo thử controller tên message có hành động là helloWorld

Cú pháp: controller <controller-ID> [action-ID] VD:

Mã:

controller message helloWorld

-MessageController đã được tạo thành công ở thư mục: protected/controllers/ -Bên cạnh đó nó cũng tạo ra view tại thư mục: protected\views\message -Chúng ta cũng có thể truy cập vào hành động helloWorld từ trình duyệt Default: http://localhost/demo/index.php?r=message -> chạy vào index

http://localhost/demo/index.php?r=message/helloWorld

VIII. Tạo liên kết

-Yii có hỗ trợ sẳn hàm tạo liên kết trong class CHtml -VD:

Tạo liên kết tới View goodbye Mã:

<p><?php echo CHtml::link("Goodbye",array('message/goodbye')); ?></p>

Tạo liên kết tới View Hello Mã:

<p><?php echo CHtml::link("Hello",array('message/helloWorld')); ?></p>

IX.Cài đặt database

1.Yii hỗ trợ các dalabase sau:

(4)

-MySQL 4.1 or later -PostgresSQL 7.3 or later -SQLite 2 and 3

-Microsoft SQL Server 2000 or later -Oracle

2. Kết nối với database

-Thực hiện ở file /protected/config/main.php

-Mặc định nó đang kích hoạt đòng này là database của khung xương Yii Mã:

'db'=>array(

'connectionString' =>

'sqlite:'.dirname(__FILE__).'/../data/testdrive.db', ),

- Giả sử ta có 1 bảng trong Mysql như sau: Mã:

CREATE TABLE IF NOT EXISTS `tbl_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(128) NOT NULL, `password` varchar(128) NOT NULL, `email` varchar(128) NOT NULL, PRIMARY KEY (`id`)

);

- Chúng ta phải kích hoạt đòng sau trong /protected/config/main.php để kết nối với Mysql (bỏ /* */ và sửa lại cấu hình)

Mã:

// uncomment the following to use a MySQL database 'db'=>array( 'connectionString' => 'mysql:host=localhost;dbname=db_yii', 'emulatePrepare' => true, 'username' => 'root', 'password' => '', 'charset' => 'utf8', ),

-Ngoài ra ta có thể kết nối với cái database khác (thay đổi dòng 'connectionString') • SQLite: sqlite:/path/to/dbfile

• MySQL: mysql:host=localhost;dbname=testdb

• PostgreSQL: pgsql:host=localhost;port=5432;dbname=testdb • SQL Server: mssql:host=localhost;dbname=testdb

(5)

XI. Tạo CRUD

- CRUD là các chức năng create, read, update và delete 1 bảng trong database 1. Kích hoạt công cụ Gii

- Gii hỗ trợ sinh mã tự động các chức năng như Controller, Crud, Form, Model, Module. - Để kích hoạt Gii ta vào file config /protected/config/main.php

- Kích hoạt đoạn code sau Mã:

// uncomment the following to enable the Gii tool 'gii'=>array(

'class'=>'system.gii.GiiModule', 'password'=>'123456',

// If removed, Gii defaults to localhost only. Edit carefully to taste.

'ipFilters'=>array('127.0.0.1','::1'), ),

- Đổi password mới để đăng nhập Gii - Vào Gii thông qua url:

http:// tên host/demo/index.php?r=gii

http://i12.photobucket.com/albums/a225/k...age023.png http://i12.photobucket.com/albums/a225/k...age025.png

2. Tạo user Model

-Vào mục Model Generator để tạo Model cho bảng user

http://i12.photobucket.com/albums/a225/k...age027.png

- Table Prefix: viết phần tiền tố của bảng (nếu có) vào đây, ở đây bảng của ta tên là tbl_user nên tiền tố sẽ là tbl_

- Table Name: phần còn lại của tên bảng là user (ta có thể tạo tự động tất cả bảng bằng cách nhập dấu * vào đây)

- Model Class: tên lớp của model là User (tự sinh ra) - Còn lại để mặc định và click Preview

- Sau đó click Generate để tạo file Model của User tại thư mục /protected/models/User.php

3. Tạo CRUD:

- Vào mục Crud Generator

http://i12.photobucket.com/albums/a225/k...age029.png

- Model Class: điền chính xác tên lớp Model vừa tạo là User - Controller ID: điền user (không viết hoa)

- Còn lại để mặc định và click Preview - Sau đó click Generate để tạo Crud

(6)

4. Truy cập CRUD

- Vào url: http://yourhostname/demo/index.php?r=user

- Click vào các chức năng như Create User, Manage User, nó sẽ bắt ta đăng nhập, ta có thể sử dụng user và pass sau: demo/demo (tài khoản bình thường) hay admin/admin (tài khoản admin)

- Với tài khoản admin ta có thể truy cập vào trang quản lý sau

http://yourhostname/demo/index.php?r=user/admin

5. URL Thân thiện

Vào protected/config/main.php bỏ comment urlManager…..

$yii=dirname(__FILE__).'/framework/yii.php';

XII CÁC TRƯỜNG DỮ LIỆU TRONG FORM

$this->pageTitle=”Thay đổi tiêu đề trang tại đây”; Cách 1: Dùng form bằng cách dùng widget.

//Khởi tạo widget sử dụng Ajax cho Form Active

$form=$this->beginWidget('CActiveForm',array(

'id'=>'user-form',

'enableAjaxValidation'=>

true,

'enableClientValidation' =>true,

'focus'=>array($model,' name')

)); <?php //Kiểm tra đầu vào model đã đúng chưa ?

echo $form->errorSummary($model); ?>

<div class="row">

<?php //Khởi tạo trường name

echo 'Tên truy cập:';

echo $form->textField($model,'name');

echo $form->error($model,'name'); ?>

</div>

Thêm Captcha cho form

-Nếu chưa bật "gd2" thì ta vào file php.ini rồi sữa lại dòng này Mã PHP:

extension=php_gd2.dll

<?php $this->widget('CCaptcha',array(

'buttonLabel'

=> 'Lấy code mới',

'clickableImage'

=> true,

'imageOptions'

=> array('id' => 'captchaimg')

)); ?> RE: [Cơ Bản] Tạo form trong view

Xem thêm các Method để add các Field khác cho form Here

(7)

Viết Lại form trên bằng cách dùng 'CHtml': Mã PHP: <div id='form'> <?php echo CHtml::beginForm(); ?> <div id='row'>

<?php echo CHtml::activeLabel($model,'name');?> <br/>

<?php echo CHtml::activeTextField($model,'name')?> </div>

<div id='row'>

<?php echo CHtml::activeLabel($model,'email');?> <br/>

<?php echo CHtml::activeTextField($model,'email')?> </div>

<div id='row'>

<?php echo CHtml::activeLabel($model,'pass');?> <br/>

<?php echo CHtml::activePasswordField($model,'pass')?> </div>

<div id='row'>

<?php echo CHtml::activeLabel($model,'repass');?> <br/>

<?php echo CHtml::activePasswordField($model,'repass')?> </div>

<div id='row'>

<?php echo CHtml::activeLabel($model,'date');?> <br/>

<?php echo CHtml::activeTextField($model,'date')?> </div>

<div id='send'> <br/>

<?php echo CHtml::submitButton('Đăng Ký ',array('id'=>'frmReg','name'=>'frmReg'));?> </div>

<?php

echo CHtml::endForm(); ?>

</div>

Sau khi tạo form xong thì tới bước tiếp theo là add các ràng buộc cho thông tin mà user nhập vào ví dụ như:

• Các text box không được bỏ trống

• Email phài đúng dạng

• Pass phải lớn hơn 6 nhỏ hơn 15

• Repass phài y chang Pass

• Date: phài hợp lệ theo kiểu (dd-mm-yyyy) hay (mm-dd-yyyy)

• Add thêm captcha chống đăng ký hàng loạt

(8)

-Yii có hỗ trợ sẵn thư viện captcha cho chúng ta, và captcha thì nhìn cũng rất là cool.

Test xem có thể render captcha hay không

-Đầu tiên truy cập thử link này để test xem có captcha hay không cái đã.

http://www.code.com/index.php?r=site/captcha nếu ra như vầy là ok

-Nếu nó không hiện captcha thì ta nên check lại xem đã load "gd2" hay chưa bằng cách chạy mục test của Yii

giống như hình là load rồi, nó vàng hay đỏ thì xem lại cấu hình webserver -Nếu chưa bật "gd2" thì ta vào file php.ini rồi sữa lại dòng này

Mã PHP:

extension=php_gd2.dll

bỏ dấu ";" trước nó, mấy cái khác để defaut đừng táy máy, restar webser ver và test lại, nếu vẫn lỗi --> thôi cài lại win cho nó lành

-Để tạo captcha ta thêm vào phần view đoạn code sau: Mã PHP:

<?php $this->widget('CCaptcha',array(

'buttonLabel'

=> 'Lấy code mới',

'clickableImage'

=> true,

'imageOptions'

=> array('id' => 'captchaimg')

)); ?>

Với:

• 'buttonLabel' : hiển thị một link với nội dung mà ta set, khi click vào đó sẽ đỏi string cùa captcha

• 'clickableImage': khi click vào image sẽ đổi sang hình khác.

(9)

- Một captcha được rendered bởi một hành động của lớp CCaptchaAction, do đó nếu chỉ add bên view sẽ không hiển thị hình ảnh, vì captcha không được render. Do đó ta viết thêm bên Controller:

Mã PHP:

public function actions() { return array( 'captcha' => array ( 'class' => 'CCaptchaActio n', 'backColor' =>'#fff ' ), ); } Với

• 'backColor': màu nền ảnh #fff là màu đen,

• 'foreColor': màu chử captcha.

• 'height': chiểu cao ành

• 'width': Chiểu rộng

• 'maxLength': chiều dài tối da của chử captcha

• 'minLength': độ dài tối thiểu của string.

• 'verifyCode': lấy giá trị mã xác nhận

(10)

-Để ràng buộc các thông tin mà ủe nhập vào ta viết một phương thức trong Model như sau:

Mã PHP:

public function rules() {

return array (

array ('code','captcha', 'allowEmpty'=>! CCaptcha::checkRequirements(),

'message' => 'Mã Xác Nhận Nhập Không Đúng'

),

array('email','email','message' =>'{attribute} không hợp lệ'),

array('name,email,pass,repass,date,code','required',

'message'=>"{attribute} không được bỏ trống"),

array('repass','compare','compareAttribute'=>'pass',

'message'=>"{attribute} phải chính xác"),

array('pass','length','min'=>'6','message'=>"{attri bute} không đủ độ dài "),

array('date','date','format'=>

'dd-mm-yyyy','message'=>"{attribute} phải chính xác dạng {dd-mm-yyyy}"), );

}

PHẦN I – XỬ LÝ NỘI TẠI WEBSITE

Các bước phân tích BackEnd (CMS) với dự án (PROJECT)

TẠO BẢNG PROJECT

CREATE TABLE tbl_project (

id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(128), description TEXT, create_time DATETIME, create_user_id INTEGER, update_time DATETIME, update_user_id INTEGER );

Sử dụng GII xây dựng Project AR class

Lưu ý: sau tên localhost là tên folder website của bạn, vui lòng thay thế cho đúng.

http://localhost/trackstar/index.php?r=gii.

Tạo mới 1 class model tbl_project table, the Model Generator ->Generate.

Navigate back to the main Gii menu located at http://localhost/trackstar/index.php? r=gii, and choose the Crud Generator ->Generate (Gõ tên bảng vào keyword tìm

(11)

Xem kết quả: http://localhost/trackstar/index.php?r=project). Tạo một vài dữ liệu để thực hiện việc xây dựng DB.

-Thiết kế giản đồ dữ liệu (database schema) và xây dựng đối tượng hỗ trợ các sản phẩm (issues) của dự án.

- Tạo mô hình lớp(model class) Yii cho phép ứng dụng dễ dàng tương tác các bảng dữ liệu với nhau sau khi tạo.

- Tạo lớp điều khiển (controller class) sẽ là không gian chứa các hàm cho phép chúng ta : + Tạo các sản phẩm (issues) mới.

+ Tìm về một danh sách sản phẩm hiện hành trong phạm vi một dự án lấy từ database.

+ Cập nhật/chỉnh sửa sản phẩm hiện hành. + Xóa đi sản phẩm hiện hành.

- Tạo khung nhìn (view) để trả lại (render) cho giao diện người sử dụng các hành động ( có trước).

- THIẾT KẾ GIẢN ĐỒ (SCHEMA)

Chúng ta giả sử nó có một thuộc tính (type), bản thân (owner), một yêu cầu (requester), một trạng thái (status) , và miêu tả (description). Chúng ta sẽ tạo bảng (tbl_project) để thêm các thông tin cơ bản được kiểm tra với các bảng khác chúng ta tạo ngày( date), giờ(times) và người truy cập update bảng .

Tuy nhiên thuộc tính(types), bản thân(owner), người yêu cầu(requester) và trạng thái(status) là tự chúng.Bản thân chúng là thực thể. Để giữ cho mô hình mềm dẻo và dễ dàng mở rộng, chúng ta sẽ tạo nhiều mô hình (model) không dính dáng tới nhau. Bản thân (developer) (owner) và người yêu cầu (requester) là hai người sử dụng hệ thống được tham chiếu từ một hàng (row) trong bảng được gọi là (tbl_user).

Chúng ta có thể bắt đầu giới thiệu ý tưởng về người sử dụng (user) trong bảng dự án (tbl_project) , chúng ta thêm cột (create_user_id) , (update_user_id) để nhận dạng đường đi của một người sử dụng lúc ban đầu họ tạo dự án, tương tự như vậy khi người sử dụng (user) cập nhật chi tiết dự án lần cuối cùng. Mặc dù chúng ta chưa giới thiệu bảng đó vào lúc này, có những trường dữ liệu được mô hình chuyển qua khóa ngoài tới một bảng dữ liệu khác để lưu trữ dữ liệu về người sử dụng (user data). Trường (owner_id) mã bản thân, (requester_id) mã người yêu cầu, trong bảng (tbl_issue) cũng sẽ được khóa ngoài liên kết trở lại với bảng (tbl_user).

ĐỊNH NGHĨA CÁC MỐI QUAN HỆ

+

Một dự án có thể có nhiều người sử dụng truy cập, và người truy cập có thể liên kết với nhiều dự án chúng ta gọi đó là liên kết nhiều – nhiều (many – to – many ).

+Cách thức tốt nhất để mô hình hóa quan hệ nhiều – nhiều (many-to-many) trong các dữ liệu liên quan đó là sử dụng sự kết hợp (association) hoặc phân quyền cho bảng (table).

(12)

Dưới đây là mô hình cơ bản thực thể quan hệ giữa người sử dụng (users),dự án(project), và sản phẩm (issues). Một dự án có thể có hoặc không có nhiều người dùng,. Một người sử dụng cần phải kết hợp với ít nhất một dự án, hoặc có thể kết hợp với nhiều dự án. Sản phẩm sẽ chỉ thuộc về một và chỉ duy nhất một dự án. Khi đó một dự án có thể có không -> nhiều sản phẩm.

Một sản phẩm được phân quyền (hay được yêu cầu) bởi duy nhất 1 người dùng.

Exactly one: Chỉ duy nhất 1. 1 or More : Một hoặc nhiều 0 or More : Không hoặc nhiều. Dịch : Project: Dự án

Issue: vấn đề User: Người dùng Owner: Bản thân.

XÂY DỰNG DATABASE VÀ CÁC MỐI QUAN HỆ

Tạo 3 bảng mới là: tbl_issue,tbl_user,tbl_project_user_assignment() ( bảng trung gian ).

CREATE TABLE IF NOT EXISTS 'tbl_issue' (

'id' INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, 'name' varchar(256) NOT NULL,

'description' varchar(2000), 'project_id' INTEGER, 'type_id' INTEGER, 'status_id' INTEGER, 'owner_id' INTEGER, 'requester_id' INTEGER, 'create_time' DATETIME, 'create_user_id' INTEGER, 'update_time' DATETIME,

(13)

'update_user_id' INTEGER ) ENGINE = InnoDB

;

CREATE TABLE IF NOT EXISTS 'tbl_user' (

'id' INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, 'email' Varchar(256) NOT NULL,

'username' Varchar(256), 'password' Varchar(256), 'last_login_time' Datetime, 'create_time' DATETIME, 'create_user_id' INTEGER, 'update_time' DATETIME, 'update_user_id' INTEGER ) ENGINE = InnoDB ;

CREATE TABLE IF NOT EXISTS 'tbl_project_user_assignment' (

'project_id' Int(11) NOT NULL, 'user_id' Int(11) NOT NULL, 'create_time' DATETIME, 'create_user_id' INTEGER, 'update_time' DATETIME, 'update_user_id' INTEGER,

PRIMARY KEY ('project_id','user_id') ) ENGINE = InnoDB

;

Tạo các mối quan hệ:

-Tạo khóa ngoại giữa 2 bảng tbl_issue,tbl_project tham chiếu (id thuộc bảng tbl_project) nối với project_id trong bảng tbl_issue.

ALTER TABLE 'tbl_issue' ADD CONSTRAINT 'FK_issue_project' FOREIGN KEY ('project_id') REFERENCES 'tbl_project' ('id') ON DELETE CASCADE ON UPDATE RESTRICT;

-Tạo khóa ngoại giữa 2 bảng tbl_issue, tbl_user tham chiếu (id thuộc bảng tbl_user) nối với owner_id (khóa bản thân) trong bảng tbl_issue.

ALTER TABLE 'tbl_issue' ADD CONSTRAINT 'FK_issue_owner'

FOREIGN KEY ('owner_id') REFERENCES 'tbl_user' ('id') ON DELETE CASCADE ON UPDATE RESTRICT;

Tương tự với các khóa ngoại còn lại:

ALTER TABLE 'tbl_issue' ADD CONSTRAINT 'FK_issue_requester' FOREIGN KEY ('requester_id') REFERENCES 'tbl_user' ('id') ON DELETE CASCADE ON UPDATE RESTRICT;

(14)

ALTER TABLE 'tbl_project_user_assignment' ADD CONSTRAINT 'FK_project_user' FOREIGN KEY ('project_id') REFERENCES 'tbl_project' ('id') ON DELETE CASCADE ON UPDATE RESTRICT; ALTER TABLE 'tbl_project_user_assignment' ADD CONSTRAINT 'FK_user_project' FOREIGN KEY ('user_id') REFERENCES 'tbl_user' ('id') ON DELETE CASCADE ON UPDATE RESTRICT;

Tạo Active Record Model classes cho các bảng vừa tạo:

-Tạo AR Model issues

Navigate to the Gii tool via http://localhost/trackstar/index.php?r=gii, and choose the

Model Generator link. Leave the table prefix as tbl_. Fill in the Table Name

field as tbl_issue, which will auto-populate the Model Class field as Issue.->preview->generate - Tạo Issues CRUD operation

Navigate to the Gii generator menu at http://localhost/trackstar/index.php? r=gii, and choose the Crud Generator link. Fill out the form using Issue as the value for the Model Class field. This will auto-populate the Controller ID to also be Issue. The Base Controller Class and Code Template fields can remain their predefined default values. Click the Preview -> Generate.

Thêm thuộc tính DropDown Menu

Mở model/Issue class: Ở đầu trang class Issue khai báo hằng các thuộc tính: const TYPE_BUG=0;

const TYPE_FEATURE=1; const TYPE_TASK=2;

Tạo hàm trả về mảng chứa các thuộc tính: public function getTypeOptions()

{ return array( self::TYPE_BUG=>'Bug', self::TYPE_FEATURE=>'Feature', self::TYPE_TASK=>'Task', ); }

Thêm một filter (bộ lọc)

Mở protected/controllers/IssueController.php thêm nội dung sau vào dưới lớp:

public function filterProjectContext($filterChain) {

$filterChain->run(); }

(15)

Thêm cấu hình cho filter vào mảng cấu hình.Với filter mới được định nghĩa ta thử áp dụng với create action.(Hàm tạo).

public function filters() {

return array(

'accessControl', // perform access control for CRUD operations

'projectContext + create', //check to ensure valid project context );

}

Phương thức trên sẽ trả về cấu hình cho filter projectContext cái mà chúng ta đã định nghĩa giống như một phương thức trong class và nó áp dụng cho actionCreate() method. Cú pháp cấu hình cho phép là : ‘+’ hoặc dấu ‘-‘ ký hiệu đặc biệt được sử dụng khi chúng ta muốn hoặc không muốn một filter nào đó được áp dụng hay không.

Ví dụ nếu chúng ta quyết định muốn áp dụng cho tất cả các action ngoại trừ actionUpdate() cập nhật, và actionView() (nhìn).Chúng ta thực hiện :

return array('projectContext - update, view' ,); Thêm một vài Filter Logic

Chúng ta vừa định nghĩa được filter mới và cấu hình nó thực hiện method actionCreate();

Tuy nhiên chúng ta chưa thực hiện được sự logic cần thiết.Chúng ta muốn chắc chắn rằng văn bản dự án được thực hiện trước khi các hành động (action) được kick hoạt.Chúng ta cần đặt filter logic trước khi gọi filterChain->run().

Chúng ta sẽ sử dụng chuỗi từ khóa (querystring) là một tham biến ngoài URL được trình bày để nhận dạng các dự án (project).

Các pre-action của Filter sẽ kiểm tra để nhận biết.Nếu các thuộc tính của dự án hiện tại là NULL, chúng ta sẽ sử dụng chuỗi từ khóa(querystring) tham biến để kích hoạt sự lựa chọn các dự án cơ bản trong khóa chính được nhận dạng (Primary Key indentifier). Nếu thành công Action sẽ thực hiện, và nếu thất bại một lỗi ngoại lệ sẽ được hiện ra.

Chúng ta vào IssueController class:

class IssueController extends CController {

.... /**

* @var private property containing the associated Project model instance.

*/

private $_project = null; /**

(16)

* @project_id the primary identifier of the associated Project

* @return object the Project data model based on the primary key */

protected function loadProject($project_id) {

//if the project property is null, create it based on input id if($this->_project===null)

{

$this->_project=Issue::model()->findbyPk($project_id); if($this->_project===null)

{

throw new CHttpException(404,'The requested project does not exist.'); } } return $this->_project; } /**

* In-class defined filter method, configured for use in the above filters() method

* It is called before the actionCreate() action method is run in order to ensure a proper project context

*/

public function filterProjectContext($filterChain) {

//set the project identifier based on either the GET or POST input //request variables, since we allow both types for our actions $projectId = null; if(isset($_GET['pid'])) $projectId = $_GET['pid']; else if(isset($_POST['pid'])) $projectId = $_POST['pid']; $this->loadProject($projectId);

//complete the running of other filters and execute the requested action

$filterChain->run(); }

... }

(17)

THÊM PROJECT ID

Liên kết( link) chúng ta cần điều chỉnh trong view file : /protected/views/issue/index.php.

Ở đầu trang chúng ta sẽ nhìn thấy link create new . $this->menu=array(

array('label'=>'Create Issue', 'url'=>array('create')), array('label'=>'Manage Issue', 'url'=>array('admin')),

);

Chúng ta thêm trường pid vừa tạo :

array('label'=>'Create Issue', 'url'=>array('create', 'pid'=>1)), Truy cập lại vào admin và click vào link liên kết : http://localhost/demo/index.php? r=issue/create&pid=1. Ta đã thực hiện được.

Điều chỉnh chi tiết từng trang của dự án:

Thêm mã dự án cho từng URL cho việc tạo mới sản phẩm là một giai đoạn khá tốt để chắc chắn rằng những điều chỉnh bên ngoài làm việc một cách hoàn hảo.Tuy nhiên, chúng ta có một vấn đề xảy ra với mã code là projectID luôn luôn =1 .Tất nhiên, điều này không phải là những gì chúng ta muốn.Chúng ta muốn có menu option cho việc tạo mới sản phẩm trong trang chi tiết của dự án.Nghĩa là , khi bạn lựa chọn một dự án từ trang danh sách chi tiết các dự án, mã dự án đặc biệt sẽ phải được hiểu và phải có mã dự án động . (dynamic project id).#1

Mở chi tiết dự án trong : view, /protected/views/project/view.php. Trong phần đầu trong ta sẽ tìm và thêm pid như sau :

$this->menu=array(

array('label'=>'List Project', 'url'=>array('index')), array('label'=>'Create Project', 'url'=>array('create')), array('label'=>'Update Project', 'url'=>array('update', 'id'=>$model->id)),

array('label'=>'Delete Project', 'url'=>'#',

'linkOptions'=>array('submit'=>array('delete','id'=>$model->id),'confirm'=>'Are you sure you want to delete this item?')), array('label'=>'Manage Project', 'url'=>array('admin')),

array('label'=>'Create Issue', 'url'=>array('issue/create', 'pid'=>$model->id)),

);

Xóa bỏ các input form dự án (project).

Đầu tiên hãy chỉnh lại IssueController::actionCreate() public function actionCreate()

{

(18)

$model->project_id = $this->_project->id; ... } Mở /protected/views/issue/_form. Tìm trường: <div class="row"> <?php echo $form->labelEx($model,'project_id'); ?> <?php echo $form->textField($model,'project_id'); ?> <?php echo $form->error($model,'project_id'); ?> </div>

Thay thế: <div class="row">

<?php echo $form->hiddenField($model,'project_id'); ?> </div>

Quay lại việc bản thân (owner) và người yêu cầu (requester) dropdown. Chúng ta đã thêm 2 user là :

INSERT INTO 'tbl_user'

('email', 'username', 'password') VALUES

('[email protected]','Test_User_One', MD5('test1')), ('[email protected]','Test_User_Two', MD5('test2')) ;

Để tạo 2 user trong hệ thống với Id là 1, 2 ta thực hiện assign:

INSERT INTO 'tbl_project_user_assignment' ('project_id', 'user_id') VALUES (1,1), (1,2);

Chúng ta có thể nhìn mối quan hệ giữa các table trong /protected/models/Issue.php.

public function relations() {

// NOTE: you may need to adjust the relation name and the related // class name for the relations automatically generated below. return array(

'owner' => array(self::BELONGS_TO, 'User', 'owner_id'), 'project' => array(self::BELONGS_TO, 'Project', 'project_id'), 'requester' => array(self::BELONGS_TO, 'User', 'requester_id'), );

}

Chúng ta sẽ thêm quan hệ: Project::relations() method.

Mở: /protected/models/Project.php, và thay thế các thực thể trong relation() như sau:

(19)

/**

* @return array relational rules. */

public function relations() {

// NOTE: you may need to adjust the relation name and the related // class name for the relations automatically generated below. return array(

'issues' => array(self::HAS_MANY, 'Issue', 'project_id'), 'users' => array(self::MANY_MANY, 'User',

'tbl_project_user_assignment(project_id, user_id)'), );

}

Tạo Dữ liệu từ Dropdown Menu

Mở /issue/models/Issue.php, và thêm đoạn code sau vào dưới class: public function getUserOptions()

{

$usersArray = CHtml::listData($this->users, 'id', 'username'); return $usersArray;

}}

Thêm User và ProjectUserAssignment

Thêm đoạn sau vào dưới class của IssueController class: /**

* Returns the project model instance to which this issue belongs */

public function getProject() {

return $this->_project; }

Mở /protected/views/issue/_form.php và tìm trong form các trường owner_id, requester_id

Thay thế: <?php //echo $form->textField($model,'owner_id'); ?> thành

<?php echo $form->dropDownList($model,'owner_id',$model->project->getUserOptions()); ?>

Thực hiện thay thế:

(20)

Trở thành:

<?php echo $form->dropDownList($model,'requester_id', $this->getProject()->getUserOptions()); ?> Remove các trường sau: <div class="row"> <?php echo $form->labelEx($model,'create_time'); ?> <?php echo $form->textField($model,'create_time'); ?> <?php echo $form->error($model,'create_time'); ?> </div> <div class="row"> <?php echo $form->labelEx($model,'create_user_id'); ?> <?php echo $form->textField($model,'create_user_id'); ?> <?php echo $form->error($model,'create_user_id'); ?> </div> <div class="row"> <?php echo $form->labelEx($model,'update_time'); ?> <?php echo $form->textField($model,'update_time'); ?> <?php echo $form->error($model,'update_time'); ?> </div> <div class="row"> <?php echo $form->labelEx($model,'update_user_id'); ?> <?php echo $form->textField($model,'update_user_id'); ?> <?php echo $form->error($model,'update_user_id'); ?> </div>

Truy cập vào issue với acc:demo xem thử phần create action(); THAY ĐỔI PROJECT CONTROLLER

Trước tiên điều chỉnh actionView() trong class Project Controller giống như chúng ta muốn trưng bày danh sách sản phẩm liên quan đến các dự án đặc biệt.Chúng ta có thể làm điều này trong một vài trang giống như trang chi tiết.Phương thức Action View() là method được dùng để hiển thị chi tiết sản phẩm.

Điều chỉnh method như sau: /**

* Displays a particular model. */

public function actionView() {

$issueDataProvider=new CActiveDataProvider('Issue', array( 'criteria'=>array(

'condition'=>'project_id=:projectId',

'params'=>array(':projectId'=>$this->loadModel()->id), ),

(21)

'pageSize'=>1, ), )); $this->render('view',array( 'model'=>$this->loadModel(), 'issueDataProvider'=>$issueDataProvider, )); }

Tại đây chúng ta sử dụng CactiveDataProvider class trong framework để cung cấp dữ liệu trong object ActiveRecord. Nó sẽ sử dụng class Model AR liên quan để lấy dữ liệu từ database trong một các dễ dàng với Yii widget. ClistView để trưng bày item trong danh sách được render trong view file. Chúng ta có thể sử dụng criteria là điều kiện đặc biệt chỉ để lấy các vấn đề liên quan tới dự án được trưng bày.Chúng ta cũng có thể sử dụng pagination(Phân trang) để giới hạn danh sách sản phẩm trong một trang.

ĐIỀU CHỈNH Project View File Mở /protected/views/project/view.php

Thêm đoạn code sau vào dưới cùng file: <br> <h1>Project Issues</h1> <?php $this->widget('zii.widgets.CListView', array( 'dataProvider'=>$issueDataProvider, 'itemView'=>'/issue/_view', )); ?>

Ở đây chúng ta đang thiết lập thuộc tính dataProvider CListView được vấn đề cung cấp dữ liệu chúng ta đã vừa tạo. Sau đó chúng ta cấu hình nó để sử dụng trong

protected/view/issue/_view.php giống như một template cho render item trong dữ liệu được cung cấp.File này đã được tạo cho chúng ta bởi Gii tool khi chúng ta generate trong CRUD của issues. Chúng ta chỉ sử dụng nó ở đây để trưng bày sản phẩm trong trang chi tiết của dự án.

Chúng ta cũng phải thay đổi /protected/views/issue/_view.php sử dụng template layout cho sản phẩm khác. Điều chỉnh nội dung thực thể sau:

<div class="view"> <b><?php echo CHtml::encode($data->getAttributeLabel('name')); ?>:</b> <?php echo CHtml::link(CHtml::encode($data->name), array('issue/view', 'id'=>$data->id)); ?> <br /> <b><?php echo CHtml::encode($data->getAttributeLabel('description')); ?>:</b> <?php echo CHtml::encode($data->description); ?> <br />

(22)

<b><?php echo CHtml::encode($data->getAttributeLabel('type_id')); ?>:</b> <?php echo CHtml::encode($data->type_id); ?> <br /> <b><?php echo CHtml::encode($data->getAttributeLabel('status_id')); ?:</b> <?php echo CHtml::encode($data->status_id); ?> </div>

Tại Project Controller Sửa đổi LoadModule private $_model;

public function loadModel() { if($this->_model===NULL) { if(isset($_GET['id'])) $this->_model=Project::model()->findByPk($_GET['id']); if($this->_model===null)

throw new CHttpException(404,'The requested page does not exist.');

}

return $this->_model; }

Thêm dữ liệu vào bên issue/create tạo mới 2 bản ghi.

Kiểm tra kết quả : (http://localhost/tasctrak/index.php?r=project/view&id=1)

Hiển thị các Status và Type text trong ISSUE Vào : /protected/models/Issue.php

public function getStatusText() {

$statusOptions=$this->statusOptions;

return isset($statusOptions[$this->status_id]) ? $statusOptions[$this->status_id] : "unknown status ({$this->status_id})";

} /**

* @return string the type text display for the current issue */

public function getTypeText() {

$typeOptions=$this->typeOptions;

return isset($typeOptions[$this->type_id]) ? $typeOptions[$this->type_id] : "unknown type ({$this->type_id})";

}

(23)

Vào : /protected/views/issue/_view.php:

Thay đổi :<?php echo CHtml::encode($data->type_id); ?> thành <?php echo CHtml::encode($data->getTypeText()); ?> Và thay đổi <?php echo CHtml::encode($data->status_id); ?> this: <?php echo CHtml::encode($data->getStatusText()); ?> THAY ĐỔI CHI TIẾT VIEW ISSUE

Mở :/protected/views/issue/view.php Thêm đoạn sau: <?php $this->widget('zii.widgets.CDetailView', array( 'data'=>$model, 'attributes'=>array( 'id', 'name', 'description', 'project_id', 'type_id', 'status_id', 'owner_id', 'requester_id', 'create_time', 'create_user_id', 'update_time', 'update_user_id', ), )); ?> Thay đổi thành: <?php $this->widget('zii.widgets.CDetailView', array( 'data'=>$model, 'attributes'=>array( 'id', 'name', 'description', array(

(24)

'name'=>'type_id', 'value'=>CHtml::encode($model->getTypeText()) ), array( 'name'=>'status_id', 'value'=>CHtml::encode($model->getStatusText()) ), 'owner_id', 'requester_id', ), )); ?>

Bổ sung thêm project_id vào function Admin public function actionAdmin()

{

$model=new Issue('search');

$model->unsetAttributes(); // clear any default values if(isset($_GET['Issue'])) $model->attributes=$_GET['Issue']; $model->project_id=$this->_project->id; $this->render('admin',array( 'model'=>$model, )); }

Định nghĩa CactiveDataProvider trong indexAction public function actionIndex()

{ $dataProvider=new CActiveDataProvider('Issue',array('criteria'=>array('condition'=>'project_id=:project_Id',' params'=>array(':project_Id'=>$this->_project->id)))); $this->render('index',array( 'dataProvider'=>$dataProvider, )); } Sử dụng quan hệ AR

Như issues và user là đại diện như những bảng dữ liệu riêng biệt, và liên quan đến quan hệ khóa ngoại, chúng ta thực sự truy cập vào owner và requester username trực tiếp từ $model trong view file. Bằng cách sử dụng sức mạnh của Yii AR mô hình quan hệ, trưng bày thuộc tính username của liên quan đến model User class.

As we have mentioned, the model class Issue::relations() method is where the relationships are defined. If we take a peek at this method, we see the following: /**

(25)

* @return array relational rules. */

public function relations() {

// NOTE: you may need to adjust the relation name and the related // class name for the relations automatically generated below. return array(

'owner' => array(self::BELONGS_TO, 'User', 'owner_id'), //belong to là thuộc về 'project' => array(self::BELONGS_TO, 'Project', 'project_id'),

'requester' => array(self::BELONGS_TO, 'User', 'requester_id'), );

}

Trưng bày Username của Owner và requester: Protected\view\issue\view.php <?php $this->widget('zii.widgets.CDetailView', array( 'data'=>$model, 'attributes'=>array( 'id', 'name', 'description', array( 'name'=>'type_id', 'value'=>CHtml::encode($model->getTypeText()) ), array( 'name'=>'status_id', 'value'=>CHtml::encode($model->getStatusText()) ), array( 'name'=>'owner_id', 'value'=>CHtml::encode($model->owner->username) ), array( 'name'=>'requester_id', 'value'=>CHtml::encode($model->requester->username) ), ) )); ?>

Thực hiện một số điều chỉnh cuối cùng.

Một điều chúng ta nhận ra là ứng dụng vẫn cho phép người dùng được điều hướng tới những danh sách của sản phẩm, cũng như tất cả dự án. Ví dụ trong một trang chi tiết sản phẩm,

(26)

Chúng ta nhìn thấy menu điều hướng bên phải, gồm có Danh sách sản phảm, và quản lý sản phẩm tương ứng :http://localhost/trackstar/index.php?r=issue/index and

http://localhost/trackstar/index.php?r=issue/admin

Nhớ rằng để truy cập vào trang quản trị bạn cần vào với tài khoản admin/admin Nhưng vẫn còn hiển thị tất cả các sản phẩm, trên tất cả các dự án. Vì vậy, chúng ta cần phải hạn chế danh sách này để có một dự án cụ thể.

Có những liên kết hình thành từ trang chi tiết sản phẩm (issue) và đặc biệt sản phẩm đó có dự án liên quan, chúng ta có thể bắt đầu chỉnh lại liên kết được nhấn trong projectID và projectID này nằm trong IssueController::index và IssueController::actionAdmin method.

Mở đường dẫn: /protected/views/issue/view.php thay đổi cấu hình menu:

$this->menu=array(

array('label'=>'List Issue', 'url'=>array('index', 'pid'=>$model->project->id)), array('label'=>'Create Issue', 'url'=>array('create', 'pid'=>$model->project->id)), array('label'=>'Update Issue', 'url'=>array('update', 'id'=>$model->id)),

array('label'=>'Delete Issue', 'url'=>'#',

'linkOptions'=>array('submit'=>array('delete','id'=>$model->id),'confirm'=>'Are you sure you want to delete this item?')),

array('label'=>'Manage Issue', 'url'=>array('admin', 'pid'=>$model->project->id)), );

Thay đổi cấu hình filter trong IssueController public function filters()

{

return array(

'accessControl', // perform access control for CRUD operations

'projectContext + create index admin', //perform a check to ensure valid project context

); }

Chỉnh lai method actionIndex() public function actionIndex() {

$dataProvider=new CActiveDataProvider('Issue', array( 'criteria'=>array( 'condition'=>'project_id=:projectId', 'params'=>array(':projectId'=>$this->_project->id), ), )); $this->render('index',array( 'dataProvider'=>$dataProvider, ));

(27)

}

THAY ĐỔI DANH SÁCH TRANG ADMIN Điều chỉnh method admin:

public function actionAdmin() { $model=new Issue('search'); if(isset($_GET['Issue'])) $model->attributes=$_GET['Issue']; $model->project_id = $this->_project->id; $this->render('admin',array( 'model'=>$model, )); }

Thêm các tiêu chuẩn mới vào Model/ Issue::search() public function search()

{

// Warning: Please modify the following code to remove attributes that

// should not be searched. $criteria=new CDbCriteria; $criteria->compare('id',$this->id); $criteria->compare('name',$this->name,true); $criteria->compare('description',$this->description,true); $criteria->compare('type_id',$this->type_id); $criteria->compare('status_id',$this->status_id); $criteria->compare('owner_id',$this->owner_id); $criteria->compare('requester_id',$this->requester_id); $criteria->compare('create_time',$this->create_time,true); $criteria->compare('create_user_id',$this->create_user_id); $criteria->compare('update_time',$this->update_time,true); $criteria->compare('update_user_id',$this->update_user_id); $criteria->condition='project_id=:projectID'; $criteria->params=array(':projectID'=>$this->project_id); return new CActiveDataProvider(get_class($this), array(

'criteria'=>$criteria, ));

}

CHƯƠNG 7 - QUẢN TRỊ NGƯỜI DÙNG VÀ Xác Thực QUYỀN

TRUY CẬP

(28)

Khi chúng ta sử dụng công cụ yiic command, chúng ta nhận được hàm đăng nhập(login) mức cơ bản với công cụ tạo sẵn cho chúng ta. Trang đăng nhập cho phép người dùng truy nhập với 2 hình thức tài khoản (admin/admin) (demo/demo)

Chúng ta cần làm một số thay đổi điều chỉnh sao cho chúng ta quản lý được nhiều người dùng.Điều này sẽ khiến ta phải mở rộng thêm bảng người dùng (table user) và thêm các chức năng cần thiết để quản lý.

TẠO CRUD của table User

Navigate to the Gii tool via http://localhost/trackstar/index.php?r=gii and choose the

Model Generator link. Leave the table prefix as tbl. Fill in the Table Name field as tbl_user, which will auto-populate the Model Class name field as User .Click preview -> generate.

Navigate to the tool via http://localhost/trackstar/index.php?r=gii.

2. Choose the Crud Generator link from the list of available generators. 3. Type in User for the Model Class name field. The corresponding

Controller ID will auto-populate with user.->preview->generate. Gõ http://localhost/trackstar/index.php?r=user để xem kết quả hiển thị.

Cập nhật kiểm tra lịch sử các cột (columns).

Như tất cả các thực thể của chúng tôi bảng tbl_project, tbl_issue, tbl_user có các cột tương tự quy định, chúng tôi sẽ thêm vào các logic cần thiết cho một lớp cơ sở chung và sau đó có mỗi của các lớp cá nhân AR mở rộng từ lớp cơ sở mới này.

Lý do chúng ta đang tạo lớp mới này, thay vì chỉ cần thêm logic trực tiếp vào model class project, là bởi vì các class khác, model Issue và User, cũng cần logic này. Thay vì lặp lại trong các mã trong tất cả các lớp mô hình AR, cách tiếp cận này sẽ cho phép chúng tôi để thiết lập các lĩnh vực này cho tất cả các lớp mô hình AR chỉ trong một nơi. Chúng tôi cũng sẽ làm cho lớp trừu tượng mới, vì nó không nên được khởi tạo trực tiếp.

Tạo file mới: trong protected/models/ tạo CheckUserActiveRecord.php

<?php

abstract class CheckUserActiveRecord extends CActiveRecord {

/**

* Prepares create_time, create_user_id, update_time and update_user_id attributes before performing validation.

*/

protected function beforeValidate() {

if($this->isNewRecord) {

// set the create date, last updated date and the user doing the creating $this->create_time=$this->update_time=new CDbExpression('NOW()'); $this->create_user_id=$this->update_user_id=Yii::app()->user->id; }

else {

(29)

//not a new record, so just set the last updated time and last updated user id $this->update_time=new CDbExpression('NOW()'); $this->update_user_id=Yii::app()->user->id; } return parent::beforeValidate(); } }

Ở đây chúng ta đang ghi đè phương thức CactiveRecord::beforeValidate().Đây là phương thức giúp người sử dụng có thể tùy biến quá trình truy cập.

nếu bạn không thực hiện sai một tham số khi gọi phương thức save () trên một lớp AR, quá trình xác thực sẽ được kích hoạt. Quá trình này thực hiện xác thực theo quy định trong phương pháp rules () trong lớp AR. Có hai phương pháp tiếp xúc cho phép chúng ta để khai thác các công việc xác nhận và thực hiện bất kỳ logic cần thiết, hoặc ngay trước hoặc ngay sau khi xác nhận được thực hiện: beforeValidate () và afterValidate ().

Chú ý: Sử dụng NOW () trong mã trước đó là cụ thể cho MySQL. Điều này có thể làm việc nếu bạn đang theo cùng cách sử dụng một cơ sở dữ liệu khác nhau. Bạn luôn có thể có một cách tiếp cận khác nhau để thiết lập giá trị này. Ví dụ, bằng cách sử dụng chức năng thời gian PHP và định dạng nó một cách thích hợp cho loại dữ liệu của cột: $ this-> createTime = $ this-> updateTime = ngày ("Ymd H: i: s, time());

bây giờ chúng ta cần phải thay đổi 3 class hiện có của AR là -Project.php, User.php, và Issue.php để mở rộng từ lớp trừu tượng hơn là trực tiếp từ CActiveRecord.3 class này nằm trong protected/models/.

Chúng ta thay thế :

class Project extends CActiveRecord {

Thay đổi thành

class Project extends CheckUserActiveRecord {

Tương tự với 2 class user và issue.

Định nghĩa lần lượt các trường dữ liệu trong form nằm trong :

protected/views/project/_form.php và protected/views/user/_form.php protected/views/issue/_form.php,

Loại bỏ các trường dữ liệu như sau: <div class="row"> <?php echo $form->labelEx($model,'create_time'); ?> <?php echo $form->textField($model,'create_time'); ?> <?php echo $form->error($model,'create_time'); ?> </div> <div class="row"> <?php echo $form->labelEx($model,'create_user_id'); ?> <?php echo $form->textField($model,'create_user_id'); ?> <?php echo $form->error($model,'create_user_id'); ?> </div>

(30)

<div class="row"> <?php echo $form->labelEx($model,'update_time'); ?> <?php echo $form->textField($model,'update_time'); ?> <?php echo $form->error($model,'update_time'); ?> </div> <div class="row"> <?php echo $form->labelEx($model,'update_user_id'); ?> <?php echo $form->textField($model,'update_user_id'); ?> <?php echo $form->error($model,'update_user_id'); ?> </div>

Từ form user trong : protected/views/user/_form.php chúng ta xóa bỏ thuộc tính last login time

<div class="row">

<?php echo $form->labelEx($model,'last_login_time'); ?> <?php echo $form->textField($model,'last_login_time'); ?> <?php echo $form->error($model,'last_login_time'); ?> </div>

chúng ta cũng nên loại bỏ các quy tắc xác nhận quy định cho các trường này trong các method quy tắc liên quan

Trong method User::rules() method, xóa đi 2 rules sau:

array('create_user_id, update_user_id', 'numerical', 'integerOnly'=>true), array('last_login_time, create_time, update_time', 'safe'),

Làm tương tự với 2 model còn lại là :project, issue. Xóa bỏ các trường liên quan tới dữ liệu vừa xóa.

Thêm trường xác thực mật khẩu: Thêm lên bên đầu trang user:

public $password_repeat;

User::rules() method thêm :

array('password', 'compare'), array('password_repeat', 'safe'),

Vào protected/views/user/_form thêm trường nhập lại mật khẩu :

<div class="row"> <?php echo $form->label($model,'password_repeat'); ?> <?php echo $form->passwordField($model,'password_repeat',array('size'=>60,'maxlength'=>256)); ?> <?php echo $form->error($model,'password_repeat'); ?> </div> Mã hóa mật khẩu:

Mở CheckUserActiveRecord trong protected/models/ và thực hiện:

/**

(31)

*/

protected function afterValidate() {

parent::afterValidate();

$this->password = $this->encrypt($this->password); }

public function encrypt($value) {

return md5($value); }

XÁC THỰC USER sử dụng DATABASE

Giới thiệu Yii authentication model

là một thành phần ứng dụng, người sử dụng, trong đó, trong trường hợp chung nhất, là một đối tượng thực hiện giao diện IWebUser. Các lớp học cụ thể được sử dụng bằng cách thực hiện mặc định của chúng tôi là lớp khung, CWebUser. Thành phần này người sử dụng đóng gói tất cả các thông tin nhận dạng cho người sử dụng hiện tại của ứng dụng. Thành phần này đã được cấu hình cho chúng ta như là một phần của mã ứng dụng tự động tạo ra khi chúng tôi bước đầu tạo ra ứng dụng của chúng tôi sử dụng công cụ yiic. Cấu hình có thể được nhìn thấy trong các tập tin được protected / config / main.php 'user'=>array(

// enable cookie-based authentication 'allowAutoLogin'=>true,

),

Vì nó là cấu hình như một thành phần ứng dụng, với key(user) , chúng ta có thể truy cập nó ở bất kỳ nơi nào trong suốt ứng dụng của chúng tôi bằng cách sử dụng Yii:: app () -> user.

Chúng ta thấy rằng allowAutoLogin, đang được thiết lập ở đây là khá ổn. Thiết lập này là false theo mặc định, nhưng việc thiết lập nó là true cho phép thông tin người dùng được lưu trữ trong các cookie của trình duyệt liên tục. Những thông tin này sau đó được sử dụng để tự động xác thực người dùng khi lần ghé thăm sau này. Đây là những gì sẽ cho phép chúng ta có một tài khoản Ghi nhớ hộp kiểm trên các hình thức đăng nhập để, nếu người dùng lựa chọn, họ có thể được tự động đăng nhập vào ứng dụng khi lần ghé thăm sau để vào trang web.

Khung xác thực Yii định nghĩa một thực thể riêng biệt để nhà logic thẩm định thực tế. Điều này được gọi là một lớp học nhận dạng, và trong hình thức chung nhất của nó là một lớp mà thực hiện các giao diện

IUserIdentity. Một trong những vai trò chính của lớp này là để đóng gói logic xác thực dễ dàng cho phép triển khai khác nhau. Tùy thuộc vào yêu cầu ứng dụng, chúng tôi có thể cần phải xác nhận một tên người dùng và mật khẩu đối với giá trị được lưu trữ trong một cơ sở dữ liệu, hoặc cho phép người dùng đăng nhập với OpenID thông tin của họ, hoặc tích hợp với một phương pháp tiếp cận LDAP hiện có. Tách logic đó là cụ thể phương pháp xác thực từ phần còn lại của quá trình đăng nhập ứng dụng cho phép chúng ta dễ dàng chuyển đổi giữa hiện thực như vậy.

(32)

Vào protected/components/UserIdentity.php

Xem qua nội dung của Identity ta thấy việc thực hiện này chỉ đơn giản là sử dụng tên đăng nhập / mật khẩu mã hóa cứng các giá trị của bản demo / demo và quản trị admin /. Nó kiểm tra các giá trị đối với tên người dùng và các thuộc tính của lớp mật khẩu (tài sản quy định tại các lớp cha mẹ, CUserIdentity) và nếu họ không phù hợp, nó sẽ thiết lập và trả về một mã lỗi thích hợp.

Mô hình hoạt động của quá trình đăng nhập được mô tả như sau:

Để hiểu rõ hơn về những mảnh phù hợp với toàn bộ quá trình xác thực end-to-end, chúng ta hãy đi qua các logic bắt đầu với hình thức đăng nhập. Nếu chúng ta điều hướng đến trang đăng nhập: http://localhost/demo/index.php?r=site/login, chúng ta thấy một hình thức đơn giản cho phép đầu vào của một tên người dùng, mật khẩu và tùy chọn hộp kiểm cho các tài khoản Ghi nhớ Thời gian Tiếp theo chức năng mà chúng tôi thảo luận trước khi. Trình đơn này gọi logic trong SiteController:: actionLogin () phương pháp. Sơ đồ trình tự sau đây mô tả sự tương tác lớp xảy ra trong quá trình đăng nhập thành công từ thời điểm này dưới hình thức

được gửi.

Quá trình bắt đầu với việc thiết lập các thuộc tính lớp học về mô hình hình thức,

LoginForm, với các giá trị hình thức trình. LoginForm-> phương thức validate () sau đó được gọi, trong đó xác nhận các giá trị thuộc tính dựa trên các quy tắc quy định trong phương pháp quy định (). Phương pháp này được quy định như sau:

(33)

{

return array(

// username and password are required array('username, password', 'required'), // rememberMe needs to be a boolean array('rememberMe', 'boolean'), // password needs to be authenticated array('password', 'authenticate'), );

}

Cuối cùng của các quy tắc này quy định rằng thuộc tính mật khẩu được xác nhận bằng cách sử dụng các tùy chỉnh phương pháp authenticate (), cũng được định nghĩa trong lớp LoginForm như sau:

/**

* Authenticates the password.

* This is the 'authenticate' validator as declared in rules(). */

public function authenticate($attribute,$params) {

$this->_identity=new UserIdentity($this->username,$this->password); if(!$this->_identity->authenticate())

$this->addError('password','Incorrect username or password.'); }

Tiếp tục thực hiện theo các sơ đồ trình tự, xác nhận mật khẩu trong LoginForm cuộc gọi authenticate () phương pháp trong cùng một lớp. Phương pháp này tạo ra một thể hiện mới của lớp danh tính xác thực được sử dụng, trong trường hợp này là / protected/ component/ UserIdentity.php bảo vệ, và sau đó gọi xác thực của nó authenticate (). UserIdentity :: authenticate () như sau:

/**

* Authenticates the password.

* This is the 'authenticate' validator as declared in rules(). */

public function authenticate($attribute,$params) {

(34)

if(!$this->hasErrors()) // we only want to authenticate when no input errors { $identity=new UserIdentity($this->username,$this->password); $identity->authenticate(); switch($identity->errorCode) { case UserIdentity::ERROR_NONE: $duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days Yii::app()->user->login($identity,$duration); break; case UserIdentity::ERROR_USERNAME_INVALID: $this->addError('username','Username is incorrect.'); break; default: // UserIdentity::ERROR_PASSWORD_INVALID $this->addError('password','Password is incorrect.'); break; } } }

Điều này được thực hiện để sử dụng tên người dùng và mật khẩu để thực hiện xác thực của nó. Trong việc thực hiện này, miễn là sự kết hợp tên người dùng / mật khẩu là một trong hai bản demo / demo hoặc admin / admin, phương pháp này sẽ trở lại đúng sự thật. Khi chúng ta đang đi qua một đăng nhập thành công, chứng thực thành công và đăng nhập () phương pháp trên các thành phần ứng dụng người dùng.

THAY ĐỔI QUÁ TRÌNH THỰC HIỆN XÁC THỰC

Bây giờ chúng ta hiểu toàn bộ quá trình xác thực, chúng ta có thể dễ dàng nhìn thấy nơi mà chúng ta cần phải thực hiện thay đổi để sử dụng bảng tbl_user của chúng tôi để xác nhận tên người dùng và các thông tin mật khẩu được cung cấp theo hình thức đăng nhập. Chúng ta có thể thay đổi authenticate() trong class Useridentity để xác minh sự tồn tại của một hàng phù hợp với tên người dùng cung cấp và giá trị mật khẩu. Kể từ khi, vào lúc này, có không có gì khác trong class UserIdentity.php ngoại trừ authenticate method, chúng ta hãy thay thế hoàn toàn các nội dung của tập tin này với các mã sau đây:

(35)

<?php /**

* UserIdentity represents the data needed to identity a user.

* It contains the authentication method that checks if the provided * data can identify the user.

*/

class UserIdentity extends CUserIdentity {

private $_id; /**

* Authenticates a user using the User data model. * @return boolean whether authentication succeeds.

*/

public function authenticate() { $user=User::model()->findByAttributes(array('username'=>$this->username)); if($user===null) { $this->errorCode=self::ERROR_USERNAME_INVALID; } else { if($user->password!==$user->encrypt($this->password)) { $this->errorCode=self::ERROR_PASSWORD_INVALID; } else { $this->_id = $user->id; if(null===$user->last_login_time) { $lastLogin = time(); } else { $lastLogin = strtotime($user->last_login_time); }

>setState('lastLoginTime', $lastLogin); $this->errorCode=self::ERROR_NONE;

} }

return !$this->errorCode; }

public function getId() {

(36)

return $this->_id; }

}

Chúng ta đã thiết lập một thuộc tính mới vào class UserIdentity cho ID người dùng. Việc thực hiện mặc định trong các lớp cha mẹ là để trả lại tên người dùng cho ID. Như chúng ta đang sử dụng một cơ sở dữ liệu, và có các phím số tiểu nhận dạng người dùng duy nhất, chúng ta phải chắc chắn rằng ID số này là những gì được thiết lập và trả lại trong suốt các ứng dụng khi các ID người dùng được yêu cầu. Đó là, khi các mã: Yii:: app () -> user-> id được thực thi, chúng ta phải đảm bảo rằng ID duy nhất từ cơ sở dữ liệu được trả về, không phải tên người dùng.

KẾ THỪA Ứng dụng các thuộc tính User

Điều thứ hai xảy ra ở đây là các thiết lập của một thuộc tính trên User Identity là thời gian đăng nhập cuối cùng trở về từ cơ sở dữ liệu. Thành phần ứng dụng người dùng, CWebUser, có nguồn gốc thuộc tính người dùng ID rõ ràng và các thuộc tính tên được định nghĩa trong class indentity , và sau đó từ tên => cặp giá trị trong mảng được gọi từ state identity.

chúng tôi đã thiết lập các thuộc tính có tên là lastLoginTime là giá trị của trường last_login_time trong cơ sở dữ liệu. Bằng cách này, ở bất kỳ nơi nào trong ứng dụng, thuộc tính này có thể được truy cập thông qua:

Yii:: app () -> user-> lastLoginTime;

Khi các hàng người dùng ban đầu vào bảng với các giá trị null cho thời gian đăng nhập cuối cùng,

có một kiểm tra nhanh chóng cho null để chúng tôi có thể lưu trữ một thời điểm thích hợp khi

người sử dụng các bản ghi trong thời gian đầu tiên.

Với những thay đổi này tại chỗ, bây giờ bạn sẽ cần phải cung cấp đúng tên và mật khẩu kết hợp cho một người dùng được xác định trong bảng tbl_user trong cơ sở dữ liệu. Sử dụng demo / demo hoặc admin / quản trị sẽ, tất nhiên, công việc không còn.Hãy cho nó một thử. Bạn có thể đăng nhập như bất kỳ một trong những người sử dụng mà bạn đã tạo ra trước đó trong chương này. Nếu bạn làm theo và có các dữ liệu người dùng như chúng tôi, các thông tin sau đây nên làm việc:

Tên đăng nhập: Test_User_One Mật khẩu: test1

CẬP NHẬT NGƯỜI DÙNG CÓ THỜI GIAN ĐĂNG NHẬP CUỐI CÙNG Như chúng ta đã đề cập trước đó trong chương này, chúng tôi loại bỏ thời gian đăng nhập cuối cùng như một trường đầu vào của người dùng tạo ra các hình thức, nhưng chúng tôi vẫn cần thêm logic để cập nhật lĩnh vực này. Như chúng ta đang theo dõi thời gian đăng nhập cuối cùng trong bảng cơ sở dữ liệu tbl_user, chúng ta cần phải cập nhật lĩnh vực này cho phù hợp sau khi đăng nhập thành công. Khi đăng nhập thực tế xảy ra trong LoginForm:: login () phương pháp trong lớp mô hình hình thức, chúng ta hãy cập nhật giá trị này. Thêm các dòng sau đây nhấn mạnh đến LoginForm:: login () method:

(37)

/**

* Logs in the user using the given username and password in the model. * @return boolean whether login is successful

*/

public function login() { if($this->_identity===null) { $this->_identity=new UserIdentity($this->username,$this->password); $this->_identity->authenticate(); } if($this->_identity->errorCode===UserIdentity::ERROR_NONE) { $duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days Yii::app()->user->login($this->_identity,$duration); User::model()->updateByPk($this->_identity->id, array('last_login_time'=>new CDbExpression('NOW()'))); return true; } else return false; }

Ở đây chúng ta đang kêu gọi updateByPk () phương pháp như là một cách tiếp cận hiệu quả để chỉ đơn giản là cập nhật hồ sơ User, chỉ định khóa chính cũng như một loạt các tên => cặp giá trị cho các cột mà ta muốn cập nhật.

Hiển thị lần đăng nhập cuối cùng ngoài trang chủ

Mở :

protected/views/site/index.php

<h1>Welcome to <i><?php echo CHtml::encode(Yii::app()->name); ?

></i></h1>

<?php if(!Yii::app()->user->isGuest):?>

<p>

You last logged in on <?php echo date( 'l, F d, Y, g:i a',

Yii::app()->user->lastLoginTime ); ?>.

</p>

(38)

CHƯƠNG 8 : ĐIỀU KHIỂN Sự Truy Cập của Người Dùng

Có hai phương pháp có liên quan đến kiểm soát truy cập của người dùng ví dụ trong ProjectController :, ProjectController:: filter () và ProjectController:: accessRules (). Các mã cho phương pháp đầu tiên được liệt kê như sau:

/**

* @return array action filters

*/

public function filters()

{

return array(

'accessControl', // thực hiện điều khiển truy cập cho CRUD operations

);

}

Phương thức thứ 2 được sử dụng như sau:

/**

* Specifies the access control rules.

* This method is used by the 'accessControl' filter. * @return array access control rules

*/

public function accessRules() {

return array(

array('allow', // cho phép người dùng thực hiện 'index' and 'view' actions

'actions'=>array('index','view'), 'users'=>array('*'),

),

array('allow', // cho phép chứng thực người dùng với 'create' and 'update' actions

(39)

'users'=>array('@'), ),

array('allow', // cho phép admin user thực hiện 'admin' and 'delete' actions

'actions'=>array('admin','delete'), 'users'=>array('admin'),

),

array('deny', // Từ chối truy cập 'users'=>array('*'),

), ); }

Method filter () đã quen thuộc với chúng ta. Nó là nơi mà chúng ta xác định tất cả các filter được sử dụng trong lớp điều khiển. Trong trường hợp này, chúng tôi đã chỉ có một, accessControl, trong đó đề cập đến một bộ lọc được cung cấp bởi khung Yii. Bộ lọc này sử dụng phương pháp khác, accessRules (), trong đó xác định các quy tắc điều khiển hạn chế truy cập.

Trong phương pháp accessRules () đã đề cập trước đây, có bốn quy tắc quy định. Mỗi quy tắc được thể hiện như là một mảng (array) . Yếu tố đầu tiên của mảng có thể cho phép (allow) hoặc từ chối (deny). Chỉ ra việc cấp hoặc từ chối truy cập. Phần còn lại của mảng bao gồm tên => cặp giá trị quy định cụ thể các thông số còn lại của quy tắc.

Quy tắc truy cập có thể được định nghĩa bằng cách sử dụng một số các thông số bối cảnh. Các quy tắc được đề cập trước đó xác định những hành động và người sử dụng để tạo ra bối cảnh quy tắc, nhưng có một số người khác được liệt kê như sau:

• Controller: Quy tắc này quy định cụ thể một mảng của các ID controller các quy tắc áp dụng.

• Roles: Quy tắc này quy định cụ thể danh sách các item ủy quyền

(roles,operation,premission) mà rule áp dụng. Điều này làm cho sử dụng các tính năng RBAC chúng tôi sẽ được thảo luận trong phần tiếp theo.

• Ips: Quy tắc này quy định cụ thể danh sách các địa chỉ client IP mà rule này được áp dụng.

• Verbs: Quy tắc này quy định cụ thể các loại yêu cầu HTTP (GET, POST, và như vậy) áp dụng cho quy tắc này.

• Expression: Quy tắc này quy định cụ thể một biểu thức PHP có giá trị cho thấy có hay không có quy tắc nên được áp dụng.

• Action: Quy tắc này quy định cụ thể các phương thức hành động, bằng cách sử dụng ID hành động tương ứng, mà nguyên tắc phải phù hợp với.

Users : Quy tắc này quy định cụ thể người sử dụng các quy tắc áp dụng. Thuộc tính tên người sử dụng ứng dụng hiện tại được sử dụng cho phù hợp. Ba ký tự đặc biệt cũng có thể được sử dụng ở đây:

° *: bất kỳ người dùng °: vô danh người dùng ° @: xác thực người sử dụng

References

Related documents

We provide copy of Wizard Of Oz Free Ebook in digital format, so the resources that you find are reliable. There are also many Ebooks of related with

The 35th General Council of The United Church of Canada (1994) established a “youth and young adult fund to which congregations could apply for partial financial support for

includes lack of qualified, competent and adequate personnel, lack of digital and electronic resources, lack of digital space, lack of communication with

An alternative to overcome this problem is to use an inverse identification based on simulation of drape test using the finite element method combined with a learning

What types of dyes are used for cotton, jute and flax

• A model that has made melee attacks that turn half may not afterwards charge or end any movement adjacent to another enemy.. In this example a party of heroes have opened a

By the time of Johnson's assessment the world had witnessed the attacks of 11th September 2001 (9/11) in the USA, an event which had profound significance for the subsequent

From the forensic point of view, IaaS instances provide much more information that could be used as forensic evidence in case of an incident than the PaaS and SaaS models do [6]..