P. 1
Yii 1.1 Development Cookbook - Vietnamese

Yii 1.1 Development Cookbook - Vietnamese

4.0

|Views: 781|Likes:
Published by badboyst

More info:

Published by: badboyst on Nov 29, 2012
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as DOC, PDF, TXT or read online from Scribd
See more
See less

08/28/2014

pdf

text

original

[YII 1.

1 APP DEVELOPMENT COOKBOOK ] August 28, 2012

Yii 1.1 Application Development Cookbook Public: packpub Year : 2011
http://www.seodrupal.vn Translate by : longt8x email : phamducbact1k10@gmail.com

Everything you want supported please send request to email or yahoo : taisaoemkotin_17@yahoo.com, thank you! Bạn vào trang chủ : http://www.yiiframework.com/download/ Download phiên bản mới nhất về sau đó giải nén (extract here), sau đó rename lại là cookbook, copy folder cookbook mới giải nén vào C:\xampp\htdocs\, bạn phải down xampp về rồi cài đặt setup thành công thì chạy xampp center thiết lập apache và mysql running.
http://localhost/cookbook/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\cookbook\framework". Lưu ý sửa đường dẫn cho phù hợp 153 với máy bạn nha . -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: Vào start -> run->cmd http://www.seodrupal.vn | Learn Drupal Online

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012
C:\ Cd\ Cd C:\xampp\htdocs\ C:\xampp\htdocs\>cookbook/framework/yiic webapp skybook Nếu không được thì gõ tiếp cd cookbook  Gõ tiếp cd framework -> gõ yiic webapp skybook. [skybook]-> Tên ứng dụng Create a Web application under '/Webroot/skybook'? [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:skybook/ 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 protected/ chứa các file được bảo vệ Vào cookbook/framework/ chuyển folder mới tạo là skybook ra ngoài folder website C:/xampp/htdocs. Đường dẫn mới của app là C:/xampp/htdocs/skybook. copy folder framework của cookbook sang skybook. Vào file index.php thay đổi đường dẫn thành :
$yii=dirname(__FILE__).'/framework/yii.php';

Bạn có thể truy cập vào ứng dụng từ trình duyệt http://localhost/skybook/index.php

Ok, hoàn tất cấu hình để tiến hành coder.
153

CHƯƠNG 1 -

Giới thiệu về Yii framework

1 – Sử dụng getter and setter ( Hàm nhận và hàm thiết lập).

http://www.seodrupal.vn | Learn Drupal Online

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 PHP cũng giống như các công nghệ khác như Java, C# , đều có cấu trúc lập trình hướng đối tượng và xây dựng công nghệ theo các class(lớp), yii framework được xây dựng trên nền php cũng không ngoại lệ, tuy nhiên điều khác biệt là nó kế thừa từ Ccomponent (class ảo cho bất kỳ class nào trong Yii). Cách thực hiện: Chúng ta theo dõi định nghĩa lớp trong php với hàm thiết lập (setter) và hàm nhận lại (getter)
class MyClass { private $property; // ham nhan lay giá trị public function getProperty() { return $this->property; } // ham khởi tạo giá trị public function setProperty($value) { $this->property = $value; } } // tạo mới đối tượng $object = new MyClass(); // thiết lập đối tượng $object->setProperty('value'); // trả về giá trị echo $object->getProperty(); Trong Yii chúng ta thực hiện nhờ kế thừa từ Ccomponent như sau :
// extending CComponent is necessary class MyClass extends CComponent { private $property; public function getProperty() { return $this->property; } public function setProperty($value) { $this->property = $value; } } $object = new MyClass(); $object->property = 'value'; // cũng như php : $object-> setProperty('value'); echo $object->property; // cũng như $object->getProperty();

153

Ngoài ra Yii còn hỗ trợ các hàm sau thực hiện việc thiết lập và nhận giá trị : __get, __set, __isset, và __unset

http://www.seodrupal.vn | Learn Drupal Online

Hãy nhìn vào cách chúng ta có thể kích hoạt một sự kiện xử lý từ một sự kiện.’object method’) Tạo và nhận hàm định danh sử dụng create_function như sau: Trước tiên định nghĩa component http://www.Kích hoạt một hay nhiều sự kiện xử lý. chúng ta có thể đăng ký nhiều sự kiện xử lí để thực hiện tùy theo loại sự kiện. 2012 Cách dùng như sau : vd public function __get($name) { $getter='get'.Tất cả các thể hiện xử lý được gọi tự động.$getter)) return $this->$getter().yêu cầu của bạn trước mỗi sự kiện thường là một hàm tiêu chuẩn gọi lại (standard function callback) php để sử dụng. ví dụ nếu bạn thêm onRegister method . Sử dụng các sự kiện cho phép đạt được sự linh hoạt trong ứng dụng.[YII 1. Cách thực hiện thế nào ? Để định nghĩa một sự kiện trong lớp con của Ccomponent. một thông điệp tới ứng dụng để yêu cầu thực hiện công việc nào đó. $handler: Xử lý sự kiện.Thành phần nâng cao (raise) của một sự kiện được sử dụng bởi Ccomponent ::raiseEvent method . Chúng ta sử dụng Ccomponent::attachEventHandler method.Bạn sẽ chỉ trả về giá trị array(‘Tên lớp (Name class)’.seodrupal. } 2 – Sử dụng Yii Event ( Các sự kiện trong Yii) Hầu hết các class đều được kế thừa từ Yii Component (Ccomponent) vì thế nên chúng ta có thể sử lý tốt các sự kiện từ ứng dụng. if(method_exists($this. Một sự kiện tương ứng là một lời nhắn. một hàm xử lý có thể nhận được các tham số từ các sự kiện với các tham số được định nghĩa.’Tên phương thức tĩnh(static method Name)’). .Nó chấp nhận các tham số sau đây: $name : Tên sự kiện. .vn | Learn Drupal Online 153 . Sử dụng các phương thức tĩnh từ lớp (static class method).$name. Bạn có thể thực hiện hàm gọi lại như sau : Sử dụng hàm cục bộ (global function) và chỉ nhận tên giống như các chuỗi ví dụ “ my_function”.1 APP DEVELOPMENT COOKBOOK ] August 28. Sử dụng object method : array($object. bạn sẽ nhận được tương ứng một sự kiện bạn đã khai báo. bạn sẽ thêm phương thức (method) với tên bắt đầu bằng từ “on”.Định nghĩa một sự kiện được thêm tuơng ứng một phương thức. Các loại sự kiện được sử dụng giống như : .

$component = Yii::app()->{$this->component}.function($event){echo ‘click’. Yii application có 2 sự kiện được sử lý trong các trường hợp sau . hoặc $component->onClick->add($handler). Capplication::onBeginRequest và Capplication::onEndRequest hãy sử dụng chúng . // Kích hoạt sử lý sau khi kết thúc ứng dụng Yii::app()->onEndRequest = function($event) { // releasing output buffer return ob_end_flush(). }. Để thêm một xử lý vào đầu danh sách các xử lý ta viết: $component->getEventHandlers(‘onClick’)->insertAt(0. } $component>attachEventHandler(‘onClick’.}).vn | Learn Drupal Online 153 .3 trở lên bạn chỉ cần viết: $component->attachEventHandler(‘onclick’.$handler). }.[YII 1. Ví dụ : $component->getEventHandlers(‘onClick’)->add($handler). Để code ngắn hơn bạn chỉ cần viết như sau : $component>onClick=$handler.seodrupal. Với phiên bản PHP 5.1 APP DEVELOPMENT COOKBOOK ] August 28. Để xóa một xử lý bạn sử dụng Ccomponent::detachEventHandler: $component->detachEventHandler(‘onClick’. // Kích hoạt sử lý trước khi bắt đầu ứng dụng Yii::app()->onBeginRequest = function($event) { // starting output buffering with gzip handler return ob_start("ob_gzhandler"). http://www. Đặt cấu hình thiết lập như sau vào file index. $app = Yii::createWebApplication($config).’echo “click!”)). Để quản lý việc xử lý sự kiện bạn sử dụng hàm get handler list (Clist) trong Ccomponent::getEventHandlers và làm việc với nó.create_function(‘$event’.php trước khi chạy ứng dụng: require_once($yii).$handler). 2012 public function init() { parent::init().

Chúng ta sẽ custom sự kiện NewCommentEvent để thực hiện cả post và comment model và sử lý class Notifier làm việc: Bắt đầu vào protected/components/ tạo NewCommentEvent. } // định nghĩa sự kiện onNewComment http://www. Bây giờ bạn di chuyển tới protected/models/Post. 2012 $app->run().1 APP DEVELOPMENT COOKBOOK ] August 28. public $post.seodrupal. Post là một phương thức ngoại lệ trong Gii-generated model. Comment là một tiêu chuẩn của AR model generate với Gii. $event->comment = $comment. $event->post = $this. // kích hoạt sự kiện mới 153 $this->onNewComment($event).[YII 1. return $event->isValid.php class NewCommentEvent extends CModelEvent { public $comment.vn | Learn Drupal Online . // tạo mới sự kiện từ class trước $event = new NewCommentEvent($this). Tất cả tiêu chuẩn AR method được xây dựng như sau: class Post extends CActiveRecord { function addComment(Comment $comment){ $comment->post_id = $this->id.php. } Rất đơn giản chỉ bao gồm 2 thuộc tính.

$event).[YII 1. 'comment'). } } Tiếp theo tạo trong protected/components/ file Notifier.php class Notifier { function comment($event){ $text = "Có một comment mới từ {$event->comment->author} trong post {$event->post->title}". } } Tiếp theo vào trong protected/controllers/ tạo file PostController. mail('admin@example. $comment->author = 'Sam Dark'.com'.seodrupal.php Class PostController extends Ccontroller { // tạo action thêm comment function actionAddComment() { $post = Post::model()->findByPk(10).1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online . http://www. $text). // kích hoạt sử lý sự kiện $post->onNewComment = array($notifier. $notifier = new Notifier(). 'New comment'. 2012 public function onNewComment($event) { $this->raiseEvent('onNewComment'. 153 // dữ liệu thật được dưới dạng request $_POST $comment = new Comment().

seodrupal. // thêm comment $post->addComment($comment). Ví dụ chúng ta có form model UserForm sử dụng để thu thập thông tin của người dùng và chúng ta cần hiển thị đầy đủ họ tên của user. Ta vào protected/models/ tạo file UserForm.vn | Learn Drupal Online . //tên đầy đủ public function rules() { return array( //tập hợp quy tắc : firstname. tuy nhiên nhiều trường hợp không nhất thiết phải kích hoạt sử lý sự kiện mà chúng ta cũng có thể kích hoạt sử lý sự kiện từ các component đã tồn tại và chúng ta chỉ cần overriding các class cơ bản đó .lastname được yêu cầu (k rỗng) array('firstName.[YII 1. //họ public $fullName. Thật may. Cmodel class cơ bản trong Yii model có thể mở rộng form models. 153 ).php class UserForm extends CFormModel { public $firstName. } // $event ở đây được thiết lập từ CEvent http://www.1 APP DEVELOPMENT COOKBOOK ] August 28. } } Như vậy là bạn đã biết cách kích hoạt và sử lý một sự kiện . lastName'. 2012 $comment->text = 'Yii events are amazing!'. 'required'). Cmodel::afterValidate được gọi sau khi form được submit thành công. //tên public $lastName.

Sử dụng import và autoloading Khi lập trình với php hầu hết các class và hàm tạo đều được load bởi hai phương thức là : “include” và “require”. Cấu hình Component(Thành phần) http://www.$this->lastName. vì thế mà việc load trong Yii rất nhanh.[YII 1. yii sử dụng công nghệ này vào Yii Base và việc xây dựng các lớp tiêu chuẩn trong yii CdbCriteria.1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online . 153 Hầu hết tất cả các lớp được load khi cần including hoặc importing . Tuy nhiên bạn cũng có thể sử dụng loader nhờ SPL class.seodrupal. function afterValidate() { //Nếu phương thức được gọi thì sự kiện sẽ tự động nạp dữ liệu sau: $this->fullName = $this->firstName. // điều quan trọng là nó phải được gọi lại từ lớp cha (parent class) // đó là điều giúp các sử lý sự kiện khác được gọi lại.' '. } } Chúng ta cần gọi lại từ lớp cha (parent class) của afterValidate() vì hàm định nghĩa onAfterValidate() thực chất là raiseEvent: Protected function afterValidate() { $this->onAfterValidate(new CEvent($this)). 3. Mặc định autoloader (YiiBase::autoload) sẽ được sử dụng. } 2. // CModel::afterValidate(). Yii hoàn tất bởi YiiBase::$_coreClasses map. 2012 // tạo ra và thiết lập một sự kiện( event) khi method được gọi . extension class hoặc class của bạn định nghĩa cũng được tự động load.Zii class cũng như Cmenu. return parent::afterValidate().

CDbConnection'. hầu như mọi thứ đều có thể custom một cách dễ dàng đó là ưu điểm của yii. 'connectionString'=>'mysql:host=localhost. … ).seodrupal.php Để có thể sử dụng database kết nối mysql ta chỉ cần bỏ 2 dòng /* ---.[YII 1. 2012 Yii là một framework custom.*/ để array dưới đây được kích hoạt. 'username'=>'root'. trước tiên chúng ta tìm hiểu file config của Yii trong protected/con fig /main.dbname=database_ name'. 'password'=>''. 'charset'=>'utf8'.1 APP DEVELOPMENT COOKBOOK ] August 28. Một số component trong Yii bạn nên biết : 153 http://www.vn | Learn Drupal Online .db. … ). ). return array( … 'components'=>array( 'db'=>array( 'class'=>'system. Khi đã có thể kết nối tới database rồi bạn chỉ cần khai báo Yii::app()->db. là ta đã có thể làm việc trực tiếp với CSDL.

vn | Learn Drupal Online . 2012 153 http://www.seodrupal.[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28.

class TestController extends CController { http://www.1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online . Bạn có thể truy nhập request component trong yii bằng việc sử dụng : Yii::app()>getRequest(). ispost …. getIsAjaxRequest (kiểm tra ajax loader).cung cấp thêm vấn đề bảo mật. 2012 4: Làm việc với Request Với yii bạn có thể trả về dữ liệu dưới dạng request mà php đưa ra như $_SERVER. Ví dụ chúng ta muốn kiểm tra xem aJax đã được load hay chưa ta xem ví dụ sau : class TestController extends CController { public function actionIndex() { if(Yii::app()->request->isAjaxRequest)s $this->renderPartial('test'). các method trả về khác biệt từ URL : Để chắc chắn các request được truyền đúng ta có thêm các hàm kiểm tra : IsPostRequest (Kiểm tra hàm post). getRequestType (kiểm tra request thuộc loại get hay post hay ajax).seodrupal. nhưng tốt hơn bạn nên làm theo việc sử dụng của Yii là :ChttpRequest class . quản lý cookies.$_POST.và đặc biệt là hướng đối tượng . } } 153 Ngoài ra b ạ cũng có th ạdùng các hàm thi ạ l ạ thông d ạ c ạ PHP đ ạki ạ tra nh ạ n t p ng a m isset. Vì thế nên xem một số hàm hữu ích . lớp này giải quyết những ngoại lệ từ server. else $this->render('test'). $_GET.[YII 1.

[YII 1. 153 if($cookie) // in giá trạ cookie echo $cookie->value.seodrupal. // equals to $param = isset($_POST['id']) ? $_POST['id'] : 1.vn | Learn Drupal Online . // nh ạ giá trạ ạ cookie n c a $cookie = $request->cookies['test']. $param = $request->getParam('id'. // equals to $param = isset($_GET['id']) ? $_GET['id'] : null.1 APP DEVELOPMENT COOKBOOK ] August 28. $param = $request->getPost('id'. 1). 2012 public function actionIndex() { $request = Yii::app()->request. nó tr ạv ạ t ạCcookieCollection class cho phép chúng ta làm vi ạ v ạ cookie. } } Đi ạ cu ạ cùng chúng tôi mu ạ b ạ bi ạ thêm trong ch ạạ 1 này chính là hàm u i n n t ng getCookies. 1). Vì c i CcookieCollection đ ạạk ạth ạ t ạCmap nên chúng ta có th ạs ạd ạ method sau: c a ng class TestController extends CController { public function actionIndex() { $request = Yii::app()->request. // equals to $param = isset($_REQUEST['id']) ? $_REQUEST['id'] : 1. $param = $request->getQuery('id'). else { http://www.

2012 // tạo mại cookie $cookie=new CHttpCookie('test'.$value). $cookie->expire = $expiration. $expiration=0) { $cookie=new CHttpCookie($name.vn | Learn Drupal Online . b ạ mu ạ code c ạ mình ng ạ g ạ hãy u n c i u c a n n a n n sạ dạng class sau: class Cookie { public static function get($name) { $cookie=Yii::app()->request->cookies[$name]. return $cookie->value. if(!$cookie) return null. $request->cookies['test'] = $cookie. } public static function set($name. Yii::app()->request->cookies[$name]=$cookie.'I am a cookie!'). $value. } } B ạ thay đ ạ code trong TestController nh ạsau: n i 153 class TestController extends CController { public function actionIndex() { http://www.seodrupal.1 APP DEVELOPMENT COOKBOOK ] August 28.[YII 1. } } N ạ b ạ làm vi ạ v ạ nhi ạ giá trạ ạ cookie .

Controller (Điều khiển). ch ạạ m ạ v ạ các b ạ m ạ h ạ s ạkhông th ạlàm th ạđ ạạvì không có database u ng t i n i c c đạthạ.1 APP DEVELOPMENT COOKBOOK ] August 28. if($cookie) echo $cookie.[YII 1. Cung cấp url rules ở mỗi thời điểm. xin vui lòng down source code bạn English đạtest app cạa hạ. Generating Url by path Sử dụng biểu thức quy tắc (regular expression) trong URL rules Tạo url rules cho các trang tĩnh.'I am a cookie!!').seodrupal.vn | Learn Drupal Online . 2012 $cookie = Cookie::get('test'). } } L ạ ý. else Cookie::set('test'. and views (khung nhìn) Trong chương này bạn sẽ được học: • Cấu hình quy tắc url. CHƯƠNG 2 : ROUTER (Định tuyến). Sử dụng controller cơ bản Sử dụng action cơ bản Hiển thị trang động với CViewAction Sử dụng flash messages ( Cờ thông điệp) Sử dụng controller context trong view Sử dụng clips • • • • • • 153 • • • • http://www.

php Tìm dòng sau: // application components 'components'=>array( … // uncomment the following to enable URLs in path-format /* 'urlManager'=>array( 'urlFormat'=>'path'. ). ). '<controller:\w+>/<action:\w+>'=>'<controller>/<action>'.vn | Learn Drupal Online . 'rules'=>array( '<controller:\w+>/<id:\d+>'=>'<controller>/view'. 2012 • • • Sử dụng decorator Định nghĩa nhiều layout (giao diện) Paginating and sorting data (Phân trang và sắp xếp dữ liệu) 1. Bỏ hai dấu /* và */ sau đó xóa mọi thứ trong rules để ta bắt đầu thực hành. Cấu hình quy tắc URL Trước tiên bạn vào protected/config/main. 153 'rules'=>array( ).[YII 1. '<controller:\w+>/<action:\w+>/<id:\ d+>'=>'<controller>/<action>'.1 APP DEVELOPMENT COOKBOOK ] August 28. 'urlManager'=>array( 'urlFormat'=>'path'. http://www.seodrupal. ).

php Thêm đoạn sau vào main.seodrupal. http://www.php RewriteRule ../data/testdrive.1 APP DEVELOPMENT COOKBOOK ] August 28.).'/.dirname(__FILE__). index.[YII 1. 2012 'db'=>array('connectionString'=>'sqlite:'.".htaccess trong protected như sau : Options +FollowSymLinks IndexIgnore */* RewriteEngine on # if a directory or a file exists.db'.php với dòng code sau: class WebsiteController extends CController { public function actionIndex() { echo "index". use it directly RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # otherwise forward it to index. } } Thay đổi file . Vào protected/controllers tạo websiteController. } public function actionPage($alias) { echo "Page is $alias. 'rules'=>array( 'home' => 'website/index'.vn | Learn Drupal Online .php như sau: 153 'urlManager'=>array( 'urlFormat'=>'path'.

php/page/test http://localhost/skybook/index. Nó có thể nhận về các tham số ảo từ tham số $alias trong action Page của website controller. trong Yii mỗi controller và action đều có một quy tắc chung mặc định là moduleId (tên module)/controllerID(tên controller)/actionID(tên action). ). controller website.[YII 1. 'page/<alias>' => 'website/page'. chúng ta định nghĩa một alias parameter ( tham số định danh) đặc biệt trong Url sau /page/. 2012 '<alias:about>' => 'website/page'.1 APP DEVELOPMENT COOKBOOK ] August 28. Ví dụ trong trường hợp home đó là module : default.php/home http://localhost/skybook/index. ‘page/<alias>’=>’website/page’. Ở đây bạn định nghĩa trả về tham số cho nó bằng việc thiết lập quy tắc: http://www.php/page/about Bạn sẽ thấy biến alias trong action page sẽ thay đổi tùy theo đường dẫn thứ 2 sau page bạn điền vào.vn | Learn Drupal Online . đây chính là url định danh (url alias). Thực tế điều gì đã xảy ra: Với quy tắc : ‘home’=>’website/index’ . và action là index. ). Lần lượt gõ vào trình duyệt các đường dẫn sau: http://localhost/skybook/index. 153 Ở đây .php/about http://localhost/skybook/index.seodrupal.

và một số phương thức CHtml như form. } // the rest of the methods http://www. Định dạng của quy tắc vẫn theo thứ tự : modulesID/controllerID/actionId. echo $this->createAbsoluteUrl('website/page'.Quyết định nơi chúng ta cần nó. Tham số là biến $_GET sẽ nhận một action với định tuyến đặc biệt.refresh và ajaxLink tất cả chấp nhận url và thuộc tính sử dụng trong views. 2. Array(quy tắc cục bộ. 'alias' => 'about').[YII 1. tham số => giá trị…). 153 'alias' => 'test'). đồng nghĩa với việc tham số $alias sẽ chỉ nhận được tham số ảo là about. 'name' => 'Đệt cụ bọn tàu khựa đã làm ra Yii (Quiang Xue)')).có những cách làm khác nhau nhưng cơ bản hãy nhìn một số phương thức generate url sau: CHtml::link().1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online . Một số trường hợp url sẽ được generated.tham số=>giá trị. Generating Url By Path Khi chúng ta cần generate Url của index và page action trong website controller. Trong controller bạn có thể sử dụng createUrl để tạo mới url và createAbsoluteUrl để hiển thị thong tin về url: class WebsiteController extends CController { public function actionTest() { echo $this->createUrl('website/page'. URl rất hữu ích khi sử dụng controller . 2012 ‘<alias:about>’=>’website/page’. Định dạng chung cho việc trả về dữ liệu như sau: • • Url string: Trả về đường dẫn url dạng kí tự. cho ví dụ nếu chúng ta muốn tạo một url từ websitecontroller ::actionIndex và nhận tham số $_GET[‘name’] ta chỉ cần làm như sau: echo CHtml::link('Click me!'.seodrupal. array('website/index'.

} } 153 Cấu hình lại . $name!".php mới với dòng sau: class PostController extends CController { public function actionView($alias) { echo "Showing post with alias $alias. 3.seodrupal. 'alias' => 'about'). khi bạn thực thi ứng dụng bạn có thể sử dụng method sau: echo Yii::app()->createUrl('website/page'. echo Yii::app()->createAbsoluteUrl('website/page'.". Tiếp theo vào protected/controllers tạo file PostController.vn | Learn Drupal Online . 2012 } Khi bạn không muốn hiện khởi tạo của controller . } public function actionIndex($order = 'DESC') { echo "Showing posts ordered $order.Sử dụng biểu thức quy tắc trong Url rules Ngựa quen đường cũ và gà lại thèm rượu nên ta xóa dữ liệu trong rules array(). } public function actionHello($name) { echo "Hello.[YII 1.".htaccess trong protected như sau: Options +FollowSymLinks IndexIgnore */* http://www.1 APP DEVELOPMENT COOKBOOK ] August 28. 'alias' => 'test').

php/post/test-post thành công http://localhost/skybook/index. '(posts|archive)/<order:(DESC|ASC)>' => 'post/index'.php/achive hi sinh vì index thuộc dạng số không thuộc kí tự http://localhost/skybook/index.seodrupal. 2012 RewriteEngine on # if a directory or a file exists.php RewriteRule . use it directly RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # otherwise forward it to index. ). 'sayhello/<name>' => 'post/hello'. 'rules'=>array( 'post/<alias:[-a-z]+>' => 'post/view'.[YII 1.php phần rules như sau: 'urlManager'=>array( 'urlFormat'=>'path'.php/post/test-9 hi sinh (vì hàm ngoại lệ yêu cầu dạng kí tự k phải dạng số) http://localhost/skybook/index. '(posts|archive)' => 'post/index'. ). Sau đó vào trình duyệt tự sướng: http://localhost/skybook/index.vn | Learn Drupal Online . index.php/posts/ASC thành công 153 http://www.php Tiếp theo thay đổi lại trong main.1 APP DEVELOPMENT COOKBOOK ] August 28.

'tos' => array('website/page'. lệnh sử lý đến trang đó chỉ đơn giản là controller action./contact.vn | Learn Drupal Online . 2012 4. Sử dụng controller cơ bản Đầu tiên ta vào protected/components tạo SecureController. '<alias:tos>' => 'website/page'. Lại vào main. '<alias:contact>' => 'website/page'. 6. Ta sẽ tìm một cách để tạo ra Url rules cho các thuộc tính của trang. '<alias:(about|contact|tos)>' => 'website/page'./tos. Thay đổi lại như sau: '<alias:about>' => 'website/page'.php phần rules để hót phân chó (xóa toàn bộ mọi thứ trong array của rules).php <?php 153 class SecureController extends Controller { public function filters() { http://www.1 APP DEVELOPMENT COOKBOOK ] August 28. 'defaultParams' => array('alias' => 'terms_of_service')).seodrupal.[YII 1. Tạo Url rules cho trang tĩnh Một website chứa các thuộc tính tĩnh thường là :/about.

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 return array( 'accessControl', ); } public function accessRules() { return array( array('allow', 'users'=>array('@'), ), array('deny', 'users'=>array('*'), ), ); } } Vào protected/config/ main.php tìm đoạn /* 'gii'=>array( 'class'=>'system.gii.GiiModule', 'password'=>'Enter Your Password Here', // If removed, Gii defaults to localhost only. Edit carefully to taste.
153

'ipFilters'=>array('127.0.0.1','::1'), ), */
http://www.seodrupal.vn | Learn Drupal Online

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Bỏ 2 dòng check và điền password cho gii (generated database) 'gii'=>array( 'class'=>'system.gii.GiiModule', 'password'=>'1111', 'ipFilters'=>array('127.0.0.1','::1'), ), Tiếp theo vào http://localhost/skybook/index.php/gii/default/login Điền mật khẩu là 1111 Tiếp theo chọn Controller Generator gõ SecureController

153

Nh ạ generate đ ạ t ạ controller và action index n o Đạm ạmáy nh ạl ạ gõ nhanh quá word báo : please slow character @@ t n,

http://www.seodrupal.vn | Learn Drupal Online

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012
Generate xong đạng nghĩa vại viạc bạn đã tạo xong controller SecureController , bạn có thạvào protected/controllers đạtìm thạy file này và trong views. Th ạ nhanh chóng đúng không ? ta không c ạ ph ạ m ạ công t ạ tuy nhiên @@ không t n i t o khuy ạ khích vì các d ạl ạ đòi h ạ kh ạnăng custom cao vì th ạnên chạ n n i generate models cho chóng xong, còn controller thì tạt nhạt tạ tạo file . C ạ trúc c ạ YII v ạ tuân th ạMVC, (model/views/controller) . u a n

7. Sử dụng cơ bản Action
Vào protected/config/main.php tìm đoạn sau: 'db'=>array( 'connectionString' => 'sqlite:'.dirname(__FILE__).'/../data/testdrive.db', ), // uncomment the following to use a MySQL database

'db'=>array( 'connectionString' => 'mysql:host=localhost;dbname=testdrive', 'emulatePrepare' => true, 'username' => 'root', 'password' => '', 'charset' => 'utf8', ), Thay th ạb ạ skybook ho ạ b ạ đ ạnguyên, vào localhost/phpmyadmin t ạ table testdrive ng c n o nạu bạn đạnguyên, hoạc nạu thay thạ= skybook thì tạo bạng skybook. Vào phpmyadmin vại table mại tạo vại query: CREATE TABLE `post` ( 153 `id` int(10) unsigned NOT NULL auto_increment, `created_on` int(11) unsigned NOT NULL, `title` varchar(255) NOT NULL, `content` text NOT NULL, http://www.seodrupal.vn | Learn Drupal Online

[YII 1. `username` varchar(200) NOT NULL. CREATE TABLE `user` ( `id` int(10) unsigned NOT NULL auto_increment.seodrupal.vn | Learn Drupal Online . c Tiạp theo vào GII generated 2 bạng mại tạo bạng cách chạn model generated http://www. `password` char(40) NOT NULL. 153 Nhạn go đạquery đạạ thạc hiạn.1 APP DEVELOPMENT COOKBOOK ] August 28. 2012 PRIMARY KEY (`id`) ). PRIMARY KEY (`id`) ).

)).[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28. 153 } function actionDelete($id) { http://www. array( 'posts' => $posts. Tiếp theo vào PostController viết lại như sau: class PostController extends CController { function actionIndex() { $posts = Post::model()->findAll().vn | Learn Drupal Online .seodrupal. $this->render('index'. 2012 Gõ lần lượt Post và User trong table Name rồi generated Nếu nó báo override thì vẫn generated Để kiểm tra vào protected/models sẽ tìm thấy 2 file mới tạo.

if($post->delete()) $this->redirect('post/index').[YII 1.php class DeleteAction extends CAction { function run() { if(empty($_GET['id'])) throw new CHttpException(404).seodrupal.vn | Learn Drupal Online . } 153 } Hãy sử dụng component mới này trong PostController ở actionDelete http://www. throw new CHttpException(500). if($post->delete()) $this->redirect('post/index').1 APP DEVELOPMENT COOKBOOK ] August 28. 2012 $post = Post::model()->findByPk($id). if(!$post) throw new CHttpException(404). $post = Post::model()->findByPk($_GET['id']). } } Tiếp theo vào protected/components tạo file DeleteAction. if(!$post) throw new CHttpException(404). throw new CHttpException(500).

public $modelClass.[YII 1. http://www. 2012 class PostController extends CController { function actions() { return array( 'delete' => 'DeleteAction'. ta custom lại delete action: class DeleteAction extends CAction { public $pk = 'id'.1 APP DEVELOPMENT COOKBOOK ] August 28.chúng ta sử dụng delete action trong component cho post controller nhưng vẫn còn user controller. public $redirectTo = 'index'. function run() { if(empty($_GET[$this->pk])) throw new CHttpException(404). } … } OK. if(!$model) throw new CHttpException(404). ).seodrupal.vn | Learn Drupal Online . $model = CActiveRecord::model($this->modelClass) 153 ->findByPk($_GET[$this->pk]).

).1 APP DEVELOPMENT COOKBOOK ] August 28. 2012 if($model->delete()) $this->redirect($this->redirectTo). 'modelClass' => 'Post'.seodrupal.vn | Learn Drupal Online . ). } … } Với user controller ta cũng khai báo action mới trong component class UserController extends CController { 153 function actions() { return array( http://www. throw new CHttpException(500).[YII 1. } } Bây giờ chúng ta có thể sử dụng action cho cả 2 controller .Với post controller ta làm như sau: class PostController extends CController { function actions() { return array( 'delete' => array( 'class' => 'DeleteAction'.

http://www. } … } Với cách này ta có thể tiết kiệm thời gian xây dựng hàm với những hàm có cấu trúc giống nhau.1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online . bạn luôn luôn phải đưa ra lời thong báo tới user công việc đó đã thực hiện xong chưa hay đã hoàn thành. 'Everything went fine!'). $this->redirect('index'). Sử dụng Flash Messages Khi bạn chỉnh sửa model với form.[YII 1. ).hay xóa item trong models hoặc làm với những thao tác user. 8. 'modelClass' => 'User'.…” Trở lại protected/controllers/websitecontroller viết lại như sau: class WebsiteController extends CController { function actionOk() { Yii::app()->user->setFlash('success'. 'Everything went wrong!').seodrupal. cập nhật thành công. ).…Flash messages sẽ giúp hiển thị những lời thong báo ví dụ :”xóa thành công. } 153 function actionBad() { Yii::app()->user->setFlash('error'. 2012 'delete' => array( 'class' => 'DeleteAction'.

php/website/ok http://localhost/skybook/index. 2012 $this->redirect('index'). } } Vào protected/views/website tạo index.seodrupal.php/website/bad 153 http://www.vn | Learn Drupal Online .php <?php if(Yii::app()->user->hasFlash('success')):?> <div class="flash-notice"> <?php echo Yii::app()->user->getFlash('success')?> </div> <?php endif?> <?php if(Yii::app()->user->hasFlash('error')):?> <div class="flash-error"> <?php echo Yii::app()->user->getFlash('error')?> </div> <?php endif?> Vào trình duyệt http://localhost/skybook/index.1 APP DEVELOPMENT COOKBOOK ] August 28.[YII 1. } function actionIndex() { $this->render('index').

$this->render('index').seodrupal.[YII 1. '. 2012 9. Sử dụng controller context trong views Tạo controller sau: class WebsiteController extends CController { function actionIndex() { $this->pageTitle = 'Controller context test'. 153 } } http://www.$_GET['name'].vn | Learn Drupal Online .'!'.1 APP DEVELOPMENT COOKBOOK ] August 28. } function hello() { if(!empty($_GET['name'])) echo 'Hello.

ru/'. ))? 10. <?php $this->hello()?></p> <?php $this->widget('zii.com/v/S6u7ylr0zIg?fs=1 "></ 153 param><param name="allowFullScreen" value="true"></ param><param name="allowscriptaccess" value="always"></ param><embed src="http://www.1 APP DEVELOPMENT COOKBOOK ] August 28. array('label'=>'Yiiframework home'.youtube.CMenu'.widgets.array( 'items'=>array( array('label'=>'Home'. Sử dụng lại views với partial class WebsiteController extends CController { function actionIndex() { $this->render('index').com/v/S6u7ylr0zIg?fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" http://www.youtube.php <object width="480" height="385"><param name="movie" value="http://www.[YII 1. 'url'=>'http://yiiframework. 'url'=>array('index')).seodrupal.vn | Learn Drupal Online . } } Tạo protected/views/common/youtube. ). 2012 Tạo views : <h1><?php echo $this->pageTitle?></h1> <p>Hello call.

))?> Giờ ta sẽ thử gửi email . array( 'id' => '8Rp-CaIKvQs'. // you can get this id by simply looking at video URL 'width' => 320.php <?php $this->renderPartial('////common/youtube'.1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online .them mới action trong website controller 153 class WebsiteController extends CController { function actionSendmails() { http://www.com/v/<?php echo $id?>?fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="<?php echo !empty($width) ? $width : 480?>" height="<?php echo !empty($height) ? $height: 385?>"></ embed></object> Tạo protected/website/index.[YII 1. 2012 allowfullscreen="true" width="480" height="385"></embed></object> Chỉnh sửa lại : <object width="<?php echo!empty($width) ? $width : 480?>" height="<?php echo!empty($height) ? $height: 385?>"><param name="movie" value="http://www.youtube.youtube.seodrupal. 'height' => 256.com/v/<?php echo $id?>?fs=1 "></param><param name="allowFullScreen" value="true"></ param><param name="allowscriptaccess" value="always"></ param><embed src="http://www.

$this->renderPartial ('//email/'. } function sendEmail($template. $subject. $to. Yours. array('user' => $user)). 2012 $users = User::model->findAll().seodrupal.php them đoạn sau trước output (<?php echo $content. Website team. $user->email. Welcome to the website! You can go check our new videos section.?>) <?php if(!empty($this->clips['beforeContent'])) echo $this->clips['beforeContent']?> Và them đoạn sau trước footer http://www.'.$template. } } Tiếp theo tạo protected/views/email/welcome. There are funny raccoons. } echo 'Emails were sent. $subject. $data.1 APP DEVELOPMENT COOKBOOK ] August 28. 11 . Sử dụng clip Khi chúng ta cần định nghĩa 2 vị trí trong layout : trước content và footer.php: Hello <?php echo $user->name?>.[YII 1.vn | Learn Drupal Online 153 . foreach($users as $user) { $this->sendEmail('welcome'. mở protected/views/layouts/main. true)). 'Welcome to the website!'. $data) { mail($to.

1 APP DEVELOPMENT COOKBOOK ] August 28.tuy nhiên nhiều dự án đòi hỏi cấu hình và thẩm mỹ khác nhau dẫn tới có nhiều layout khác nhau vì thế nên yii cho phép tạo dựng nhiều layout một cách chuyên biệt và hiệu quả. Mở protected/controllers/SiteController. Hầu hết ứng dụng sử dụng một layout duy nhất cho tất cả khung nhìn. mở controller action cho beforeContent region. ?> Bây giờ chúng ta cần điền vào vị trí của chúng. Ta tạo 2 layout trong protected/views/layouts: blog và articles. Blog chứa đựng nội dung sau: <?php $this->beginContent('//layouts/main')?> <div> <?php echo $content?> </div> 153 <div class="sidebar tags"> <ul> <li><a href="#php">PHP</a></li> <li><a href="#yii">Yii</a></li> http://www.php và them đoạn sau vào actionIndex: $this->beginClip('beforeContent').Yii::app()->request->userHostAddress. Định nghĩa nhiều Layout.seodrupal. $this->endClip().[YII 1. echo 'Your IP is '. <?php $this->endClip()?> Hoàn tất bạn có thể mở index bạn sẽ thấy địa chỉ IP và “ứng dụng…” ở gần footer.php và them đoạn sau: <?php $this->beginClip('footer')?> Ứng dụng được xây dựng bởi Tàu khựa. 12 . 2012 <?php if(!empty($this->clips['footer'])) Echo $this->clips['footer']. Tiếp theo mở protected/views/site/index.vn | Learn Drupal Online .

[YII 1.ArticleController và PorfolioController với indexAction class BlogController extends Controller { http://www.seodrupal. Introduction</a></li> <li><a href="#quick-start">2.net/">PHP</a></li> </ul> </div> <?php $this->endContent()?> Article chứa nội dung sau: <?php $this->beginContent('//layouts/main')?> <div> <?php echo $content?> </div> <div class="sidebar toc"> <ul> <li><a href="#intro">1.com/">Yiiframework</a></li> <li><a href="http://php.1 APP DEVELOPMENT COOKBOOK ] August 28. 2012 </ul> </div> <div class="sidebar links"> <ul> <li><a href="http://yiiframework.vn | Learn Drupal Online . Quick start</a></li> </ul> </div> <?php $this->endContent()?> 153 Tạo 3 controller là BlogController.

vn | Learn Drupal Online .[YII 1.php/article and 153 http://localhost/skybook/index. http://localhost/skybook/index.seodrupal. $this->render('//site/index').php/blog.php/portfolio.1 APP DEVELOPMENT COOKBOOK ] August 28. $this->render('//site/index'). } } Giờ hãy thử vào http://localhost/skybook/index.chúng ta thử them layout được định nghĩa http://www. } } class ArticleController extends Controller { function actionIndex() { $this->layout = 'articles'. Chúng ta vừa định nghĩa 2 layout cho blog và articles. Nếu chúng ta không muốn copy-pase một phần của layout chính. 2012 function actionIndex() { $this->layout = 'blog'. } } class PortfolioController extends Controller { function actionIndex() { $this->render('//site/index').

// sorting http://www. Vào protected/controllers/PostController. thể hiện ở hình dưới đây: 13. 2012 bằng cách sử dụng $this->beginContent và this->endContent.[YII 1. $count=Post::model()->count($criteria). sắp xếp dữ liệu theo tiêu chuẩn.php class PostController extends Controller { function actionIndex() { $criteria = new CDbCriteria(). // elements per page 153 $pages->pageSize=5.1 APP DEVELOPMENT COOKBOOK ] August 28. Phân trang và sắp xếp dữ liệu Trước khi kết thúc chương 2 ta sẽ đi vào tìm hiểu ActiveRecord với cơ chế phân trang .seodrupal. $pages->applyLimit($criteria).vn | Learn Drupal Online . $pages=new CPagination($count).

http://www.<?php echo $model->title?></h2> </li> 153 <?php endforeach?> </ol> <?php $this->widget('CLinkPager'. $models = Post::model()->findAll($criteria). $sort->attributes = array( 'id'. 'pages' => $pages.[YII 1. )). } } Tiếp theo xây dựng views: protected/views/post/index. 2012 $sort = new CSort('Post'). array( 'pages' => $pages. 'title'. 'sort' => $sort. $this->render('index'. ).vn | Learn Drupal Online .php <p><?php echo $sort->link('id')?></p> <p><?php echo $sort->link('title')?></p> <ol> <?php foreach($models as $model):?> <li> <h2><?php echo $model->id?> .seodrupal. $sort->applyOrder($criteria).1 APP DEVELOPMENT COOKBOOK ] August 28. array( 'models' => $models.

1 APP DEVELOPMENT COOKBOOK ] August 28. sau đó vào trình duyệt xem kết quả: http://localhost/skybook/post CHƯƠNG 3 • • • • • • 153 AJAX Và jQuery Trong chương này bạn sẽ khám phá: Tải một block với AJAX Quản lý asserts Including resources với page Làm việc với JSON Nhận thiết lập từ PHP và Javascript Xử lý biến số của input 1.[YII 1.seodrupal. Tải một Block với AJAX Tạo một controller mới trong protected/controllers tên QuoteController http://www.vn | Learn Drupal Online . 2012 ))?> Để thực hiện kiểm tra bạn vào phpmyadmin và thêm vào bảng post khoảng 20 item.

vn | Learn Drupal Online .s Law. even when you take into account Hofstadter&rsquo.'. array('Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. 'Hofstadter&rsquo. 2012 : <?php class QuoteController extends Controller { private $quotes = array( array('Walking on water and developing software from a specification are easy if both are frozen.'.1 APP DEVELOPMENT COOKBOOK ] August 28.'. array('It always takes longer than you expect.'.[YII 1. array('I have always wished for my computer to be as easy to use as my telephone. private function getRandomQuote() { return $this->quotes[array_rand($this->quotes. 'Rick Osborne'). my wish has come true because I can no longer figure out how to use my telephone. array('Java is to JavaScript what Car is to Carpet. 'Bjarne Stroustrup'). array( 'quote' => $this->getRandomQuote() http://www. ). } 153 function actionIndex() { $this->render('index'. 1)].'.seodrupal.s Law'). 'Chris Heilmann'). 'Edward V Berard').

seodrupal.php <h2>Quote of the day</h2> <div id="quote-of-the-day"> <?php $this->renderPartial('_quote'.[YII 1. array( 'quote' => $this->getRandomQuote(). } } Tiếp theo tạo views : protected/views/quote/index.1 APP DEVELOPMENT COOKBOOK ] August 28.. } //ajax callback function actionGetQuote() { $this->renderPartial('_quote'. array('update' => '#quote-of-the-day'))?> 153 Tạo views thứ 2 là protected/views/quote/_quote.vn | Learn Drupal Online . array('getQuote'). 2012 )). ))?> </div> <?php echo CHtml::ajaxLink('Next quote'. <?php echo $quote[1]?> http://www.php &ldquo. array( 'quote' => $quote.<?php echo $quote[0]?>&rdquo. )).

vn | Learn Drupal Online .seodrupal. nó sẽ tạo ra vấn đề.css. Khi bạn cần truy nhập lại tài sản (css. bạn có thể thay đổi widgets tới bất kì thư mục nào.image) của bạn chỉ cần combine javascript Khi bạn sử dụng assert nhiều lần trong phân trang và tránh trùng lặp Hãy bắt đầu kế hoạch trước.js. nhưng khi số lượng class tăng lên.[YII 1.info . Nó chấp nhận có một hoặc 2 class trong đó. 2012 Vào trình duyệt gõ : http://localhost/skybook/index.1 APP DEVELOPMENT COOKBOOK ] August 28.com/search?q=%s&type= http://www. Quản lý Assert Một trong những khả năng tuyệt vời của Yii là có thể bảo vệ tài sản (mã nguồn) một cách hiệu quả Khi thực thi một extension được kích hoạt javascript. 2.facebook.js Tạo EFacebookEvents. nó nằm trong protected/components. protected $url = "https://graph.php/quote/index Để có thể xem cấu hình ajax tạo ra bạn dùng firebug trỏ vào vùng next quote sẽ hiển thị javascript tạo ra ajax từ Chtml::ajaxLink.images thì folder gốc không thể truy nhập được từ trình duyệt.gif bạn vui lòng download tại http://ajaxload.Tạo một assert trong widget với protected/extensions/facebook_events.và đặt trong đó ajax-loader.php trong folder facebook_events <?php class EFacebookEvents extends CWidget 153 { public $keyword. private $loadingImageUrl.css và facebook_event. Tiếp theo tạo facebook_event.

vn | Learn Drupal Online . $cs->registerCoreScript("jquery"). urlencode($this->keyword)). //thiet lap duong dan toi file css $cs->registerCssFile( Yii::app()->assetManager->publish( $assetsDir. // thiet lap duong dan toi file images // asset can be accessed with http://www.'/facebook_events.seodrupal. CClientScript::POS_END ). } public function init() { // khoi tao duong dan file assets $assetsDir = dirname(__FILE__). $cs = Yii::app()->getClientScript().css' 153 ) ).'/assets'.[YII 1. // thiet lap duong dan toi file js $cs->registerScriptFile( Yii::app()->assetManager->publish( $assetsDir. protected function getUrl() { return sprintf($this->url. 2012 event&callback=?".js' ).'/facebook_events.1 APP DEVELOPMENT COOKBOOK ] August 28.

http://www. } public function run() { $this->render("body".seodrupal.1 APP DEVELOPMENT COOKBOOK ] August 28.each(function(){ var url = $(this).data("url").'/ajax-loader. 2012 $this->loadingImageUrl = Yii::app()->assetManager->publish( $assetsDir.js : 153 jQuery(function($){ $(".[YII 1. } } Tiếp theo vào protected/extensions/facebook_events/ tạo views/body. )).vn | Learn Drupal Online .data". var container = $(". 'loadingImageUrl' => $this->loadingImageUrl.facebook-events"). array( 'url' => $this->getUrl(). 'keyword' => $this->keyword.php <div class="facebook-events" data-url="<?php echo $url?>"> <h2><?php echo $keyword?> events</h2> <div class="data"> <?php echo CHtml::image($loadingImageUrl)?> </div> </div> Tiếp theo vào file facebook_events.gif' ). this)..

container. }). } . float: left. Vào file facebook_events.facebook-events ul { padding: 0. width: 400px.location "</p></li>". border: 1px solid #ccc.facebook-events { padding: 10px.css: .[YII 1.function(){ html += "<li>"+ "<p><strong>" + this. }). }).data. 153 } . html += "</ul>".seodrupal. 2012 $.1 APP DEVELOPMENT COOKBOOK ] August 28.each(json.html(html).vn | Learn Drupal Online . $.function(json){ var html = "<ul>".name + "</strong> </p><p>"+this. http://www.facebook-events li { list-style: none.getJSON(url. }).

[YII 1. } Vào protected/views/site/index. 2012 padding: 10px. array( 'keyword' => 'php'.EFacebookEvents". ))?> <?php $this->widget("ext.EFacebookEvents".php <?php $this->widget("ext.1 APP DEVELOPMENT COOKBOOK ] August 28. array( 'keyword' => 'jquery'. ))?> Giờ vào trang chủ để xem kết quả: 153 Cách thức hoạt động: http://www. margin: 2px.facebook_events.seodrupal.vn | Learn Drupal Online .facebook_events.

2012 Khi chúng ta sử dụng $this->widget trong site/index view. Tên của thư mục là một hàm băm mã hóa path assert directory.Trước đó assert từ mỗi thư mục được copy tới cùng một nơi.css.js").vn | Learn Drupal Online .seodrupal.com/css/main.css'). Yii::app()->clientScript->registerCssFile('http://example.điều này nghĩa là thư mục image. Đối với CSS. http://www. sau đó chạy render html.com/js/main. 'application/rss+xml'. padding: 0}'. Cách thức như : Yii::app()->clientScript->registerScriptFile("http://example.css.Including resource tới trang Yii có tên class đặc biệt là CClientScript để giúp cho việc include script css.1 APP DEVELOPMENT COOKBOOK ] August 28. 3.js từ các đường dẫn lien quan. Những gì có trong thư mục :Assert Nếu bạn kiểm tra sẽ thấy những dòng sau: Thư mục như 1a6630a0 được sử dụng để ngăn chặn va chạm của các tập tin với những cái tên tương tự từ các thư mục khác nhau. Đối với core jquery: Yii::app()->clientScript->registerCoreScript('jquery'). 'body {margin: 0.[YII 1. Yii::app()->registerCss('myCSS'. 2 phương thức trong EFacebookEvents đều chạy init cái mà public assert và kết nối chúng tới trang.'all').js public của bạn có thể tham chiếu tới images. Đăng ký linker resources: 153 Yii::app()->clientScript->registerLinkTag( 'alternate'.

Sau khi thành công kiểm tra tại protected/models xem đã có file new chưa ? Vào protected/controllers tạo NewsController. là sử dụng định dạng AJAX application data.[YII 1. 2012 $this->createUrl('rss/articles') ). 'Content-Type').php <?php class NewsController extends Controller { 153 //tao bo loc. Đầu tiên ta vào phpmyadmin và tạo mới table : Tin tức: CREATE TABLE `news` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT. `title` varchar(255) NOT NULL. Làm việc với JSON JSON rất đơn giản. bạn gõ news và nhấn generated.dễ sử dụng.seodrupal.YII cũng có làm việc với nó.vn | Learn Drupal Online . PRIMARY KEY (`id`) ) Tiếp theo bạn vào GII rồi gererated Model. null.charset=utf-8'.1 APP DEVELOPMENT COOKBOOK ] August 28. Đăng ký metaTag: Yii::app()->clientScript->registerMetaTag(' text/html. `created_on` int(11) unsigned NOT NULL. public function filters() { http://www. 4.

$news->title = "Item #". 2012 return array( 'ajaxOnly + data'. } public function actionData() { $criteria = new CDbCriteria(). ). } public function actionIndex() { $this->render('index'). } public function actionAddRandomNews() { $news = new News().vn | Learn Drupal Online .[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28. echo "OK". $news->created_on = time(). $criteria->limit = 10. 153 $news->save().seodrupal. $news = News::model()->findAll($criteria). } } http://www.rand(1. echo CJSON::encode($news). 10000). $criteria->order = 'created_on DESC'.

vn | Learn Drupal Online .news-list').seodrupal. cache: false. } updateNews().php <div class="news-list"> Loading… </div> <?php Yii::app()->clientScript->registerCoreScript("jquery")?> <script type="text/javascript"> jQuery(function($) { var newsList = $('. http://www.each(function(){ out+="<li>"+this. function updateNews(){ newsList. out += "</ol>". $. dataType: 'json'.[YII 1.title+"</li>".html(out). 2012 Tiếp theo bạn tạo views: protected/views/news/index. $(data).1 APP DEVELOPMENT COOKBOOK ] August 28. }).html("Loading…").ajax({ url: "<?php echo $this->createUrl('data')?>". 153 } }). newsList. success: function(data) { var out = "<ol>".

2000). }).1 APP DEVELOPMENT COOKBOOK ] August 28. </script> Sau thực hiện xong vào trình duyệt gõ: http://localhost/skybook/index.nơi bạn có thể them một hoặc nhiều chức năng trong danh sách task.một chức năng quản lý ứng dụng có thể cung cấp hình ảnh.bạn có thể xem ví dụ dưới đây: 153 http://www.[YII 1.seodrupal.php/news/index 5: Xử lí biến số của input Đôi khi ứng dụng yêu cầu nhập form chứa biến số của input.vn | Learn Drupal Online . 2012 setInterval(function(){ updateNews() }.

// tieu de khong rong array('text'. 'required'). 'safe').[YII 1. 2012 Bởi mặc định. public $text. trang sẽ hiển thị một vài chức năng và hai button: Add task sẽ them thuộc tính và save là lưu lại thong tin của form. public function rules() //thiet lap quy tac { return array( array('title'.vn | Learn Drupal Online .php: <?php class Task extends CFormModel { public $title. Ta sẽ tạo protected/models file Task. //text duoc bao ve 153 ).1 APP DEVELOPMENT COOKBOOK ] August 28.seodrupal. } } http://www.

if($model->validate()) $models[] = $model. 2012 Tiếp theo vào protected/controllers/TaskController. } public function actionIndex() { $models = array().seodrupal.php <?php class TaskController extends Controller { public function filters() { return array( 'ajaxOnly + field' ). $model->setAttributes($taskData).[YII 1.vn | Learn Drupal Online . } 153 } if(!empty($models)){ // Neu ban muon luu lai du lieu co the luu tai day } http://www. if(!empty($_POST['Task'])) //kiem tra co request post hay k { foreach($_POST['Task'] as $taskData) { $model = new Task().1 APP DEVELOPMENT COOKBOOK ] August 28.

'index' => $index. 'index' => $i. )). ))?> <?php endfor ?> http://www.php <div class="form"> <?php echo CHtml::beginForm()?> <ul class="tasks"> <?php for($i=0.seodrupal. $i<count($models). array( 'model' => $model. )). } } Ta tạo view: protected/views/task/index.[YII 1. } public function actionField($index) { $model = new Task().1 APP DEVELOPMENT COOKBOOK ] August 28. $this->render('index'. $i++):?> <?php $this->renderPartial('_task'. 2012 else $models[] = new Task(). array( 153 'model' => $models[$i]. array( 'models' => $models. $this->renderPartial('_task'.vn | Learn Drupal Online .

tasks").tasks li").[YII 1. 2012 </ul> <div class="row buttons"> <?php echo CHtml::button('Add task'. dataType: 'html' }).seodrupal.vn | Learn Drupal Online .size() }.1 APP DEVELOPMENT COOKBOOK ] August 28.ajax({ success: function(html){ $(". }). data: { index: $(".append(html). type: 'get'.click(function(){ $. url: '<?php echo $this->createUrl('field')?>'. array('class' => 'tasks-add'))?> <?php Yii::app()->clientScript->registerCoreScript ("jquery")?> <script> $(". cache: false. </script> 153 <?php echo CHtml::submitButton('Save')?> </div> <?php echo CHtml::endForm()?> </div> http://www.tasks-add"). }.

seodrupal. "[$index]text")?> </div> </li> Vào trình duyệt gõ http://localhost/skybook/task/index để xem kết quả.[YII 1. "[$index]title")?> <?php echo CHtml::activeTextField($model. CHƯƠNG 4 Chương này bạn sẽ khám phá: 153 LÀM VIỆC VỚI FORM • • • Uploading files Thêm Captcha Custom Captcha http://www. 2012 Cuối cùng tạo views cho partial: protected/views/task/_task.vn | Learn Drupal Online .1 APP DEVELOPMENT COOKBOOK ] August 28. "[$index]title")?> </div> <div class="row"> <?php echo CHtml::activeLabel($model.php <li> <div class="row"> <?php echo CHtml::activeLabel($model. "[$index]text")?> <?php echo CHtml::activeTextArea($model.

php <?php class UploadController extends Controller { function actionIndex() { 153 $dir = Yii::getPathOfAlias('application. public function rules() { return array(//yeu cau thuoc tinh file có thể them các thuộc tính khác cách nhau dấu //phẩy array('file'.php <?php class Upload extends CFormModel { public $file.seodrupal.[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28. //goi model http://www. $model=new Upload(). //hien thi duong dan upload $uploaded = false. 'types'=>'zip'). vì vậy sẽ tạo protected/models/Upload. 2012 • Tạo một custom widget với Cwidget 1. 'file'.vn | Learn Drupal Online . } } Trong protected/controllers tạo UploadController. ).uploads'). Uploading files Trong folder protected bạn tạo một thư mục mới có tên: uploads Chúng ta sẽ bắt đầu với model.

$file->getName()). )). if($model->validate()){ //validate form thanh cong thi luu file do vao thu muc $uploaded = $file->saveAs($dir.[YII 1.'post'. Check <?php echo $dir?>. 'file')?> 153 <?php echo CHtml::activeFileField($model.seodrupal.array ('enctype'=>'multipart/form-data'))?> <?php echo CHtml::error($model. } } $this->render('index'.'file'). 2012 if(isset($_POST['Upload'])) { $model->attributes=$_POST['Upload'].'/'. } } Tiếp theo ta tạo views: protected/views/upload/index.vn | Learn Drupal Online . duong dan 'model' => $model.</p> <?php endif ?> <?php echo CHtml::beginForm(''.php/upload/index http://www. 'uploaded' => $uploaded. array( //hien thi thong tin ten file. 'dir' => $dir. $file=CUploadedFile::getInstance($model.php <?php if($uploaded):?> <p>File was uploaded.1 APP DEVELOPMENT COOKBOOK ] August 28. 'file')?> <?php echo CHtml::submitButton('Upload')?> <?php echo CHtml::endForm()?> Vào trình duyệt gõ: http://localhost/skybook/index.

seodrupal.[YII 1. 'email'). function rules(){ return array( array('email'.vn | Learn Drupal Online . ). 2012 2. } } Tạo protected/controller/EmailController. Thêm Captcha Tạo protected/models/EmailForm.php 153 <?php class EmailController extends Controller { public function actionIndex() http://www.php <?phpclass EmailForm extends CFormModel { public $email.1 APP DEVELOPMENT COOKBOOK ] August 28.

'email')?> <?php echo CHtml::activeTextField($model. if(!empty($_POST['EmailForm'])) { $model->setAttributes($_POST['EmailForm']).[YII 1.vn | Learn Drupal Online . 'success' => $success.php <?php if($success):?> <p>Success!</p> <?php endif?> 153 <?php echo CHtml::beginForm()?> <p> <?php echo CHtml::activeLabel($model. if($model->validate()) { $success = true. $model = new EmailForm().1 APP DEVELOPMENT COOKBOOK ] August 28. } } Tạo views: protected/email/index. array( 'model' => $model. 2012 { $success = false. 'email')?> http://www. // handle form here } } $this->render('index'. )).seodrupal.

php <?php class MathCaptchaAction extends CCaptchaAction { 153 protected function generateVerifyCode() { return mt_rand((int)$this->minLength. 'email')?> </p> <p> <?php echo CHtml::submitButton()?> </p> <?php echo CHtml::endForm()?> Vào http://localhost/skybook/index.php/email/index test 3.Custom Captcha Ta có thể custom captcha một cách dễ dàng nhờ CCaptchaAction Trong protected/components tạo MathCaptchaAction. 2012 <?php echo CHtml::error($model.1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online . (int)$this->maxLength).[YII 1. http://www.seodrupal.

if($op) return $code-$rand. $rand = mt_rand(1. 1).vn | Learn Drupal Online .»-».$rand.»+». else return $code+$rand. $op = mt_rand(0.$rand. } } Trong controller trước them action sau: public function actions() { return array( 'captcha'=>array( 'class'=>'MathCaptchaAction'. http://www. 153 'minLength' => 1. 2012 } public function renderImage($code) { parent::renderImage($this->getText($code)).1 APP DEVELOPMENT COOKBOOK ] August 28. 'maxLength' => 10.seodrupal. ). } protected function getText($code) { $code = (int)$code. $code-1).[YII 1. ).

public $attributeTo. public $valueTo. public $nameTo.seodrupal. 2012 } Ta có kết quả: 4.php <?php class RangeInputField extends CInputWidget { public $attributeFrom.[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28. Tạo một custom input widget với CInputWidget Trong protected/components tạo RangeInputField. 153 public $valueFrom.vn | Learn Drupal Online . function run() http://www. public $nameFrom.

2012 { if($this->hasModel()) { echo CHtml::activeTextField ($this->model.vn | Learn Drupal Online . $this->attributeTo). '. } } } Tiếp theo vào protected/models RangeForm. http://www. public $to. echo CHtml::textField($this->nameTo. echo CHtml::activeTextField ($this->model. $this->valueFrom). $this->attributeFrom). 153 function rules() { return array( array('from.1 APP DEVELOPMENT COOKBOOK ] August 28.php <?php class RangeForm extends CFormModel { public $from. 'numerical'. echo ' &rarr. } else { echo CHtml::textField($this->nameFrom. $this->valueTo). echo ' &rarr.seodrupal. to'.[YII 1. 'integerOnly' => true). '.

'skipOnError' => true).vn | Learn Drupal Online . 'operator' => '<='. $model = new RangeForm(). } } Tiếp theo vào protected/controllers tạo RangeController. 'success' => $success. 'compareAttribute' => 'to'. 153 )). } $this->render('index'. 'compare'.[YII 1. } } Tiếp theo vào protected/views/ tạo range/index. if($model->validate()) $success = true.1 APP DEVELOPMENT COOKBOOK ] August 28.php <?php class RangeController extends Controller { function actionIndex() { $success = false. array( 'model' => $model.php http://www.seodrupal. ). if(!empty($_POST['RangeForm'])) { $model->setAttributes($_POST['RangeForm']). 2012 array('from'.

2012 <?php if($success):?> <p>Success!</p> <?php endif?> <?php echo CHtml::errorSummary($model)?> <?php echo CHtml::beginForm()?> <?php $this->widget('RangeInputField'. 'attributeTo' => 'to'. array( 'model' => $model. ))?> <?php echo CHtml::submitButton('Submit')?> <?php echo CHtml::endForm()?> Vào trình duyệt gõ: http://localhost/skybook/index.php/range/index 153 http://www.1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online .seodrupal.[YII 1. 'attributeFrom' => 'from'.

ActiveRecord. Nhận dữ liệu từ database 153 Hầu hết ứng dụng ngày nay đều sử dụng database.1 APP DEVELOPMENT COOKBOOK ] August 28.[YII 1. ít nhất một phần được bảo vệ bởi database.và Model Tricks Trong chương này bạn sẽ khám phá: Nhận dữ liệu từ database Sử dụng scopes để hiển thị model với các ngôn ngữ khác nhau Truy cập models field với AR Applying Markdown và HTML Hightlight code với Yii Tự động timestamp Thiết lập author tự động Thực thi các bảng kế thừa đơn Sử dụng CDbCriteria 1.dù là một website nhỏ cho tới mạng xã hội .vn | Learn Drupal Online .Yii giới thiệu 3 cách làm việc trên database: Active Record http://www.seodrupal. 2012 CHƯƠNG 5 • • • • • • • • • Database .

echo '</li>'.vn | Learn Drupal Online . films.mysql.first_name. Yii::getLogger() ->getExecutionTime()).php 153 <?php class DbController extends Controller { protected function afterAction($action) { $time = sprintf('%0.last_name.title')).1 APP DEVELOPMENT COOKBOOK ] August 28. parent::afterAction($action)."MB". echo "Time: $time. $memory = round(memory_get_peak_usage()/(1024*1024). echo '<ol>'.' '. } echo '</ol>'. 'order' => 't.$actor->last_name. memory: $memory". } public function actionAr() { $actors = Actor::model()->findAll(array('with' => 'films'.html để tải gói database về sau đó vào phpmyadmin import vào csdl Tiếp theo vào Gii tạo model actor và field tables Ta vào protected /controller tạo DbController. echo '</li>'.5f'. } public function actionQueryBuilder() { http://www.com/doc/sakila/en/sakila. foreach($actor->films as $film) { echo '<li>'. echo $film->title. t. echo '<ol>'.seodrupal.[YII 1.2). echo $actor->first_name. foreach($actors as $actor) { echo '<li>'. } echo '</ol>'. 2012 Query Builder SQL và DAO Để thực hiện bạn vào : http://dev.

actor_id = a. 2012 $rows = Yii::app()->db->createCommand() ->from('actor') ->join('film_actor'. echo '<ol>'. echo $row['title']. echo '<ol>'.last_name.title') ->queryAll(). 'actor.film_id=film_actor. actor. } } Sauk hi thực hiện xong bạn chạy trên trình duyệt và vào databse để kiểm tra dữ liệu mới tạo.title".$row['last_name']. } $lastActorName = $actorName. } public function renderRows($rows) { $lastActorName = null. http://www.[YII 1. 'film.film_id') ->order('actor. f.' '. } echo '</ol>'. } public function actionSql() { $sql = "SELECT * 153 FROM actor a JOIN film_actor fa ON fa. echo '</li>'.actor_id JOIN film f ON fa. film. $rows = Yii::app()->db->createCommand($sql)->queryAll().actor_id=film_actor. echo $actorName.film_id ORDER BY a.vn | Learn Drupal Online .first_name. if($actorName!=$lastActorName){ if($lastActorName!==null){ echo '</ol>'.last_name. echo '<li>'. $this->renderRows($rows).seodrupal.1 APP DEVELOPMENT COOKBOOK ] August 28.actor_id') ->leftJoin('film'. foreach($rows as $row) { $actorName = $row['first_name']. } echo '<li>'. echo '</li>'. a.film_id = f. $this->renderRows($rows).first_name.

`text` TEXT NOT NULL.'de'. 2012 2. Khi tới ứng dụng với nhiều ngôn ngữ. `lang` VARCHAR(5) NOT NULL DEFAULT 'en'.'Text in English').vn | Learn Drupal Online .seodrupal.thay đổi tin nhắn.'Yii Nachrichten'.định dạng ngày tháng. `title` VARCHAR(255) NOT NULL. Sau khi hoàn tất vào GII chọn model generated gõ Post vào modelname và generated Sauk hi generated bạn vào models/Post. INSERT INTO `post`(`id`.bạn cần phải thay đổi giao diện.1 APP DEVELOPMENT COOKBOOK ] August 28. CREATE TABLE IF NOT EXISTS `post` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT.php và viết lại method giống như sau: class Post extends CActiveRecord { public function defaultScope() { 153 return array( 'condition' => "lang=:lang". 'params' => array( http://www. Sử dụng Scopes để hiển thị models cho những ngôn ngữ khác nhau Đa ngôn ngữ trong website của bạn là việc điều khiển không hề dễ dàng.và rất nhiều thứ khác.'Yii news'. PRIMARY KEY (`id`) ).[YII 1.'Text in Deutsch').`text`) VALUES (1. (2. Yii giúp bạn làm việc hiệu quả hơn với CLDR (Unicode Common Locate Data Repository) dữ liệu và cung cấp công cụ thay đổi ngôn ngữ. bạn có thể sẽ tìm ra cách của riêng bạn.`title`. Để bắt đầu tạo mới databse: vào phpmyadmin và chọn mục SQL : DROP TABLE IF EXISTS `post`.'en_us'.`lang`.

'</h2>'. 'params' => array( ':lang' => $lang.vn | Learn Drupal Online .$post->title. } public function lang($lang){ $this->getDbCriteria()->mergeWith(array( 'condition' => "lang=:lang". 153 echo '<h1>Default language</h1>'. } } Tiếp theo vào protected/controllers/DbtestController.1 APP DEVELOPMENT COOKBOOK ] August 28. )). ). ). ).seodrupal.php <?php class DbtestController extends CController { public function actionIndex() { // Hiển thị ngôn ngữ mặc định $posts = Post::model()->findAll(). http://www.[YII 1. return $this. 2012 ':lang' => Yii::app()->language. foreach($posts as $post) { echo '<h2>'.

} } } Sauk hi hoàn thành vào trình duyệt gõ : http://localhost/skybook/dbtest/index 3.seodrupal. foreach($posts as $post) { echo '<h2>'. echo '<h1>German</h1>'.'</h2>'.vn | Learn Drupal Online .1 APP DEVELOPMENT COOKBOOK ] August 28. } // Hiển thị ngôn ngữ của Đức $posts = Post::model()->lang('de')->findAll(). http://www.[YII 1. 2012 echo $post->text. `title` VARCHAR(255) NOT NULL.$post->title. 153 CREATE TABLE IF NOT EXISTS `post` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT. echo $post->text. Truy cập model field với Active-Record event-like method Vào phpmyadmin chọn mục SQL và thực hiện query sau: DROP TABLE IF EXISTS `post`.

$post->text='test http://www.seodrupal. PRIMARY KEY (`id`) ).[YII 1. $this->text). 2012 `text` TEXT NOT NULL. print_r($post->text). 153 $post->save(). } } http://www. '<a href="\1">\1</a>\2'.*?)( |$)~iu'.php <?php class TestController extends CController { function actionIndex() { $post=new Post().php và thêm hàm sau: protected function beforeSave() { $this->text = preg_replace('~((?:https?|ftps?)://.vn/ test'. } Tiếp theo vào protected/controllers tạo TestController.vn | Learn Drupal Online . Tiếp theo vào Gii generated model Post Sau đó bạn vào models/Post. $post->title='links test'. return parent::beforeSave().1 APP DEVELOPMENT COOKBOOK ] August 28.đập chết mẹ tàu khựa.

beforeValidate/afterValidate: Hàm được gọi khi khởi tạo trước/sau khi validation form kết thúc.Bởi sử dụng biểu thức quy tắc. http://www.sự kiện thực tế là raised propery . Để thực hiện ta vào phpmyadmin chọn mục SQL và thực hiện query sau: CREATE TABLE `snippet` ( 153 `id` int(11) unsigned NOT NULL auto_increment. trong hàm saving bạn có thể trả về giá trị false. Highlight code với Yii Nếu bạn post code.seodrupal.công ty của bạn lien quan đến nghề báo và wiki blog.sẽ luôn luôn tốt hơn khi hệ thống có highlight (hiệu ứng nháy). `title` varchar(255) NOT NULL.vn | Learn Drupal Online . 2012 Vào tình duyệt gõ http://localhost/skybook/test/index để xem kết quả. `html` text NOT NULL.1 APP DEVELOPMENT COOKBOOK ] August 28.[YII 1. 4. và một người đọc code cũng cảm thấy thoải mái. Một số method bạn nên biết: AfterConstruct : Hàm được gọi sau khi một model được khởi tạo bởi mã nguồn beforeDelete/afterDelete : Hàm được gọi trước/sau khi bản ghi bị xóa beforeSave/afterSave: Hàm được khởi tạo trước khi/sau khi lưu bản ghi thành công. chúng thay thế mọi thứ giống một url với một link được sử dụng và gọi lại để hàm thực thi cha. Cách làm việc như sau: beforeSave (trước khi lưu) được định nghĩa trong CActiveRecord class và chỉ thực hiện hàm trước khi lưu models. `code` text NOT NULL.

code. 'length'. array('title'.[YII 1. 'max' => 20). return parent::afterValidate(). 'max'=>255). Tiếp theo vào Giii generated model Snippet Sauk hi generate thành công bạn thay đổi hàm rules trong Snippet. 'length'. 'required'). $highlighter->language = $this->language. array('language'.php public function rules() { return array( array('title. $this->html = $highlighter->highlight($this->code). language'. } Thêm method sau khi validate: protected function afterValidate() { $highlighter = new CTextHighlighter().1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online .php ở protected/models/Snippet. 2012 `language` varchar(20) NOT NULL.seodrupal. ). } 153 public function getSupportedLanguages() { return array( http://www. PRIMARY KEY (`id`) ).

vn | Learn Drupal Online . $this->render('index'. array( 'models' => $models. array( 'model' => $model. 'javascript' => 'JavaScript'.seodrupal. )).[YII 1. 153 if(!$model) throw new CException(404). $models = Snippet::model()->findAll(). } public function actionView($id) { $model = Snippet::model()->findByPk($id).1 APP DEVELOPMENT COOKBOOK ] August 28. 'html' => 'HTML'. $criteria->order = 'id DESC'. http://www. } Tiếp theo vào protected/controller tạo SnippetController. 2012 'php' => 'PHP'. ).php <?php class SnippetController extends CController { public function actionIndex() { $criteria = new CDbCriteria(). 'css' => 'CSS'. $this->render('view'.

'id' => $model->id)). if($model->save()) $this->redirect(array('view'.1 APP DEVELOPMENT COOKBOOK ] August 28. if($model->save()) $this->redirect(array('view'. 2012 )).[YII 1.seodrupal. if($data) { $model->setAttributes($data). )). http://www. $data = Yii::app()->request->getPost('Snippet'). $data = Yii::app()->request->getPost('Snippet'). array( 'model' => $model. } public function actionAdd() { $model = new Snippet().vn | Learn Drupal Online . 'id' => $model->id)). if(!$model) throw new CHttpException(404). } public function actionEdit($id){ $model = Snippet::model()->findByPk($id). if($data) 153 { $model->setAttributes($data). } $this->render('add'.

array( 'model' => $model. 'id' => $model->id))?> http://www. 2012 } $this->render('edit'. array('index'))?> → <?php 153 echo CHtml::encode($model->title)?> </h2> <?php echo CHtml::link('Edit'.php <h2><?php echo CHtml::link('Snippets'. )).seodrupal.[YII 1. array ('edit'.php <h2>Snippets</h2> <?php echo CHtml::link('Add snippet'. array('add'))?> <ol> <?php foreach($models as $model):?> <li> <?php echo CHtml::link( CHtml::encode($model->title). 'id' => $model->id) )?> </li> <?php endforeach?> </ol> Tạo tiếp view thứ 2 : protected/views/snippet/view.1 APP DEVELOPMENT COOKBOOK ] August 28. array('view'. } } Tiếp theo ta tạo view trong protected/views/snippet/index.vn | Learn Drupal Online .

php <h2><?php echo CHtml::link('Snippets'.vn | Learn Drupal Online . array('index'))?> → Add snippet </h2> <?php $this->renderPartial('_form'.php <?php echo CHtml::beginForm()?> <ul> <li> <?php echo CHtml::activeLabel($model. 'language')?> http://www.[YII 1. array('model' => $model))?> Tạo view edit: protected/views/snippet/edit.1 APP DEVELOPMENT COOKBOOK ] August 28. 'title')?> </li> <li> <?php echo CHtml::activeLabel($model. 'title')?> <?php echo CHtml::activeTextField($model. 'code')?> </li> <li> <?php echo CHtml::activeLabel($model. 'code')?> 153 <?php echo CHtml::activeTextArea($model. array('index'))?> → Edit snippet </h2> <?php $this->renderPartial('_form'.php <h2><?php echo CHtml::link('Snippets'. array('model' => $model))?> Tạo view _form : protected/views/snippet/_form.seodrupal. 2012 <div> <?php echo $model->html?> </div> Tạo view add : protected/views/snippet/add.

1 APP DEVELOPMENT COOKBOOK ] August 28.seodrupal. $model->getSupportedLanguages())?> </li> <li> <?php echo CHtml::submitButton('Save')?> </li> </ul> <?php echo CHtml::endForm()?> Sauk hi hoàn thành vào trình duyệt gõ : http://localhost/skybook/snippet/index Từ từ tận hưởng hiệu ứng: 153 5. 2012 <?php echo CHtml::activeDropDownList($model.[YII 1. Thực thi kế thừa bảng Dữ liệu quan hệ thường không hỗ trợ kế thừa . Nếu bạn muốn thực hiện kế thừa database.vn | Learn Drupal Online . bạn cũng có thể được hỗ trợ từ Yii http://www. 'language'.

vn | Learn Drupal Online . Để bắt đầu ta vào phpmyadmin chọn sql và chạy query sau: CREATE TABLE `car` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT. 'sport'). PRIMARY KEY (`id`) ). ('Kia Ceed'. 'sport'). `name` varchar(255) NOT NULL.seodrupal. http://www. Ta generated model Car trong Gii Trong Protected/models/Car. INSERT INTO `car` (`name`.1 APP DEVELOPMENT COOKBOOK ] August 28.php ta sửa lại như sau: <?php class Car extends CActiveRecord 153 { public static function model($className=__CLASS__) { return parent::model($className). 'family'). ('Porsche Boxster'. 2012 Cấu trúc kế thừa đơn giản như: Xe |-> Xe thể thao |->Xe du lịch |->Xe gia đình. ('Opel Astra'. 'family'). `type` varchar(100) NOT NULL.[YII 1. 'family'). ('Ferrari 550'. `type`) VALUES ('Ford Focus'.

1 APP DEVELOPMENT COOKBOOK ] August 28. } $model=new $class(null). } } 153 Sau đó ta kế thừa cho protected/models/SportCar. default: $class=get_class($this). return $model.seodrupal. 2012 } public function tableName() { return 'car'. case 'family': $class='FamilyCar'.php <?php class SportCar extends Car { http://www. break.vn | Learn Drupal Online .[YII 1. } protected function instantiate($attributes) { switch($attributes['type']) { case 'sport': $class='SportCar'. break.

php <?php class FamilyCar extends Car { public static function model($className=__CLASS__) { return parent::model($className). ). } } http://www. ).1 APP DEVELOPMENT COOKBOOK ] August 28.[YII 1.vn | Learn Drupal Online .seodrupal. } public function defaultScope() { return array( 'condition'=>"type='sport'". } public function defaultScope() { return array( 153 'condition'=>"type='family'". 2012 public static function model($className=__CLASS__) { return parent::model($className). } } Tiếp theo ta cũng kế thừa cho protected/models/FamilyCar.

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Trong protected/controller tạo TestController.php <?php class TestController extends CController { public function actionIndex() { echo "<h1>All cars</h1>"; $cars = Car::model()->findAll(); foreach($cars as $car) { // Mỗi chiếc xe có thể là của class car, sportcar, hoặc familycar echo get_class($car).' '.$car->name."<br />"; } echo "<h1>Sport cars only</h1>"; $sportCars = SportCar::model()->findAll(); foreach($sportCars as $car) { echo get_class($car).' '.$car->name."<br />"; } } } Xong xuôi vào trình duyệt gõ : http://localhost/skybook/test/index
153

http://www.seodrupal.vn | Learn Drupal Online

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012

6. Sử dụng CdbCriteria
Khi sử dụng Active Record method như findAll, hoặc find, chúng ta có thể nhận tiêu chuẩn giống như tham số,nó có thể trả về mảng hay một khởi tạo của CdbCriteria class.Class này hiển thị query tiêu chuẩn, giống như điều kiện,ordering by,limit/offset, vv… Thường thường nó hay được sử dụng như dưới đây: $criteria = new CDbCriteria(); $criteria->limit = 10; $criteria->order= 'id DESC'; $criteria->with = array('comments'); $criteria->compare('approved', 1); $criteria->addInCondition('id', array(4, 8, 15, 16, 23, 42)); $posts = Post::model()->findAll($criteria); Cách làm việc: Bản thân class Criteria không xây dựng query, nhưng chỉ hiển thị dữ liệu hoặc cho phép điều chỉnh chúng, Hàm làm việc thực tế nằm trong Active Record method nơi các tiêu chuẩn của class này sử dụng.
153

Dịch code có thể đọc như sau: Hiển thị 10 dòng post với comment từ approved post với id trong khoảng 4,8,15,16,24 hoặc 42 order by id.

http://www.seodrupal.vn | Learn Drupal Online

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Select * from post p (định danh post) JOIN (nối) comment c(định danh comment) ON (điều kiện nối) p.id=c.post_id where p.approval=1 and p.id in (4,8,16,15,24,42) order by p.id DESC LIMIT 10.

CHƯƠNG 6
• • • •
153

KẾ THỪA Yii

Trong chương này, bạn sẽ khám phá: Sử dụng data provides Sử dụng grids (lưới) Sử dụng lists (danh sách) Tạo custom grid column( Cột lưới)

Yii có thư viện hữu ích gọi là Zii, nó đồng hành cùng với framework và một số class khác giúp cho việc phát triển trở lên dễ dàng hơn bao giờ hết,hầu hết thành phần chủ yếu là grid và list cái cho phép bạn xây dựng dữ liệu trong Admin và user website rất nhanh và đẹp. Trong chương này bạn sẽ học cách điều chỉnh component và những thứ bạn cần,bạn sẽ học về data provides,chúng là một phần trong core framework.
http://www.seodrupal.vn | Learn Drupal Online

array( 'pagination'=>array( 'pageSize'=>10.grid.tạo protected/controllers/GridController. http://www. Bởi vì cả 2 widget và provider là một tiêu chuẩn (chuẩn mực).php <?php class GridController extends Controller { public function actionAR() { $dataProvider = new CActiveDataProvider('Film'. ) )).Chúng được sử dụng với grids và lists. Vào protected/views/ tạo grid/index. phân trang.php <?php $this->widget('zii.bạn có thể hiển thị giống như dữ liệu sử dụng khác widget và bạn có thể hiện dữ liệu cho một widget từ various provider (tài sản được cung cấp).CGridView'.[YII 1. 2012 1 Sử dụng data provides (nhà cung cấp dữ liệu) Data provides được sử dụng để triệu tập dữ liệu model giống như sắp xếp.com/doc/sakila/en/sakila.html download database sau đó import vào csdl thong qua phpmyadmin. và querying. 'sort'=>array( 153 'defaultOrder'=> array('title'=>false).1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online .mysql.seodrupal.widgets. Để thực hiện coder bạn vào http://dev. ). ))?> Sau đó. array('dataProvider' => $dataProvider. Sử dụng Gii để tạo model film.

'memberSince'=>'Jan 2008'. array( 'name'=>'Wei Zhuo'. 'forumName'=>'wei'. ). 'forumName'=>'qiang'.seodrupal. array( http://www. 'active'=>true. 153 'duty'=>'project site maintenance and development'.[YII 1. 'location'=>'Washington DC. Australia'. 'location'=>'Sydney. 'id'=>'2'.1 APP DEVELOPMENT COOKBOOK ] August 28. ). } public function actionArray() { $yiiDevelopers = array( array( 'name'=>'Qiang Xue'. 'memberSince'=>'Jan 2008'. 'active'=>true. 'id'=>'3'. USA'. 'duty'=>'founder and project lead'. array( 'dataProvider' => $dataProvider. 2012 $this->render('index'.vn | Learn Drupal Online . )).

'id'=>'415'. 'active'=>true. 'memberSince'=>'Mar 2010'. ). array( 'name'=>'Maurizio Domba'. 'forumName'=>'sebas'. 'location'=>'Russia'.1 APP DEVELOPMENT COOKBOOK ] August 28.seodrupal. 153 'location'=>'Croatia'.[YII 1. 'active'=>true. 'duty'=>'core framework development'. 'forumName'=>'mdomba'. 'forumName'=>'samdark'. ). 'active'=>true. array( 'name'=>'Alexander Makarov'.vn | Learn Drupal Online . http://www. 'id'=>'54'. 'duty'=>'component development'. 2012 'name'=>'Sebastián Thierer'. 'memberSince'=>'Aug 2010'. 'duty'=>'core framework development'. 'memberSince'=>'Sep 2009'. 'location'=>'Argentina'. 'id'=>'2650'. ).

'memberSince'=>'Sep 2010'. 'location'=>'Germany'. USA'. 'active'=>false. ). 153 'memberSince'=>'Sep 2009 . http://www. array( 'name'=>'Jeffrey Winesett'. 'id'=>'15'. 'active'=>true. 'memberSince'=>'Aug 2010'.1 APP DEVELOPMENT COOKBOOK ] August 28. 'duty'=>'component development'. array( 'name'=>'Jonah Turnquist'. 'forumName'=>'jonah'.[YII 1. 'active'=>true. 2012 array( 'name'=>'Y!!'. 'id'=>'127'. 'forumName'=>'jefftulsa'. ). 'location'=>'California.vn | Learn Drupal Online . 'location'=>'Austin. 'forumName'=>'Y!!'. TX.seodrupal.Aug 2010'. 'duty'=>'documentation and marketing'. 'id'=>'1644'. 'duty'=>'core framework development'. US'.

). array( 'sort'=>array( 'attributes'=>array('name'. 2012 ). ). ). } public function actionSQL() http://www. 'memberSince'=>'Sep 2009 . 'id'=>'1286'. )).seodrupal.vn | Learn Drupal Online .1 APP DEVELOPMENT COOKBOOK ] August 28. array( 153 'dataProvider' => $dataProvider. 'active'=>false. 'name' => false). $this->render('index'. 'id'. $dataProvider = new CArrayDataProvider( $yiiDevelopers. 'forumName'=>'pestaa'. ).[YII 1. array( 'name'=>'István Beregszászi'.Mar 2010'. 'pagination'=>array( 'pageSize'=>10. 'defaultOrder'=>array('active' => true. 'active'). )). 'duty'=>'core framework development'. 'location'=>'Hungary'.

). 'sort'=>array( 'attributes'=>array('title'). $this->render('index'. ). 2012 { $count=Yii::app()->db->createCommand('SELECT COUNT(*) FROM film')->queryScalar(). )).[YII 1. 'totalItemCount'=>$count. array( 'keyField'=>'film_id'. array( 'dataProvider' => $dataProvider. )). grid/array và grid/sql để xem kết quả: 153 http://www.seodrupal. $sql='SELECT * FROM film'. 'pagination'=>array( 'pageSize'=>10.1 APP DEVELOPMENT COOKBOOK ] August 28. $dataProvider=new CSqlDataProvider($sql.vn | Learn Drupal Online . } } Vào localhost /skybook/grid/aR . 'defaultOrder'=>array('title' => false).

mysql.1 APP DEVELOPMENT COOKBOOK ] August 28.com/doc/sakila/en/ sakila. address. 2012 2. Sử dụng Zii Grid Zii grid rất hữu ích và nhanh chóng trong việc tạo khung lưới cho các trang quản trị admin hoặc bất kỳ trang nào yêu cầu về số liệu. chọn table của bạn và import db.html.seodrupal.city. Để bắt đầu bạn vào website : http://dev. Sử dụng Gii tạo model generated cho customer.[YII 1. Tiếp theo vào Gii chọn controller generated : Customer Chạy customer controller và tới quản trị Manage Customer link trong gii bạn sẽ có kết quả như sau: 153 http://www.vn | Learn Drupal Online . down load database sau do giải nén vào phpmyadmin.

seodrupal. Vào website : http://dev.mysql. 2012 3.address.city Tiếp theo mở gii.html download cơ sở dữ liệu rồi vào phpmyadmin import vào database Vào gii model generated tạo : customer.1 APP DEVELOPMENT COOKBOOK ] August 28. Sử dụng lists Zii list là công cụ khá tốt cho việc trình bày dữ liệu ở bất kỳ data provider để kết thúc user khi xử lí phân trang và sắp xếp tự động.com/doc/sakila/en/ sakila.store.vn | Learn Drupal Online .CListView là rất dễ dàng trong việc custom vì nó cho phép xây dựng bất kỳ thuộc tính nào trong list page.chọn CRug generator và nhấn Customer tới model class field.[YII 1. nhấn preview và generated Gii sẽ generated controller trong protected/controllers Chạy index action của customer controller ta có kết quả sau : http://localhost/skybook/customer/index 153 Thêm tiêu chu ẩn s ắp x ếp: http://www.

)). 'sortableAttributes'=>array( 'last_name'.CListView'. array( 'dataProvider'=>$dataProvider. 'email'. ). 'sortableAttributes'=>array( 'last_name'.widgets. 'template' => '{sorter} {pager} {items} {sorter} {pager}'.1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online .CListView'. ?> Customer templates: Thay thế views với nội dung sau: <?php $this->widget('zii. array( 153 'dataProvider'=>$dataProvider. http://www.widgets. ). 'itemsCssClass' => 'customers'.php và thay thế bằng nội dung sau : <?php $this->widget('zii.widgets. array( 'dataProvider'=>$dataProvider.[YII 1. 'itemView'=>'_view'.CListView'. )). ?> Customer markup data display <?php $this->widget('zii. 'itemsTagName' => 'ol'. 'itemView'=>'_view'. 2012 bạn vào protected/views/customer/index.seodrupal. 'itemView'=>'_view'. 'email'.

$data->store->address->city->city.1 APP DEVELOPMENT COOKBOOK ] August 28. ?> 153 </li> <li> <strong><?php echo CHtml::encode($data-> getAttributeLabel('email')).[YII 1.'. 'template' => '{sorter} {pager} {items} {sorter} {pager}'.vn | Learn Drupal Online . '. ?>:</strong> <?php echo CHtml::encode($data->store-> address->address.$data->last_name).$data->store->address->district). 2012 'sortableAttributes'=>array( 'last_name'.php <li> <h2> <?php $title = CHtml::encode($data->first_name. array('view'. 'id'=> $data->customer_id)). echo CHtml::link($title.' '. ?> Tiếp theo vào protected/views/customer tạo _views. ?> </h2> <ul> <li> <strong><?php echo CHtml::encode($data-> getAttributeLabel('store_id')). )). 'email'. ). ?>:</strong> http://www. '.'.seodrupal.

seodrupal.vn | Learn Drupal Online . ?> </li> <li> <strong><?php echo CHtml::encode($data-> getAttributeLabel('address_id')).css ol. ?> </li> </ul> </li> Vào protected/assets tạo customer. background: #fcfcfc.[YII 1.$data->address->district).'. ?> </li> <li> <strong><?php echo CHtml::encode($data-> getAttributeLabel('active')). } ol. border: 1px solid #9aafe5. ?>:</strong> <?php echo CHtml::encode($data->address->address.customers>li { 153 margin: 1em. '.$data->address->city->city. http://www.1 APP DEVELOPMENT COOKBOOK ] August 28. margin: 1em 0.customers { list-style: none.'. ?>:</strong> <?php echo $data->active ? 'Yes' : 'No'. 2012 <?php echo CHtml::encode($data->email). padding:1em. '.

Vào protected/components/ tạo FlagColumn.vn | Learn Drupal Online . assets').mysql.'/customers. Vào GII model generated tạo : customer Mở Gii chọn CRUD generated chọn : Customer và generated 153 Cách thực hiện : Trong table chúng ta có một field active (kích hoạt) .seodrupal. chúng ta muốn toggle với flag column . Column sẽ hiển thị 2 trường Y và N quyết định giá trị trả về được cliking hay ko. 2012 } Quay lại file _views trong protected/views/customer và thêm đoạn sau vào dưới cùng <?php Yii::app()->clientScript->registerCssFile( Yii::app()->assetManager->publish(Yii::getPathOfAlias('application.com/doc/sakila/en/ sakila. Tạo customer Grid column Hầu hết thời gian bạn không cần tạo khung lưới cho các thuộc tính của bạn khi mà Yii đã cung cấp đầy đủ công cụ thực hiện vì thế nên bạn chỉ cần tạo custom cho riêng mình.1 APP DEVELOPMENT COOKBOOK ] August 28.html tải database về sau đó vào phpmyadmin import và db của bạn.php http://www. Ta bắt đầu tạo custom grid column cho phép toggling Y/N giá trị và thay đổi giá trị trong models nhờ AJAX Bạn vào : http://dev.css'))?> Thử lại trên trình duyệt bằng việc F5: 4.[YII 1.

private $_flagClass = "flag_link". public $sortable=true. $cs->registerScript(__CLASS__. $script). http://www.update('$gridId').live("click". } 153 }). url: link.1 APP DEVELOPMENT COOKBOOK ] August 28. var link = this. $script = <<<SCRIPT jQuery(". function(e){ e.preventDefault().[YII 1.$gridId. public $callbackUrl = array('flag').seodrupal. 2012 <?php class FlagColumn extends CGridColumn { public $name. $. $cs=Yii::app()->getClientScript(). public function init() { parent::init().ajax({ dataType: "json".{$this->_flagClass}").'#flag_link'. success: function(data){ $('#$gridId'). $gridId = $this->grid->getId(). cache: false.yiiGridView.vn | Learn Drupal Online . }).href. SCRIPT.

153 else echo CHtml::encode($this->name). array( 'class' => $this->_flagClass.$this->header).vn | Learn Drupal Online . else if($this->name!==null && $this->header===null) { if($this->grid->dataProvider instanceof CActiveDataProvider) echo CHtml::encode($this->grid->dataProvider-> model->getAttributeLabel($this->name)). )). } protected function renderHeaderCellContent() { if($this->grid->enableSorting && $this->sortable && $this->name!==null) echo $this->grid->dataProvider->getSort()->link( $this->name. $link = CHtml::normalizeUrl($this->callbackUrl). } else http://www.seodrupal. $this->callbackUrl['pk'] = $data->primaryKey.[YII 1. $this->callbackUrl['value'] = (int)empty($value). $data) { $value=CHtml::value($data. 2012 } protected function renderDataCellContent($row. $link.1 APP DEVELOPMENT COOKBOOK ] August 28. echo CHtml::link(!empty($value) ? 'Y' : 'N'. $this->callbackUrl['name'] = urlencode($this->name).$this->name).

'filter'=>$model. 'dataProvider'=>$model->search(). $model->{$name} = $value.vn | Learn Drupal Online .1 APP DEVELOPMENT COOKBOOK ] August 28.php và thay đổi action Flag public function actionFlag($pk. 'columns'=>array( 'customer_id'.widgets. } } Cuối cùng vào protected/views/customer/admin. 'store_id'. $model->save(false).[YII 1. 'last_name'.grid.seodrupal. 'address_id'. 2012 parent::renderHeaderCellContent(). } } Tiếp theo vào protected/controllers/CustomerController. $name.php Thay đổi dòng widget: <?php $this->widget('zii. if(!Yii::app()->request->isAjaxRequest){ $this->redirect('admin'). $value){ $model = $this->loadModel($pk). array( 'id'=>'customer-grid'. 'email'.CGridView'. http://www. 153 'first_name'.

). */ array( 'class'=>'CButtonColumn'. CRUD hiện lên.vn | Learn Drupal Online .1 APP DEVELOPMENT COOKBOOK ] August 28. đệt mợ tàu khựa. )). ).seodrupal. /* 'create_date'. 'last_update'.[YII 1. customer thật dễ dàng đúng ko  . http://www. 2012 array( 'class' => 'FlagColumn'. ?> Sau k hi thành công vào Http://localhost/skybook/customer/admin 153 Bạn đã có thể thấy một loạt công cụ kích hoạt. 'name' => 'active'. ).

Sau đó một component có thể kích hoạt tới ứng dụng và cấu hình sử dụng trong protected/config/main.vn | Learn Drupal Online .php. protected $width. Để ví dụ chúng ta định nghĩa: EImageManage ứng dụng thành phần sẽ dùng để resize ảnh sử dụng thư viện GD.behavior hãy sử dụng component. http://www. kích hoạt nó tới ứng dụng và sử dụng nó.seodrupal.widget. Tạo component Nếu bạn có một vài đoạn code có thể tái sử dụng được nhưng bạn không biết cách thức.1 APP DEVELOPMENT COOKBOOK ] August 28.php <?php class EImageManager extends CApplicationComponent 153 { protected $image. Vào protected/components tạo EImageManage.[YII 1. Component kế thừa từ CComponent hoặc CApplicationComponent. protected $height. 2012 CHƯƠNG 7 Trong chương này bạn sẽ khám phá: • • • • • • • • • Tạo component Tạo controller action Tạo reusable controller Tạo một widget Tạo CLI commands Tạo filter Tạo modules Tạo một customer view renderer Làm mở rộng distribution-ready KẾ THỪA Yii 1.

} public function load($filePath) { list($this->width. $height = false){ if($width!==false) $this->newWidth = $width. 153 default: throw new CException('Unsupported image type ' . $type). case IMAGETYPE_PNG: $this->image = imagecreatefrompng($filePath). break. break. 2012 protected $newWidth. $this->height. switch ($type) { case IMAGETYPE_GIF: $this->image = imagecreatefromgif($filePath). $type) = getimagesize($filePath). case IMAGETYPE_JPEG: $this->image = imagecreatefromjpeg($filePath). } return $this. public function resize($width = false.[YII 1. if($height!==false) $this->newHeight = $height. protected $newHeight. return $this. http://www.vn | Learn Drupal Online .1 APP DEVELOPMENT COOKBOOK ] August 28. break.seodrupal.

$this->newHeight). imagecopyresampled($newImage.1 APP DEVELOPMENT COOKBOOK ] August 28. 0. } imagedestroy($newImage). case 'png': imagepng($newImage. default: 153 throw new CException("Unsupported image type ". $newImage = imagecreatetruecolor($this->newWidth. 0. $filePath). PATHINFO_EXTENSION). $filePath). 2012 } public function save($filePath) { $ext = pathinfo($filePath. $this->width. break. break.vn | Learn Drupal Online . switch($ext) { case 'jpg': case 'jpeg': imagejpeg($newImage. case 'gif': imagegif($newImage. 0. $this->newHeight. $this->image. $filePath). 0.seodrupal.[YII 1. $this->newWidth. $ext). http://www. break. $this->height).

seodrupal.png')."). … Tiếp theo chúng ta sẽ sử dụng đoạn component mới như sau: Yii::app()->image ->load(Yii::getPathOfAlias('webroot').1 APP DEVELOPMENT COOKBOOK ] August 28.[YII 1. } function __destruct() { imagedestroy($this->image).png') ->resize(100.vn | Learn Drupal Online . 2012 if(!is_file($filePath)) throw new CException("Failed to write image.'/dst. } } Tiếp theo vào main.'/src.php trong protected/config để kích hoạt: Tìm và thêm vào đoạn sau : … // application components 'components'=>array( 'image' => array( 'class' => 'EImageManager'. 153 T ải application component đã t ồn t ại http://www.100) ->save(Yii::getPathOfAlias('webroot'). ).

1 APP DEVELOPMENT COOKBOOK ] August 28. $this->_model = User::model()->findByPk($this->id). function getRole() { if($user = $this->getModel()){ return $user->role.[YII 1. } private function getModel(){ if($this->_model === null){ if($this->id === null) return null.php ta phải cấu hình lại như sau: … 153 // application components 'components'=>array( http://www. } } Và trong main. tuy nhiên việc tải code đã tồn tại giúp ta giảm thời gian lập trình và tiết kiệm công sức. } return $this->_model.seodrupal.vn | Learn Drupal Online . } else return 'guest'. Ví dụ để hiện user role từ databse sử dụng Yii::app()->user->role có thể kế thừa từ CwebUser component giống như sau: <?php class WebUser extends CWebUser { private $_model = null. 2012 Hầu hết thời gian chúng ta cần tạo ứng dụng thành phần của riêng ta.

1 APP DEVELOPMENT COOKBOOK ] August 28. … 2. PRIMARY KEY (`id`) ). `text` text. Tạo controller action Trước tiên bạn vào phpmyadmin chọn sql và thực hiện query sau: CREATE TABLE `post` ( `id` int(11) NOT NULL auto_increment. Generated model với : post và comment trong Gii. PRIMARY KEY (`id`) ).seodrupal. CREATE TABLE `comment` ( `id` int(11) NOT NULL auto_increment. 2012 'user'=>array( 'class' => 'WebUser'. /** http://www. Vào protected/extensions/actions tạo EDeleteAction.[YII 1. `text` text. // other properties ).php <?php class EDeleteAction extends CAction 153 { public $modelName. public $redirectTo = array('index').vn | Learn Drupal Online . `title` varchar(255) default NULL.

http://www.php: <?php class DeleteController extends CController { public function actions() { 153 return array( 'deletePost' => array( 'class' => 'ext. */ public function run($pk) { CActiveRecord::model($this->modelName)->deleteByPk($pk). } } } Tiếp theo vào kích hoạt controller : protected/controllers/ tạo DeleteController. } else { $this->getController()->redirect($this->redirectTo). 2012 * Runs the action.1 APP DEVELOPMENT COOKBOOK ] August 28.[YII 1. * This method is invoked by the controller owning this action.EDeleteAction'.seodrupal.vn | Learn Drupal Online . if(Yii::app()->getRequest()->getIsAjaxRequest()) { Yii::app()->end(200. 'modelName' => 'Post'.actions. true).

actions. } public function actionIndexPosts() { echo "I'm index action for Posts. } } Bây giờ bạn có thể vào trình duyệt gõ: http://localhost/skybook/delete/deletePost/pk. Tạo reusable Controller Trong Yii bạn có thể tái sử dụng controller . 'deleteComment' => array( 'class' => 'ext. 2012 'redirectTo' => array('indexPosts').seodrupal.". 'modelName' => 'Comment'. http://localhost/skybook/delete/deleteComment/pk 153 3.vn | Learn Drupal Online .[YII 1. 'redirectTo' => array('indexComments'). ). ).EDeleteAction'. http://www. ). nếu bạn tạo nhiều ứng dụng với controller có thuộc tính giống nhau. } public function actionIndexComments() { echo "I'm index action for Comments.1 APP DEVELOPMENT COOKBOOK ] August 28. di chuyển tất cả các lệnh code tới controller tái sử dụng sẽ tiết kiệm nhiều thời gian cho bạn.".

const RESPONSE_NO_DATA = 'No data'. $model->setAttributes($_POST). public $modelName. nó sẽ đưa input data từ POST hoặc GET và sẽ sử lý bằng JSON data tiếp theo là HTTP code Vào Gii. self::RESPONSE_NO_DATA). const RESPONSE_VALIDATION_ERRORS = 'Validation errors'.vn | Learn Drupal Online .1 APP DEVELOPMENT COOKBOOK ] August 28.chúng ta sẽ tạo đơn giản api controller sẽ được thi hành với JSON. 2012 Trong bài này. } public function actionCreate() { if(empty($_POST)) 153 $this->respond(400.php: <?php class JsonApiController extends CController { const RESPONSE_OK = 'OK'. const RESPONSE_NOT_FOUND = 'Not found'. public function init() { parent::init(). http://www.[YII 1.tạo 1 model generated là Post Tiếp theo vào protected/extensions/ tạo json_api tạo JsonApiController. if(empty($this->modelName)) throw new CException("You should set modelName before using JsonApiController. $model = new $this->modelName.seodrupal.CRUD API cho một model.").

self::RESPONSE_OK. $this->respond(200.[YII 1. if(!$model) $this->respond(404. $model->getErrors()). self::RESPONSE_VALIDATION_ERRORS.vn | Learn Drupal Online . } public function actionGet($pk) { $model = CActiveRecord::model ($this->modelName)->findByPk($pk). self::RESPONSE_NOT_FOUND). self::RESPONSE_NOT_FOUND). if(!$model) 153 $this->respond(404.1 APP DEVELOPMENT COOKBOOK ] August 28. self::RESPONSE_OK). $model->getAttributes()). http://www. $model->setAttributes($_POST).seodrupal. self::RESPONSE_NO_DATA). $model = CActiveRecord::model ($this->modelName)->findByPk($pk). else $this->respond(400. self::RESPONSE_OK). if($model->save()) $this->respond(200. } public function actionUpdate($pk) { if(empty($_POST)) $this->respond(400. 2012 if($model->save()) $this->respond(200.

php … http://www. echo CJSON::encode($response). $data = array()) { $response['status'] = $status.php Nó có thể hoàn thành việc thêm con troller. self::RESPONSE_OK). } else { $this->respond(404. 2012 else $this->respond(400.vn | Learn Drupal Online . self::RESPONSE_VALIDATION_ERRORS.seodrupal.1 APP DEVELOPMENT COOKBOOK ] August 28. self::RESPONSE_NOT_FOUND). } public function actionDelete($pk) { if(CActiveRecord::model($this->modelName)->deleteByPk($pk)) { $this->respond(200. } } 153 Tiếp theo bạn cần kết nối t ới ứng dụng với protected/conFig/main. } } protected function respond($httpCode. $response['data'] = $data. Yii::app()->end($httpCode. $model->getErrors()). $status.cấu hình tới controllerMap property của CwebApplication và tat hay thế cấu hình sau trong main.[YII 1. true).

"title":"post1"."text":"post1".JsonApiController'. tạo EChartWidget.vn | Learn Drupal Online . ). Bạn sẽ cần form tới post data nhưng nếu bạn có một số dữ liệu tồn tại bạn có thể sử dụng phương thức nhận bằng cách http://localhost/skybook/api/get/pk/1 Ứng dụng trả về cho bạn như sau: {"status":"OK". ).seodrupal."data":{"id":"1". Nó có thể là một sự kiện nhận dữ liệu từ models và sử dụng nó trong bản thân views.json_api. Trong protected/extensions/ tạo folder chart. … Chúng ta cần kết nối tới controller và đặc biệt nó sẽ làm việc với post model. Hãy tạo một widget và vẽ một chart biểu đồ nghệ thuật sử dụng google API. http://www.[YII 1. 'modelName' => 'Post'.1 APP DEVELOPMENT COOKBOOK ] August 28. 2012 'controllerMap' => array( 'api' => array( 'class' => 'ext.php: 153 <?php class EChartWidget extends CWidget { public $title."is_deleted":"0"}} 4. Tạo một widget Một widget là một phần tái sử dụng của khung nhìn views nó không chỉ render một số dữ liệu mà còn đọc một số logic.

public $labels=array().61*($currentValue/$maxValue)."&chxt=y&chxl=0:|0|". $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789'. } return $chartData."&chl=". $this->encodeData($this->data).1).1 APP DEVELOPMENT COOKBOOK ] August 28. $chartData="s:". public function run() { echo "<img src=\"http://chart.[YII 1. } protected function encodeData($data) { $maxValue=max($data).com/chart?chtt=".apis. if($currentValue>-1) $chartData. for($i=0.$i<count($data). 2012 public $data=array().google."\">".implode ('|'.='_'. } http://www.vn | Learn Drupal Online .$i++) { $currentValue=$data[$i]."&cht=pc&chs=300x150&chd=".seodrupal.$maxValue.=substr($chars. $this->labels).urlencode ($this->title). else 153 $chartData.

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } Tiếp theo vào protected/controllers/ tạo ChartController.php <?php class ChartController extends CController { public function actionIndex() { $value = rand(10, 90); $this->widget('ext.chart.EChartWidget', array( 'title' => 'Do you like it?', 'data' => array( $value, 100-$value ), 'labels' => array( 'No', 'Yes', ), )); } } Vào trình duyệt gõ : http://localhost/skybook/chart/index lưu ý nhà phải kết nối với internet mới truy nhập vào được google thì mới thấy cái biểu đồ này.

153

http://www.seodrupal.vn | Learn Drupal Online

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012

5. Tạo filters (bộ lọc)
Một filters là một class có thể chạy trước/sau một action đang thực hiện. Nó có thể sử dụng và thay đổi nội dung thực hiện hoặc thay đổi output, trong ví dụ này bạn sẽ thực thi một output đơn giản được filter với compress HTML output và xóa tất cả mọi định dạng. Vào protected/extensions/ tạo compress_html folder, tạo ECompressHtmlFilter.php <?php class ECompressHtmlFilter extends CFilter { protected function preFilter($filterChain) { ob_start(); return parent::preFilter($filterChain); } protected function postFilter($filterChain) { $out = ob_get_clean(); echo preg_replace("~>(\s+|\t+|\n+)<~", "><", $out);
153

parent::postFilter($filterChain); } }
http://www.seodrupal.vn | Learn Drupal Online

[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Tiếp theo chúng ta cần kết nối tới ứng dụng, chúng ta vào protected/controllers/ SiteController và thêm filter: public function filters() { return array( array( 'ext.compress_html.ECompressHtmlFilter' ), ); } Chạy ứng dụng và kiểm tra source code ta sẽ thấy như sau: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional// EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional. dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head><meta http-equiv="Content-Type" content="text/ html; charset=utf-8" /><meta name="language" content="en" /><!-blueprint CSS framework -->

6. Tạo một modules
Nếu bạn muốn tạo một ứng dụng đầy đủ và muốn sử dụng nó với việc custom theo í bạn, hầu hết điều bạn muốn đó là việc bạn cần phải tạo một modules. Trong bài này,chúng ta sẽ nhìn việc tạo modules wiki,chúng ta sẽ không focus user và quản lý phân quyền và để mọi người điều khiển mọi thứ.
153

Trước tiên vào php myadmin chọn SQL : tạo query sau : CREATE TABLE `wiki` ( `id` varchar(255) NOT NULL, `text` text NOT NULL,
http://www.seodrupal.vn | Learn Drupal Online

153 array($this. 'wiki' ).php: <?php class WikiMarkdownParser extends CMarkdownParser { public function transform($text) { $text = preg_replace_callback('~\[\[(. } http://www.GiiModule'. return parent::transform($text). Tạo protected/modules/wiki/components/wikiMarkdownParser. 2012 PRIMARY KEY (`id`) ) Generated : wiki model với Gii Generated : wiki module với Gii Di chuyển protected/models/wiki.php Thêm wiki tới moduels section của protected/config/main.*?)(?:\|(.php tới protected/modules/wiki/models/wiki.[YII 1. 'processWikiLinks'). Cách thực hiện: Đầu tiên hãy thêm wiki link tới CMarkdownParser.seodrupal.gii.*?))?\]\]~'. ).php 'modules'=>array( // uncomment the following to enable the Gii tool 'gii'=>array( 'class'=>'system. $text).1 APP DEVELOPMENT COOKBOOK ] August 28.vn | Learn Drupal Online . 'password'=>false.

Tạo protected/modules/wiki/controller/DefaultController. } public function actionView($id) http://www. Chúng ta chỉ cần 2 action là views và edit. 2012 protected function processWikiLinks($matches) { $page = $matches[1].php public function getHtml() { $parser = new WikiMarkdownParser(). return $parser->transform($this->text). } } Tiếp theo sử dụng getHtml method từ protected/modules/wiki/models/wiki. array( 'view'. 'id' => $page.vn | Learn Drupal Online .1 APP DEVELOPMENT COOKBOOK ] August 28. $title = isset($matches[2]) ? $matches[2] : $matches[1].seodrupal. return CHtml::link(CHtml::encode($title). } Chúng ta tạo customer protected/modules/wiki/controller/DefaultController.php class DefaultController extends Controller { public function actionIndex() { 153 $this->actionView('index'). )).[YII 1.

2012 { $model = Wiki::model()->findByPk($id). http://www. )). if($model->save()) $this->redirect(array('view'.seodrupal. 'id' => $id)). } public function actionEdit($id) { $model = Wiki::model()->findByPk($id). $model->id = $id.1 APP DEVELOPMENT COOKBOOK ] August 28. } if(!empty($_POST['Wiki'])) { if(!empty($_POST['Wiki']['text'])) 153 { $model->text = $_POST['Wiki']['text']. } $this->render('view'. if(!$model) { $model = new Wiki(). if(!$model) { $this->actionEdit($id). array( 'model' => $model.[YII 1.vn | Learn Drupal Online . Yii::app()->end().

1 APP DEVELOPMENT COOKBOOK ] August 28. 'rows' => 20))?> <br /><br /> <?php echo CHtml::submitButton('Done')?> http://www. 'id' => $model->id))?>] </h2> <?php echo $model->html ?> Tạo views edit: protected/modules/wiki/views/default/edit. array('cols' => 100. array( 'model' => $model )).vn | Learn Drupal Online . } } $this->render('edit'. array('edit'.[YII 1. } } Tiếp theo tạo views : protected/modules/wiki/views/default/view.php <h2>Editing <?php echo CHtml::encode($model->id)?></h2> <?php echo CHtml::beginForm()?> 153 <?php echo CHtml::activeTextArea($model. 'text'. 2012 } else { Wiki::model()->deleteByPk($id).seodrupal.php <h2> <?php echo CHtml::encode($model->id)?> [<?php echo CHtml::link('edit'.

gii.1 APP DEVELOPMENT COOKBOOK ] August 28. 'wiki'=>array( 'class' => 'ext..wiki.php trong protected/config thay đổi : 'modules'=>array( // uncomment the following to enable the Gii tool 'gii'=>array( 'class'=>'system. 2012 <?php echo CHtml::endForm()?> Xong xuôi vào http://localhost/skybook/wiki/index và localhost/skybook/wiki/edit Tiếp theo vào main.vn | Learn Drupal Online .seodrupal. Mặc định mỗi moduels generated với Gii chạy index action của default controller: 153 public function actionIndex() { $this->actionView('index'). và nhiều hơn.định nghĩa import. kích hoạt controller. ). ).[YII 1. thay đổi đường dẫn.WikiModule' ). http://www. Mỗi modules được tạo chứa một main modules class giống wikimodule nơi chúng ta có thể định nghĩa cấu hình thuộc tính. 'password'=>false.GiiModule'.

[YII 1.vn | Learn Drupal Online . chúng ta xử lý bởi action khác: $model = Wiki::model()->findByPk($id). $model->id = $id. if($model->save()) http://www. Yii::app()->end(). } $this->render('view'. if(!$model) { $model = new Wiki().1 APP DEVELOPMENT COOKBOOK ] August 28. Nếu modules này giữ một ID chúng ta sẽ hiển thị nó và sử dụng trong views.seodrupal. Nếu không có trang nào giữ ID. )). } if(!empty($_POST['Wiki'])) { 153 if(!empty($_POST['Wiki']['text'])) { $model->text = $_POST['Wiki']['text']. 2012 } Trong wiki module indexaction tat hay đổi như sau: $model = Wiki::model()->findByPk($id). if(!$model) { $this->actionEdit($id). array( 'model' => $model.

Nếu bạn muốn sử dụng nó trong Yii bạn có thể định nghĩa chúng.smarty. Tải phiên bản mới nhất về.vn | Learn Drupal Online . 2012 $this->redirect(array('view'. Bây giờ chúng ta sẽ nhúng Smarty 3.net/. } } $this->render('edit'.nếu có ký tự chúng ta lưu lại. } else { Wiki::model()->deleteByPk($id). array( 'model' => $model )).php: <?php 153 class ESmartyViewRenderer extends CApplicationComponent implements IViewRenderer { http://www. 'id' => $id)). Cách thực hiện như sau: Vào protected/extensions/smarty tạo ESmartyViewRenderer. Giải nén (extract here ) rồi vào folder đó copy folder libs của smarty tới protected/vendors/smarty .1 APP DEVELOPMENT COOKBOOK ] August 28. 6.edit form data từ POST và kiểm tra nó rỗng hay không chúng ta delete models.nếu có một models chúng ta edit nó. Tạo một custom view renderer Có nhiều PHP templates được yii nhận là native PHP và Prado templates.seodrupal. NẾU KHÔNG CÓ modules nào sử dụng ID mới tạo. Bạn vào trang chủ : http://www.[YII 1.0 vào Yii.

spl_autoload_register(array('YiiBase'. 153 * @param CBaseController the controller or widget who is rendering the view file.vn | Learn Drupal Online . * Phương thức được yêu cầu từ {@link IViewRenderer}. public $filePermission=0755.vendors. } /** * Render một file viws. Yii::app()). $compileDir = Yii::app()->getRuntimePath (). 2012 public $fileExtension='.1 APP DEVELOPMENT COOKBOOK ] August 28. } $this->smarty->compile_dir = $compileDir.'autoload')).[YII 1. true). if(!file_exists($compileDir)){ mkdir($compileDir.'/smarty/compiled/'. * @param string the view file path * @param mixed the data to be passed to the view http://www.seodrupal.tpl'. $this->smarty = new Smarty().*').'autoload')). require_once('Smarty. $this->filePermission.smarty. function init() { Yii::import('application.php'). private $smarty. spl_autoload_unregister(array('YiiBase'. $this->smarty->assign('Yii'.class. $this->smarty->template_dir = ''.

vn | Learn Drupal Online .'. } } Tiếp theo bạn cần kết nối views renderer với ứng dụng.'View file "$sourceFile" does not exist. if(!is_file($sourceFile) || ($file=realpath($sourceFile))= ==false) throw new CException(Yii::t('ext'.[YII 1.seodrupal. array('{file}'=>$sourceFile))). Trong protected/config/main.php chúng ta cần tải viewRenderer component: 153 … // application components 'components'=>array( http://www. 2012 * @param boolean whether the rendering result should be returned * @return mixed the rendering result. or null if the rendering result is not needed.$sourceFile.$data. if($return) return $this->smarty->fetch($sourceFile). else $this->smarty->display($sourceFile). */ public function renderFile($context.property} $data['this'] = $context.1 APP DEVELOPMENT COOKBOOK ] August 28. $this->smarty->assign($data).$return) { // current controller properties will be accessible as {this.

1 APP DEVELOPMENT COOKBOOK ] August 28. Tạo protected/controllers/ Tạo SmartyController. array( 'username' => 'Alexander'.vn | Learn Drupal Online .ESmartyViewRenderer'. trong component có dữ liệu thì bạn để nguyên chỉ việc thêm vào : 'viewRenderer'=>array( 'class'=>'ext. 2012 … 'viewRenderer'=>array( 'class'=>'ext. Bây giờ kiểm tra nó. )). } http://www. ). … Lưu ý.seodrupal. )). } function actionSmarty() { 153 $this->render('smarty'.php <?php class SmartyController extends Controller { function actionNative() { $this->render('native'. ).smarty. array( 'username' => 'Alexander'. ).[YII 1.ESmartyViewRenderer'.smarty.

seodrupal. <?php echo $username?>! protected/views/smarty/smarty.tpl: Hello.php: Hello. {$username}! Bây giờ vào trình duyệt gõ : http://localhost/skybook/smarty/native Bạn sẽ thấy dòng : Hello. Bây giờ chúng ta nói về cách chia sẻ thành quả của bạn với mọi người và tại sao nó lại quan trong. 153 http://www.vn | Learn Drupal Online . Hãy check trong form sau những điều bạn suy nghĩ là đúng nhất về extensions Nội dung trong sang.Alexander! 7.[YII 1. tạo nền tảng cho ý tưởng với bài test Bạn cần được cung cấp hỗ trợ cho nó Tất nhiên tất cả yếu tố trên đều được yêu cầu thực sự cần thiết để tạo ra một sản phẩm tốt.1 APP DEVELOPMENT COOKBOOK ] August 28. Làm extensions distribution-ready Trong chương này bạn đã được học rất nhiều các tạo thuộc tính từ Yii extensions. 2012 } Tiếp theo t ạo views: protected/views/smarty/native. dễ đọc và sử dụng trong API Tài liệu tốt Mọi người đều có thể tìm thấy nó Extensions áp dụng được hầu hết trong ứng dụng user Sẽ là thành phần chính Tốt cho việc test code.

Trong bài học này ta sẽ thực hiện những việc sau: Giới hạn truy cập tới controller action với chỉ các user định danh Giới hạn truy cập tới controller action từ IPs đặc biệt Giới hạn truy cập tới người dùng đặc biệt Giới hạn truy cập cho user của một trình duyệt đặc biệt.chúng ta cần lọc ra dữ liệu hoặc thực hiện một số action cơ bản trong data.seodrupal. Sử dụng controller filter Trong nhiều trường hợp.đầu tiên là CInlineFilter nó cho phép sử dụng controller method như một bộ lọc. và cái thứ hai là (là một thứ chúng ta sẽ focus nó) CAccessControlFilter nó cho phép điều khiển truy cập tới dữ liệu của controller action. Yii có xây dựng hai bộ lọc .ví dụ với custom filter.vn | Learn Drupal Online .sức mạnh của user với việc sử dụng HTTPS.[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28.hoặc redirect user từ một phần quan trọng trong cấu hình trang để sử dụng trong ứng dụng.php <?php class AccessController extends CController { http://www. 2012 CHƯƠNG 8 • • • • • Sử dụng controller filter BẢO MẬT Bạn sẽ khám phá điều gì trong chương cuối này ? Sử dụng CHtml và CHtmlPurifier tới sự kiện XSS Khám phá SQL injection Khám phá CSRF Sử dụng RBAC 1. trong trường hợp chúng ta cũng có thể hiển thị custom messager 153 Trước tiên vào protected/controllers tạo AccessController. chúng ta có thể lọc ra lượt truy cập bởi IP.

} public function actionIp() { echo "Your IP is in our list. } Tiếp theo ta thêm access Rules (quy tắc truy cập) 153 { return array( array( 'deny'. http://www.". ).[YII 1. } public function actionUser() { echo "You're the right man.vn | Learn Drupal Online . Welcome!". 2012 public function actionAuthOnly() { echo "Looks like you are authorized to run me.1 APP DEVELOPMENT COOKBOOK ] August 28. } } Tiếp theo ta thêm bộ lọc sau: public function filters() { return array( 'accessControl'.seodrupal. Lucky you!".

[YII 1. 'users' => array('@'). ). thay autheronly bằng ip. array( 'allow'. sorry.0.0.seodrupal. array( 'allow'. 'actions' => array('user'). array('deny').1'). ). ). user để test Bây giờ chúng ta sẽ thử controller trên trình duyệt sử dụng cả 2 tài khoản admin và demo sẽ đều có kết quả sau http://www. ). 'actions' => array('ip').vn | Learn Drupal Online . \'MSIE\') !== FALSE'. ). 2012 'expression' => 'strpos($_SERVER[\'HTTP_USER_AGENT\']. 'users' => array('admin').". } 153 http://localhost/skybook/access/authonly .1 APP DEVELOPMENT COOKBOOK ] August 28. array( 'allow'. 'actions' => array('authOnly'). 'ips' => array('127. 'message' => "You're using the wrong browser.

php <?php class XssController extends CController { public function actionSimple() { echo 'Hello.'!'. nhận được một thông tin người dùng.</script> 153 http://www. 2012 2. Sử dụng CHtml và CHtmlPurifier tới sự kiện XSS XSS là viết tắt của cross-site scripting và là một loại lỗ hổng mà cho phép trích một kịch bản phía máy khách (thông thường. Xem xét sức mạnh của kịch bản phía máy khách này có thể dẫn đến hậu quả rất nghiêm trọng như bỏ qua kiểm tra an ninh. ta gõ tiếp . JavaScript) trong trang được xem bởi người dùng khác. Để test ta vào protected/controllers tạo XssController. '. } } Bây giờ vào trình duyệt gõ : http://localhost/skybook/xss/simple? username=Longt8x.1 APP DEVELOPMENT COOKBOOK ] August 28. hoặc rò rỉ dữ liệu. http://localhost/skybook/xss/simple?username=<script>alert(‘XSS’).$_GET['username'].vn | Learn Drupal Online .[YII 1. tuy nhiên tài sản chính không xuất hiện lên output .seodrupal.

array()).1 APP DEVELOPMENT COOKBOOK ] August 28.'!'. nhưng trong form data của bạn chứa nhiều dữ liệu mật thì điều thất thoát là khó tránh. 2012 Đương nhiên trong ví dụ này khách chỉ sử dụng một hàm alert thong số. 153 Tiếp theo sử dụng CHtmlPurifier giúp loại bỏ những thong tin thừa do phía máy khách tự nhập vào public function actionHtml() http://www.[YII 1. } } Đối với một link bạn chỉ cần sử dụng như sau: echo CHtml::link(CHtml::encode($_GET['username']).CHtml::encode($_GET['username']).vn | Learn Drupal Online . '. Yii đưa ra giải pháp sau: class XssController extends CController { public function actionSimple() { echo 'Hello.seodrupal.

Trước tiên vào phpmyadmin chọn sql và thêm query sau: CREATE TABLE `user` ( 153 `id` int(11) unsigned NOT NULL AUTO_INCREMENT.1 APP DEVELOPMENT COOKBOOK ] August 28. 2012 { $this->beginWidget('CHtmlPurifier').[YII 1.<strong>username</strong>!<script>alert(‘XSS’).seodrupal. echo $_GET['html'].vn | Learn Drupal Online . `password` varchar(32) NOT NULL. } public function actionHtml() { $purifier=new CHtmlPurifier(). Sự kiện SQL injection SQL injection là một loại injection code được sử dụng để làm tổn thương ở cấp cơ sở dữ liệu và cho phép thực hiện bất kỳ SQL cho phép người sử dụng độc hại để thực hiện hành động chẳng hạn như xóa dữ liệu hoặc nâng cao đặc quyền của họ . $this->endWidget(). `username` varchar(100) NOT NULL. http://www. } Ta vào trình duyệt gõ http://localhost/skybook/xss/html? html=Hello. echo $purifier->purify($_GET['html']).</script> sẽ có kết quả sau: 3.

$sql = "SELECT * FROM user WHERE username = '$userName' AND password = '$password' LIMIT 1.[YII 1.vn | Learn Drupal Online . $password = md5($_GET['password']). if($user) { echo "Success". Tiếp theo generated model : User sử dụng Gii Vào protected/controllers/ tạo SqlController.`username`. $user = Yii::app()->db->createCommand($sql)->queryRow().seodrupal. INSERT INTO `user`(`id`. 2012 PRIMARY KEY (`id`) ).`password`) VALUES ( '1'.'Alex' . INSERT INTO `user`(`id`.'202cb962ac59075b964b07152d234b70'). } http://www.php <?php class SqlController extends CController { public function actionSimple() { $userName = $_GET['username'].".`password`) VALUES ( '2'.1 APP DEVELOPMENT COOKBOOK ] August 28.'Qiang '. } 153 else { echo "Failure".`username`.'202cb962ac59075b964b07152d234b70').

Để fix vấn đề này bạn thêm vào controller action mới: public function actionPrepared() { $userName = $_GET['username'].1 APP DEVELOPMENT COOKBOOK ] August 28. 2012 } } Vào trình duyệt gõ : http://localhost/skybook/sql/simple? username=test&password=test bạn sẽ thấy trình duyệt in : Failure. $password = md5($_GET['password']).". $userName).vn | Learn Drupal Online . $command->bindValue('password'. Bây giờ thay http://localhost/skybook/sql/simple?username=%27+or+ %271%27%3D%271%2 7%3B+--&password=whatever. $password). Sẽ thấy ‘ hoặc ‘1’ =’1’. $user = $command->queryRow(). --' AND password = '008c5926ca861023c1d2a36653fd88e2' LIMIT 1.seodrupal. $sql = "SELECT * FROM user WHERE username = :username AND password = :password LIMIT 1. http://www. -Nó tương đương với query : SELECT * FROM user WHERE username = '' or '1'='1'.[YII 1. $command = Yii::app()->db->createCommand($sql). $command->bindValue('username'. 153 if($user) { echo "Success".

4.vn | Learn Drupal Online . Sự kiện CSRF CSRF hay XSRF viết tắt cross-site là một request giả . http://www.[YII 1. ngăn chặn tất cả các người sử dụng trang web đăng nhập vào.seodrupal.ngay lập tức bạn sẽ được đăng nhập từ example. Hậu quả của CSRF có thể sẽ rất nghiêm trọng: phá hủy dữ liệu trang web. Thậm chí nếu các thẻ hình ảnh được chèn vào trong một trang web khác. } } Bây giờ vào http://localhost/skybook/sql/prepared Sẽ hiện ra chữ failure.com/site/logout. và hơn thế nữa… Một số thực trạng của CSRF: Như CSRF nên được thực hiện bởi người sử dụng trình duyệt của nạn nhân. Yii include một token generation và token checking.một vài thủ thuật sử dụng độc hại của trình duyệt user để âm thầm thực hiện một yêu cầu HTTP đến với trang web khi người dùng đăng nhập. 2012 } else { echo "Failure". phơi bày tin dữ liệu. kẻ tấn công có thể không thường thay đổi tiêu đề HTTP được gửi.com. Thêm nữa có thể tự động insert một token trong HTML form: Vào protected/config/main. như vậy thong tin đã được bảo toàn. Một ví dụ về cuộc tấn công này là chèn một thẻ hình ảnh vô hình với src trỏ đến http://example.php thêm đoạn sau: 'components'=>array( 153 … 'request'=>array( 'enableCsrfValidation'=>true.1 APP DEVELOPMENT COOKBOOK ] August 28. ).

2012 … ).seodrupal. echo CHtml::submitButton().php 'components' => array( http://www.bạn sẽ nhận được một lời thong báo giống như sau: 153 Bảo mật mức cao: Nếu ứng dụng của bạn yêu cầu độ bảo mật cao hơn nữa. Sauk hi cấu hình ứng dụng bạn sử dụng C:Html::beginForm và CHtml::endForm khởi tạo của HTML form. echo CHtml::endForm().[YII 1. public function actionCreate() { echo CHtml::beginForm(). } Yii sẽ tự động thêm một token field ẩn sau: <form action="/csrf/create" method="post"> <div style="display:none"><input type="hidden" value="e4d1021e79ac 269e8d6289043a7a8bc154d7115a" name="YII_CSRF_TOKEN" /> Nếu bạn lưu form html và thử submit.vn | Learn Drupal Online .1 APP DEVELOPMENT COOKBOOK ] August 28. bạn hãy vào protected/config/main.

vn | Learn Drupal Online 153 .. .php sửa lại thong số giống như sau: http://www. Vào protected/config/main. ). import nó... Trong bài này.nhưng kể từ khi nó là khá phức tạp và mạnh mẽ.. .. Sau đó cho session timeout hoạt động 'components' => array( .. 5 .. Nó không ngăn cản tất cả các loại CSRF. Nó được mô tả trong tài liệu hướng dẫn. 'session' => array( 'timeout' => 200.. Sử dụng thuộc tính GET và POST HTTP khẳng định không sử dụng GET cho các hoạt động thay đổi dữ liệu hoặc trạng thái. chúng ta sẽ làm rõ vai trò của hệ thống phân cấp từ tiêu chuẩn hướng dẫn. ). và giải thích những gì đang xảy ra trong nội bộ. 2012 . nó không phải là dễ dàng như vậy để hiểu làm thế nào nó thực sựhoạt động mà không nhận được hood .[YII 1...seodrupal. Gắn bó với nguyên tắc này là một cách tốt.. Sử dụng RBAC RBAC là phương pháp kiểm soát truy cập mạnh mẽ nhất có sẵn trong Yii. 'user'=>array( // enable cookie-based authentication 'allowAutoLogin'=>false. nhưng ít nhất sẽ làm cho một số mũi trích như <img src = trở lên vô nghĩa. ). ).1 APP DEVELOPMENT COOKBOOK ] August 28.

… ). 'readerA'=>'123'. 'admin'=>'admin'. ). ). 'editorC'=>'123'. 'authorB'=>'123'.vn | Learn Drupal Online .seodrupal. Thêm vào protected/components/UserIdentity. Tạo protected/controllers/RbacController.php đoạn sau: $users=array( // username => password 'demo'=>'demo'. 2012 return array( 'components'=>array( … 'authManager'=>array( 'class'=>'CDbAuthManager'.1 APP DEVELOPMENT COOKBOOK ] August 28. 'adminD'=>'123'. ).[YII 1. 'connectionID'=>'db'.php 153 <?php class RbacController extends CController { public function filters() http://www.

). ). 'roles' => array('deletePost'). 'test'). 2012 { return array( 'accessControl'.[YII 1. ).'create a post'). $auth->createOperation('createPost'. array('deny').seodrupal. array( 'allow'. ).'read a post').1 APP DEVELOPMENT COOKBOOK ] August 28. 'actions' => array('init'. } public function accessRules() { return array( array( 'allow'. 'actions' => array('deletePost'). $auth->createOperation('updatePost'. } public function actionInit() { 153 $auth=Yii::app()->authManager. $auth->createOperation('readPost'. http://www.vn | Learn Drupal Online .'update a post').

$auth->assign('author'. $role->addChild('author'). echo "Done.1 APP DEVELOPMENT COOKBOOK ] August 28. $role->addChild('readPost'). $role=$auth->createRole('reader').[YII 1.'readerA'). $task->addChild('updatePost'). $role=$auth->createRole('admin'). $task=$auth->createTask('updateOwnPost'.seodrupal.$bizRule).'adminD'). $role=$auth->createRole('author').'authorB').'.'update a post by author himself'. 2012 $auth->createOperation('deletePost'. $role->addChild('reader'). $auth->assign('reader'. $role->addChild('createPost'). $role->addChild('updateOwnPost').".'delete a post'). $role=$auth->createRole('editor'). $role->addChild('editor'). $bizRule='return Yii::app()->user->id==$params ["post"]->authID. 153 $auth->assign('admin'. } public function actionDeletePost() http://www. $role->addChild('reader'). $auth->assign('editor'.vn | Learn Drupal Online . $role->addChild('deletePost'). $role->addChild('updatePost').'editorC').

echo "<li>Update post: "."</li>". echo "<li>Delete post: ". $post->authID = 'authorB'.Yii::app()->user->checkAccess ('createPost'). array('post' => $post)). echo "Current permissions:<br />". } public function actionTest() { $post = new stdClass().Yii::app()->user->checkAccess ('deletePost')."."</li>".seodrupal.[YII 1."</li>".Yii::app()->user->checkAccess ('readPost'). echo "<li>Read post: ".1 APP DEVELOPMENT COOKBOOK ] August 28.Yii::app()->user->checkAccess ('updatePost'.vn | Learn Drupal Online . } } Bây giờ vào localhost/skybook/rbac/init để xem kết quả 153 http://www. echo "</ul>"."</li>". 2012 { echo "Post deleted. echo "<li>Create post: ". echo "<ul>".

1 APP DEVELOPMENT COOKBOOK ] August 28. ff Không kết nối các nút cùng loại. Nếu quy tắc xác định nếu một người dùng có thể chỉnh sửa các blog của riêng bình luận. chúng ta sẽ tránh nhận được một nút hệ thống phân cấp RBAC do lưu kho.[YII 1. Ngoài ra. Một cách để giữ cho hệ thống phân cấp đơn giản và hiệu quả Theo những đề nghị khi có thể để tối đa hóa hiệu suất và giảm hệ thống phân cấp phức tạp: ff Tránh gắn nhiều vai trò một người dùng duy nhất. Vì vậy. Thực thể là một tên của thực thể. chúng tôi sẽ đặt tên nó như là blog_post_delete. nếu chúng ta cần phải tạo ra một quy tắc để xác định nếu người dùng có thể xóa một bài đăng blog. If(!$post) throw new CHttpException(404). Chúng ta có thể tạo ra một nút blog_own_post_edit với bizRule như sau: return Yii::app()->user->id==$params["post"]->author_id. Một quy ước giúp không làm cho chúng ta nhầm lẫn như sau: [Group_] [own_] entity_action Trường hợp riêng được sử dụng khi quy tắc xác định khả năng sửa đổi một phần tử chỉ khi người sử dụng hiện nay là chủ sở hữu của các yếu tố và nhóm chỉ là một không gian tên. 153 http://www. 2012 Đ ặt tên các nút RBAC Một hệ thống cấp bậc phức tạp trở nên khó hiểu mà không cần sử dụng một số loại đặt tên một hội nghị. )). tránh kết nối một trong những nhiệm vụ một số khác. chúng ta có thể tránh việc tạo ra và sử dụng các nút thêm trong một số trường hợp bằng cách thay thế chúng bằng các điều kiện bổ sung. chúng tôi đang làm việc và hành động là hành động mà chúng tôi đang thực hiện. chúng ta có thể thêm cùng một logic thường xuyên lựa chọn bài như sau: $post = Post::model()->findByAttributes(array( 'id' => $id. Một ví dụ là các sửa đổi của Post. 'author_id' => Yii::app()->user->id.vn | Learn Drupal Online . tên sẽ được blog_own_comment_edit. ví dụ.seodrupal. Bằng cách sử dụng cách thứ hai. Ví dụ. Để giữ cho hệ thống phân cấp còn đơn giản.

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->