Professional Documents
Culture Documents
Everything you want supported please send request to email or yahoo : taisaoemkotin_17@yahoo.com, thank you! Bn vo trang ch : http://www.yiiframework.com/download/ Download phin bn mi nht v sau gii nn (extract here), sau rename li l cookbook, copy folder cookbook mi gii nn vo C:\xampp\htdocs\, bn phi down xampp v ri ci t setup thnh cng th chy xampp center thit lp apache v mysql running.
http://localhost/cookbook/requirements/index.php Phn mm chy local: Xampp, Wamp, ko nn dng appserv v b li( nguyn nhn mnh ko bit, tt nht nn trnh). Hoc xi lun host tht nu nh c iu kin. 1. Chun b Trc tin bn phi cu hnh windows s dng c php vi cmd -Gi s bn ci apache mc nh trn WinXP (C:\xampp\htdocs). -Bn thit lp li bin mi trng (Environment Variables) bng cch vo: Start -> My Computer (right click!) -> Advanced Tab -> Environment Variables -> Click Path in System variables (windows 7 l Path) -> Edit. -Click vo bin PATH v chn Edit. Lu l ng c xo b cc ng dn tn ti trong textbox m ngn cch chng vi nhau bng du ";". -Tip bn thm vo nhng ng dn sau: "C:\xampp\php" v " C:\xampp\htdocs\cookbook\framework". Lu sa ng dn cho ph hp 153 vi my bn nha . -Khi ng my tnh li. 2.To ng dng Yii mi -YiiRoot l th mc ni bn ci t Yii -Webroot l th mc gc cha web -T dng lnh, n webroot ca bn v thc hin: Vo start -> run->cmd http://www.seodrupal.vn | Learn Drupal Online
CHNG 1 -
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 PHP cng ging nh cc cng ngh khc nh Java, C# , u c cu trc lp trnh hng i tng v xy dng cng ngh theo cc class(lp), yii framework c xy dng trn nn php cng khng ngoi l, tuy nhin iu khc bit l n k tha t Ccomponent (class o cho bt k class no trong Yii). Cch thc hin: Chng ta theo di nh ngha lp trong php vi hm thit lp (setter) v hm nhn li (getter)
class MyClass { private $property; // ham nhan lay gi tr public function getProperty() { return $this->property; } // ham khi to gi tr public function setProperty($value) { $this->property = $value; } } // to mi i tng $object = new MyClass(); // thit lp i tng $object->setProperty('value'); // tr v gi tr echo $object->getProperty(); Trong Yii chng ta thc hin nh k tha 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'; // cng nh php : $object-> setProperty('value'); echo $object->property; // cng nh $object->getProperty();
153
Ngoi ra Yii cn h tr cc hm sau thc hin vic thit lp v nhn gi tr : __get, __set, __isset, v __unset
Cch thc hin th no ? nh ngha mt s kin trong lp con ca Ccomponent, bn s thm phng thc (method) vi tn bt u bng t on, v d nu bn thm onRegister method , bn s nhn c tng ng mt s kin bn khai bo. Cc loi s kin c s dng ging nh : - nh ngha mt s kin c thm tung ng mt phng thc, - Kch hot mt hay nhiu s kin x l. - Thnh phn nng cao (raise) ca mt s kin c s dng bi Ccomponent ::raiseEvent method - Tt c cc th hin x l c gi t ng. Hy nhn vo cch chng ta c th kch hot mt s kin x l t mt s kin. Chng ta s dng Ccomponent::attachEventHandler method.N chp nhn cc tham s sau y: $name : Tn s kin. $handler: X l s kin,yu cu ca bn trc mi s kin thng l mt hm tiu chun gi li (standard function callback) php s dng. Bn c th thc hin hm gi li nh sau : S dng hm cc b (global function) v ch nhn tn ging nh cc chui v d my_function. S dng cc phng thc tnh t lp (static class method).Bn s ch tr v gi tr array(Tn lp (Name class),Tn phng thc tnh(static method Name)). S dng object method : array($object,object method) To v nhn hm nh danh s dng create_function nh sau: Trc tin nh ngha component
http://www.seodrupal.vn | Learn Drupal Online
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 public function init() { parent::init(); $component = Yii::app()->{$this->component}; } $component>attachEventHandler(onClick,create_function($event,echo click!)); Vi phin bn PHP 5.3 tr ln bn ch cn vit: $component->attachEventHandler(onclick,function($event){echo click;}); code ngn hn bn ch cn vit nh sau : $component>onClick=$handler; hoc $component->onClick->add($handler); qun l vic x l s kin bn s dng hm get handler list (Clist) trong Ccomponent::getEventHandlers v lm vic vi n. V d : $component->getEventHandlers(onClick)->add($handler); thm mt x l vo u danh sch cc x l ta vit: $component->getEventHandlers(onClick)->insertAt(0,$handler); xa mt x l bn s dng Ccomponent::detachEventHandler: $component->detachEventHandler(onClick,$handler);
Yii application c 2 s kin c s l trong cc trng hp sau ; Capplication::onBeginRequest v Capplication::onEndRequest hy s dng chng . t cu hnh thit lp nh sau vo file index.php trc khi chy ng dng: require_once($yii); $app = Yii::createWebApplication($config); // Kch hot s l trc khi bt u ng dng Yii::app()->onBeginRequest = function($event) { // starting output buffering with gzip handler return ob_start("ob_gzhandler"); }; // Kch hot s l sau khi kt thc ng dng Yii::app()->onEndRequest = function($event) { // releasing output buffer return ob_end_flush(); };
http://www.seodrupal.vn | Learn Drupal Online
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $app->run(); Comment l mt tiu chun ca AR model generate vi Gii, Post l mt phng thc ngoi l trong Gii-generated model. Chng ta s custom s kin NewCommentEvent thc hin c post v comment model v s l class Notifier lm vic: Bt u vo protected/components/ to NewCommentEvent.php
class NewCommentEvent extends CModelEvent { public $comment; public $post; } Rt n gin ch bao gm 2 thuc tnh. By gi bn di chuyn ti protected/models/Post.php. Tt c tiu chun AR method c xy dng nh sau:
class Post extends CActiveRecord { function addComment(Comment $comment){ $comment->post_id = $this->id; // to mi s kin t class trc $event = new NewCommentEvent($this); $event->post = $this; $event->comment = $comment; // kch hot s kin mi
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 public function onNewComment($event) { $this->raiseEvent('onNewComment', $event); } } Tip theo to trong protected/components/ file Notifier.php
class Notifier { function comment($event){ $text = "C mt comment mi t {$event->comment->author} trong post {$event->post->title}"; mail('admin@example.com', 'New comment', $text); } } Tip theo vo trong protected/controllers/ to file PostController.php Class PostController extends Ccontroller { // to action thm comment function actionAddComment() { $post = Post::model()->findByPk(10); $notifier = new Notifier(); // kch hot s l s kin $post->onNewComment = array($notifier, 'comment');
153
// d liu tht c di dng request $_POST $comment = new Comment(); $comment->author = 'Sam Dark';
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $comment->text = 'Yii events are amazing!'; // thm comment $post->addComment($comment); }
} Nh vy l bn bit cch kch hot v s l mt s kin , tuy nhin nhiu trng hp khng nht thit phi kch hot s l s kin m chng ta cng c th kch hot s l s kin t cc component tn ti v chng ta ch cn overriding cc class c bn . V d chng ta c form model UserForm s dng thu thp thng tin ca ngi dng v chng ta cn hin th y h tn ca user. Tht may, Cmodel class c bn trong Yii model c th m rng form models. Cmodel::afterValidate c gi sau khi form c submit thnh cng. Ta vo protected/models/ to file UserForm.php class UserForm extends CFormModel { public $firstName; //tn public $lastName; //h public $fullName; //tn y public function rules() { return array( //tp hp quy tc : firstname,lastname c yu cu (k rng) array('firstName, lastName', 'required'),
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 // to ra v thit lp mt s kin( event) khi method c gi . // CModel::afterValidate(). function afterValidate() { //Nu phng thc c gi th s kin s t ng np d liu sau: $this->fullName = $this->firstName.' '.$this->lastName; // iu quan trng l n phi c gi li t lp cha (parent class) // l iu gip cc s l s kin khc c gi li. return parent::afterValidate(); } }
Chng ta cn gi li t lp cha (parent class) ca afterValidate() v hm nh ngha onAfterValidate() thc cht l raiseEvent: Protected function afterValidate() { $this->onAfterValidate(new CEvent($this)); } 2. S dng import v autoloading Khi lp trnh vi php hu ht cc class v hm to u c load bi hai phng thc l : include v require. Tuy nhin bn cng c th s dng loader nh SPL class, yii s dng cng ngh ny vo Yii Base v vic xy dng cc lp tiu chun trong yii CdbCriteria. Mc nh autoloader (YiiBase::autoload) s c s dng.
153
Hu ht tt c cc lp c load khi cn including hoc importing . Yii hon tt bi YiiBase::$_coreClasses map, v th m vic load trong Yii rt nhanh.Zii class cng nh Cmenu, extension class hoc class ca bn nh ngha cng c t ng load. 3. Cu hnh Component(Thnh phn)
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Yii l mt framework custom, hu nh mi th u c th custom mt cch d dng l u im ca yii, trc tin chng ta tm hiu file config ca Yii trong protected/con fig /main.php c th s dng database kt ni mysql ta ch cn b 2 dng /* ---- */ array di y c kch hot. return array( 'components'=>array( 'db'=>array( 'class'=>'system.db.CDbConnection', 'connectionString'=>'mysql:host=localhost;dbname=database_ name', 'username'=>'root', 'password'=>'', 'charset'=>'utf8', ), ), );
Khi c th kt ni ti database ri bn ch cn khai bo Yii::app()->db; l ta c th lm vic trc tip vi CSDL. Mt s component trong Yii bn nn bit :
153
153
4: Lm vic vi Request
Vi yii bn c th tr v d liu di dng request m php a ra nh $_SERVER, $_GET,$_POST, nhng tt hn bn nn lm theo vic s dng ca Yii l :ChttpRequest class , lp ny gii quyt nhng ngoi l t server, qun l cookies,cung cp thm vn bo mt,v c bit l hng i tng . Bn c th truy nhp request component trong yii bng vic s dng : Yii::app()>getRequest(). V th nn xem mt s hm hu ch , cc method tr v khc bit t URL :
chc chn cc request c truyn ng ta c thm cc hm kim tra : IsPostRequest (Kim tra hm post), getIsAjaxRequest (kim tra ajax loader), getRequestType (kim tra request thuc loi get hay post hay ajax). V d chng ta mun kim tra xem aJax c load hay cha ta xem v d sau :
class TestController extends CController { public function actionIndex() { if(Yii::app()->request->isAjaxRequest)s $this->renderPartial('test'); else $this->render('test'); } } 153 Ngoi ra b cng c th dng cc hm thi l thng d c PHP ki tra nh n t p ng a m isset, ispost . class TestController extends CController { http://www.seodrupal.vn | Learn Drupal Online
L , ch m v cc b m h s khng th lm th v khng c database u ng t i n i c c th, xin vui lng down source code bn English test app ca h.
CHNG 2 : ROUTER (nh tuyn), Controller (iu khin), and views (khung nhn)
Trong chng ny bn s c hc:
Cu hnh quy tc url, Generating Url by path S dng biu thc quy tc (regular expression) trong URL rules To url rules cho cc trang tnh. Cung cp url rules mi thi im. S dng controller c bn S dng action c bn Hin th trang ng vi CViewAction S dng flash messages ( C thng ip) S dng controller context trong view S dng clips
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 S dng decorator nh ngha nhiu layout (giao din) Paginating and sorting data (Phn trang v sp xp d liu)
'rules'=>array( ), ),
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 'db'=>array('connectionString'=>'sqlite:'.dirname(__FILE__).'/../data/testdrive.db',), Vo protected/controllers to websiteController.php vi dng code sau: class WebsiteController extends CController { public function actionIndex() { echo "index"; } public function actionPage($alias) { echo "Page is $alias."; } }
Thay i file .htaccess trong protected nh sau : Options +FollowSymLinks IndexIgnore */* RewriteEngine on # if a directory or a file exists, use it directly RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # otherwise forward it to index.php RewriteRule . index.php Thm on sau vo main.php nh sau:
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 '<alias:about>' => 'website/page', 'page/<alias>' => 'website/page', ), ), Ln lt g vo trnh duyt cc ng dn sau: http://localhost/skybook/index.php/page/test http://localhost/skybook/index.php/home http://localhost/skybook/index.php/about http://localhost/skybook/index.php/page/about
Bn s thy bin alias trong action page s thay i ty theo ng dn th 2 sau page bn in vo, y chnh l url nh danh (url alias). Thc t iu g xy ra: Vi quy tc : home=>website/index , trong Yii mi controller v action u c mt quy tc chung mc nh l moduleId (tn module)/controllerID(tn controller)/actionID(tn action). V d trong trng hp home l module : default, controller website, v action l index. page/<alias>=>website/page,
153
y , chng ta nh ngha mt alias parameter ( tham s nh danh) c bit trong Url sau /page/. N c th nhn v cc tham s o t tham s $alias trong action Page ca website controller. y bn nh ngha tr v tham s cho n bng vic thit lp quy tc:
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 <alias:about>=>website/page, ng ngha vi vic tham s $alias s ch nhn c tham s o l about.
nh dng ca quy tc vn theo th t : modulesID/controllerID/actionId. Tham s l bin $_GET s nhn mt action vi nh tuyn c bit, cho v d nu chng ta mun to mt url t websitecontroller ::actionIndex v nhn tham s $_GET[name] ta ch cn lm nh sau: echo CHtml::link('Click me!', array('website/index', 'name' => 't c bn tu kha lm ra Yii (Quiang Xue)')); URl rt hu ch khi s dng controller . Trong controller bn c th s dng createUrl to mi url v createAbsoluteUrl hin th thong tin v url: class WebsiteController extends CController { public function actionTest() { echo $this->createUrl('website/page', 'alias' => 'about'); echo $this->createAbsoluteUrl('website/page',
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } Khi bn khng mun hin khi to ca controller , khi bn thc thi ng dng bn c th s dng method sau: echo Yii::app()->createUrl('website/page', 'alias' => 'about'); echo Yii::app()->createAbsoluteUrl('website/page', 'alias' => 'test');
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 RewriteEngine on # if a directory or a file exists, use it directly RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # otherwise forward it to index.php RewriteRule . index.php Tip theo thay i li trong main.php phn rules nh sau: 'urlManager'=>array( 'urlFormat'=>'path', 'rules'=>array( 'post/<alias:[-a-z]+>' => 'post/view', '(posts|archive)' => 'post/index', '(posts|archive)/<order:(DESC|ASC)>' => 'post/index', 'sayhello/<name>' => 'post/hello', ), ), Sau vo trnh duyt t sng: http://localhost/skybook/index.php/post/test-post thnh cng http://localhost/skybook/index.php/post/test-9 hi sinh (v hm ngoi l yu cu dng k t k phi dng s) http://localhost/skybook/index.php/achive hi sinh v index thuc dng s khng thuc k t http://localhost/skybook/index.php/posts/ASC thnh cng
153
6. S dng controller c bn
u tin ta vo protected/components to SecureController.php <?php
153
[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('*'), ), ); } } Vo protected/config/ main.php tm on /* '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 dng check v in password cho gii (generated database) 'gii'=>array( 'class'=>'system.gii.GiiModule', 'password'=>'1111', 'ipFilters'=>array('127.0.0.1','::1'), ), Tip theo vo http://localhost/skybook/index.php/gii/default/login in mt khu l 1111 Tip theo chn Controller Generator g SecureController
153
7. S dng c bn Action
Vo protected/config/main.php tm on 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 nguyn, vo localhost/phpmyadmin t table testdrive ng c n o nu bn nguyn, hoc nu thay th= skybook th to bng skybook. Vo phpmyadmin vi table mi to vi 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
153 Nhn go query thc hin. c Tip theo vo GII generated 2 bng mi to bng cch chn model generated
G ln lt Post v User trong table Name ri generated Nu n bo override th vn generated kim tra vo protected/models s tm thy 2 file mi to. Tip theo vo PostController vit li nh sau: class PostController extends CController { function actionIndex() { $posts = Post::model()->findAll(); $this->render('index', array( 'posts' => $posts, ));
153
} function actionDelete($id) {
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $post = Post::model()->findByPk($id); if(!$post) throw new CHttpException(404); if($post->delete()) $this->redirect('post/index'); throw new CHttpException(500); } } Tip theo vo protected/components to file DeleteAction.php class DeleteAction extends CAction { function run() { if(empty($_GET['id'])) throw new CHttpException(404); $post = Post::model()->findByPk($_GET['id']); if(!$post) throw new CHttpException(404); if($post->delete()) $this->redirect('post/index'); throw new CHttpException(500); }
153
class PostController extends CController { function actions() { return array( 'delete' => 'DeleteAction', ); } } OK.chng ta s dng delete action trong component cho post controller nhng vn cn user controller, ta custom li delete action: class DeleteAction extends CAction { public $pk = 'id'; public $redirectTo = 'index'; public $modelClass; function run() { if(empty($_GET[$this->pk])) throw new CHttpException(404); $model = CActiveRecord::model($this->modelClass)
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 if($model->delete()) $this->redirect($this->redirectTo); throw new CHttpException(500); } } By gi chng ta c th s dng action cho c 2 controller .Vi post controller ta lm nh sau: class PostController extends CController { function actions() { return array( 'delete' => array( 'class' => 'DeleteAction', 'modelClass' => 'Post', ); ); } } Vi user controller ta cng khai bo action mi trong component class UserController extends CController {
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 'delete' => array( 'class' => 'DeleteAction', 'modelClass' => 'User', ); ); } } Vi cch ny ta c th tit kim thi gian xy dng hm vi nhng hm c cu trc ging nhau.
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $this->redirect('index'); } function actionIndex() { $this->render('index'); } } Vo protected/views/website to index.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?>
153
} }
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 To views : <h1><?php echo $this->pageTitle?></h1> <p>Hello call. <?php $this->hello()?></p> <?php $this->widget('zii.widgets.CMenu',array( 'items'=>array( array('label'=>'Home', 'url'=>array('index')), array('label'=>'Yiiframework home', 'url'=>'http://yiiframework.ru/', ), ))?
param><param name="allowFullScreen" value="true"></ param><param name="allowscriptaccess" value="always"></ param><embed src="http://www.youtube.com/v/S6u7ylr0zIg?fs=1" type="application/x-shockwave-flash" allowscriptaccess="always"
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 allowfullscreen="true" width="480" height="385"></embed></object>
Chnh sa li : <object width="<?php echo!empty($width) ? $width : 480?>" height="<?php echo!empty($height) ? $height: 385?>"><param name="movie" value="http://www.youtube.com/v/<?php echo $id?>?fs=1 "></param><param name="allowFullScreen" value="true"></ param><param name="allowscriptaccess" value="always"></ param><embed src="http://www.youtube.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>
To protected/website/index.php <?php $this->renderPartial('////common/youtube', array( 'id' => '8Rp-CaIKvQs', // you can get this id by simply looking at video URL 'width' => 320, 'height' => 256, ))?> Gi ta s th gi email ,them mi action trong website controller
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $users = User::model->findAll(); foreach($users as $user) { $this->sendEmail('welcome', $user->email, 'Welcome to the website!', array('user' => $user)); } echo 'Emails were sent.'; } function sendEmail($template, $to, $subject, $data) { mail($to, $subject, $this->renderPartial ('//email/'.$template, $data, true)); } } Tip theo to protected/views/email/welcome.php: Hello <?php echo $user->name?>, Welcome to the website! You can go check our new videos section. There are funny raccoons. Yours, Website team.
11 . S dng clip
Khi chng ta cn nh ngha 2 v tr trong layout : trc content v footer, m protected/views/layouts/main.php them on sau trc output (<?php echo $content;?>) <?php if(!empty($this->clips['beforeContent'])) echo $this->clips['beforeContent']?> V them on sau trc footer
http://www.seodrupal.vn | Learn Drupal Online
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 <?php if(!empty($this->clips['footer'])) Echo $this->clips['footer']; ?> By gi chng ta cn in vo v tr ca chng, m controller action cho beforeContent region. M protected/controllers/SiteController.php v them on sau vo actionIndex: $this->beginClip('beforeContent'); echo 'Your IP is '.Yii::app()->request->userHostAddress; $this->endClip(); Tip theo m protected/views/site/index.php v them on sau: <?php $this->beginClip('footer')?> ng dng c xy dng bi Tu kha. <?php $this->endClip()?> Hon tt bn c th m index bn s thy a ch IP v ng dng gn footer.
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 </ul> </div> <div class="sidebar links"> <ul> <li><a href="http://yiiframework.com/">Yiiframework</a></li> <li><a href="http://php.net/">PHP</a></li> </ul> </div> <?php $this->endContent()?>
Article cha ni dung sau: <?php $this->beginContent('//layouts/main')?> <div> <?php echo $content?> </div> <div class="sidebar toc"> <ul> <li><a href="#intro">1. Introduction</a></li> <li><a href="#quick-start">2. Quick start</a></li> </ul> </div> <?php $this->endContent()?>
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 function actionIndex() { $this->layout = 'blog'; $this->render('//site/index'); } } class ArticleController extends Controller { function actionIndex() { $this->layout = 'articles'; $this->render('//site/index'); } } class PortfolioController extends Controller { function actionIndex() { $this->render('//site/index'); } } Gi hy th vo http://localhost/skybook/index.php/blog, http://localhost/skybook/index.php/article and
153
http://localhost/skybook/index.php/portfolio. Chng ta va nh ngha 2 layout cho blog v articles. Nu chng ta khng mun copy-pase mt phn ca layout chnh,chng ta th them layout c nh ngha
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 bng cch s dng $this->beginContent v this->endContent; th hin hnh di y:
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $sort = new CSort('Post'); $sort->attributes = array( 'id', 'title', ); $sort->applyOrder($criteria); $models = Post::model()->findAll($criteria); $this->render('index', array( 'models' => $models, 'pages' => $pages, 'sort' => $sort, )); } } Tip theo xy dng views: protected/views/post/index.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?> - <?php echo $model->title?></h2> </li>
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 ))?> thc hin kim tra bn vo phpmyadmin v thm vo bng post khong 20 item, sau vo trnh duyt xem kt qu: http://localhost/skybook/post
CHNG 3
153
AJAX V jQuery
Trong chng ny bn s khm ph: Ti mt block vi AJAX Qun l asserts Including resources vi page Lm vic vi JSON Nhn thit lp t PHP v Javascript X l bin s ca input
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 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.', 'Edward V Berard'), array('It always takes longer than you expect, even when you take into account Hofstadter’s Law.', 'Hofstadter’s Law'), array('Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.', 'Rick Osborne'), array('I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone.', 'Bjarne Stroustrup'), array('Java is to JavaScript what Car is to Carpet.', 'Chris Heilmann'), ); private function getRandomQuote() { return $this->quotes[array_rand($this->quotes, 1)]; }
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 )); } //ajax callback function actionGetQuote() { $this->renderPartial('_quote', array( 'quote' => $this->getRandomQuote(), )); } }
Tip theo to views : protected/views/quote/index.php <h2>Quote of the day</h2> <div id="quote-of-the-day"> <?php $this->renderPartial('_quote', array( 'quote' => $quote, ))?> </div> <?php echo CHtml::ajaxLink('Next quote', array('getQuote'), array('update' => '#quote-of-the-day'))?>
153
Vo trnh duyt g : http://localhost/skybook/index.php/quote/index c th xem cu hnh ajax to ra bn dng firebug tr vo vng next quote s hin th javascript to ra ajax t Chtml::ajaxLink. 2. Qun l Assert Mt trong nhng kh nng tuyt vi ca Yii l c th bo v ti sn (m ngun) mt cch hiu qu Khi thc thi mt extension c kch hot javascript,css,images th folder gc khng th truy nhp c t trnh duyt. Khi bn cn truy nhp li ti sn (css,js,image) ca bn ch cn combine javascript Khi bn s dng assert nhiu ln trong phn trang v trnh trng lp Hy bt u k hoch trc, bn c th thay i widgets ti bt k th mc no, n nm trong protected/components. N chp nhn c mt hoc 2 class trong , nhng khi s lng class tng ln, n s to ra vn ,To mt assert trong widget vi protected/extensions/facebook_events.v t trong ajax-loader.gif bn vui lng download ti http://ajaxload.info . Tip theo to facebook_event.css v facebook_event.js To EFacebookEvents.php trong folder facebook_events <?php class EFacebookEvents extends CWidget
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 event&callback=?"; protected function getUrl() { return sprintf($this->url, urlencode($this->keyword)); } public function init() { // khoi tao duong dan file assets $assetsDir = dirname(__FILE__).'/assets'; $cs = Yii::app()->getClientScript(); $cs->registerCoreScript("jquery");
// thiet lap duong dan toi file js $cs->registerScriptFile( Yii::app()->assetManager->publish( $assetsDir.'/facebook_events.js' ), CClientScript::POS_END ); //thiet lap duong dan toi file css $cs->registerCssFile( Yii::app()->assetManager->publish( $assetsDir.'/facebook_events.css'
153
) ); // thiet lap duong dan toi file images // asset can be accessed with
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $this->loadingImageUrl = Yii::app()->assetManager->publish( $assetsDir.'/ajax-loader.gif' ); } public function run() { $this->render("body", array( 'url' => $this->getUrl(), 'loadingImageUrl' => $this->loadingImageUrl,, 'keyword' => $this->keyword, )); } }
Tip theo vo protected/extensions/facebook_events/ to views/body.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> Tip theo vo file facebook_events.js :
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $.getJSON(url,function(json){ var html = "<ul>"; $.each(json.data,function(){ html += "<li>"+ "<p><strong>" + this.name + "</strong> </p><p>"+this.location "</p></li>"; }); html += "</ul>"; container.html(html); }); }); });
Vo file facebook_events.css: .facebook-events { padding: 10px; width: 400px; float: left; } .facebook-events ul { padding: 0;
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 padding: 10px; margin: 2px; } Vo protected/views/site/index.php <?php $this->widget("ext.facebook_events.EFacebookEvents", array( 'keyword' => 'php', ))?>
<?php $this->widget("ext.facebook_events.EFacebookEvents", array( 'keyword' => 'jquery', ))?> Gi vo trang ch xem kt qu:
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Khi chng ta s dng $this->widget trong site/index view, 2 phng thc trong EFacebookEvents u chy init ci m public assert v kt ni chng ti trang, sau chy render html. Nhng g c trong th mc :Assert Nu bn kim tra s thy nhng dng sau:
Th mc nh 1a6630a0 c s dng ngn chn va chm ca cc tp tin vi nhng ci tn tng t t cc th mc khc nhau. Tn ca th mc l mt hm bm m ha path assert directory.Trc assert t mi th mc c copy ti cng mt ni,iu ny ngha l th mc image,css,js public ca bn c th tham chiu ti images,css,js t cc ng dn lien quan.
4. Lm vic vi JSON
JSON rt n gin,d s dng, l s dng nh dng AJAX application data.YII cng c lm vic vi n. u tin ta vo phpmyadmin v to mi table : Tin tc: CREATE TABLE `news` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `created_on` int(11) unsigned NOT NULL, `title` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) Tip theo bn vo GII ri gererated Model, bn g news v nhn generated. Sau khi thnh cng kim tra ti protected/models xem c file new cha ? Vo protected/controllers to NewsController.php <?php class NewsController extends Controller {
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 return array( 'ajaxOnly + data',
); } public function actionIndex() { $this->render('index'); } public function actionData() { $criteria = new CDbCriteria(); $criteria->order = 'created_on DESC'; $criteria->limit = 10; $news = News::model()->findAll($criteria); echo CJSON::encode($news); } public function actionAddRandomNews() { $news = new News(); $news->title = "Item #".rand(1, 10000); $news->created_on = time();
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Tip theo bn to views: protected/views/news/index.php
<div class="news-list"> Loading </div> <?php Yii::app()->clientScript->registerCoreScript("jquery")?> <script type="text/javascript"> jQuery(function($) { var newsList = $('.news-list'); function updateNews(){ newsList.html("Loading"); $.ajax({ url: "<?php echo $this->createUrl('data')?>", dataType: 'json', cache: false, success: function(data) { var out = "<ol>"; $(data).each(function(){ out+="<li>"+this.title+"</li>"; }); out += "</ol>"; newsList.html(out);
153
} }); } updateNews();
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 setInterval(function(){ updateNews() }, 2000); }); </script> Sau thc hin xong vo trnh duyt g: http://localhost/skybook/index.php/news/index
5: X l bin s ca input
i khi ng dng yu cu nhp form cha bin s ca input,mt chc nng qun l ng dng c th cung cp hnh nh,ni bn c th them mt hoc nhiu chc nng trong danh sch task,bn c th xem v d di y:
153
Bi mc nh, trang s hin th mt vi chc nng v hai button: Add task s them thuc tnh v save l lu li thong tin ca form. Ta s to protected/models file Task.php: <?php class Task extends CFormModel { public $title; public $text; public function rules() //thiet lap quy tac { return array( array('title', 'required'), // tieu de khong rong array('text', 'safe'), //text duoc bao ve
153
); } }
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Tip theo vo protected/controllers/TaskController.php <?php class TaskController extends Controller { public function filters() { return array( 'ajaxOnly + field' ); } public function actionIndex() { $models = array(); if(!empty($_POST['Task'])) //kiem tra co request post hay k { foreach($_POST['Task'] as $taskData) { $model = new Task(); $model->setAttributes($taskData); if($model->validate()) $models[] = $model; }
153
} if(!empty($models)){ // Neu ban muon luu lai du lieu co the luu tai day }
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 else $models[] = new Task(); $this->render('index', array( 'models' => $models, )); } public function actionField($index) { $model = new Task(); $this->renderPartial('_task', array( 'model' => $model, 'index' => $index, )); } }
Ta to view: protected/views/task/index.php <div class="form"> <?php echo CHtml::beginForm()?> <ul class="tasks"> <?php for($i=0; $i<count($models); $i++):?> <?php $this->renderPartial('_task', array(
153
'model' => $models[$i], 'index' => $i, ))?> <?php endfor ?>
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 </ul> <div class="row buttons"> <?php echo CHtml::button('Add task', array('class' => 'tasks-add'))?> <?php Yii::app()->clientScript->registerCoreScript ("jquery")?> <script> $(".tasks-add").click(function(){ $.ajax({ success: function(html){ $(".tasks").append(html); }, type: 'get', url: '<?php echo $this->createUrl('field')?>', data: { index: $(".tasks li").size() }, cache: false, dataType: 'html' }); }); </script>
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Cui cng to views cho partial: protected/views/task/_task.php <li> <div class="row"> <?php echo CHtml::activeLabel($model, "[$index]title")?> <?php echo CHtml::activeTextField($model, "[$index]title")?> </div> <div class="row"> <?php echo CHtml::activeLabel($model, "[$index]text")?> <?php echo CHtml::activeTextArea($model, "[$index]text")?> </div> </li> Vo trnh duyt g http://localhost/skybook/task/index xem kt qu.
CHNG 4
Chng ny bn s khm ph:
153
LM VIC VI FORM
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 To mt custom widget vi Cwidget
1. Uploading files
Trong folder protected bn to mt th mc mi c tn: uploads Chng ta s bt u vi model, v vy s to protected/models/Upload.php <?php class Upload extends CFormModel { public $file; public function rules() { return array(//yeu cau thuoc tinh file c th them cc thuc tnh khc cch nhau du //phy array('file', 'file', 'types'=>'zip'), ); } } Trong protected/controllers to UploadController.php <?php class UploadController extends Controller {
function actionIndex() {
153
$dir = Yii::getPathOfAlias('application.uploads'); //hien thi duong dan upload $uploaded = false; $model=new Upload(); //goi model
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 if(isset($_POST['Upload'])) { $model->attributes=$_POST['Upload']; $file=CUploadedFile::getInstance($model,'file'); if($model->validate()){ //validate form thanh cong thi luu file do vao thu muc $uploaded = $file->saveAs($dir.'/'.$file->getName()); } } $this->render('index', array( //hien thi thong tin ten file, duong dan 'model' => $model, 'uploaded' => $uploaded, 'dir' => $dir, )); } } Tip theo ta to views: protected/views/upload/index.php <?php if($uploaded):?> <p>File was uploaded. Check <?php echo $dir?>.</p> <?php endif ?> <?php echo CHtml::beginForm('','post',array ('enctype'=>'multipart/form-data'))?> <?php echo CHtml::error($model, 'file')?>
153
<?php echo CHtml::activeFileField($model, 'file')?> <?php echo CHtml::submitButton('Upload')?> <?php echo CHtml::endForm()?> Vo trnh duyt g: http://localhost/skybook/index.php/upload/index
http://www.seodrupal.vn | Learn Drupal Online
2. Thm Captcha
To protected/models/EmailForm.php <?phpclass EmailForm extends CFormModel { public $email; function rules(){ return array( array('email', 'email'), ); } } To protected/controller/EmailController.php
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 { $success = false; $model = new EmailForm(); if(!empty($_POST['EmailForm'])) { $model->setAttributes($_POST['EmailForm']); if($model->validate()) { $success = true; // handle form here } } $this->render('index', array( 'model' => $model, 'success' => $success, )); } } To views: protected/email/index.php <?php if($success):?> <p>Success!</p> <?php endif?>
153
<?php echo CHtml::beginForm()?> <p> <?php echo CHtml::activeLabel($model, 'email')?> <?php echo CHtml::activeTextField($model, 'email')?>
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 <?php echo CHtml::error($model, 'email')?> </p> <p> <?php echo CHtml::submitButton()?> </p> <?php echo CHtml::endForm()?> Vo http://localhost/skybook/index.php/email/index test
3.Custom Captcha
Ta c th custom captcha mt cch d dng nh CCaptchaAction Trong protected/components to MathCaptchaAction.php <?php class MathCaptchaAction extends CCaptchaAction {
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } public function renderImage($code) { parent::renderImage($this->getText($code)); } protected function getText($code) { $code = (int)$code; $rand = mt_rand(1, $code-1); $op = mt_rand(0, 1); if($op) return $code-$rand.+.$rand; else return $code+$rand.-.$rand; } } Trong controller trc them action sau: public function actions() { return array( 'captcha'=>array( 'class'=>'MathCaptchaAction',
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 { if($this->hasModel()) { echo CHtml::activeTextField ($this->model, $this->attributeFrom); echo ' → '; echo CHtml::activeTextField ($this->model, $this->attributeTo); } else { echo CHtml::textField($this->nameFrom, $this->valueFrom); echo ' → '; echo CHtml::textField($this->nameTo, $this->valueTo); } } } Tip theo vo protected/models RangeForm.php <?php class RangeForm extends CFormModel { public $from; public $to;
153
function rules() { return array( array('from, to', 'numerical', 'integerOnly' => true),
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 array('from', 'compare', 'compareAttribute' => 'to', 'operator' => '<=', 'skipOnError' => true), ); } } Tip theo vo protected/controllers to RangeController.php <?php class RangeController extends Controller { function actionIndex() { $success = false; $model = new RangeForm(); if(!empty($_POST['RangeForm'])) { $model->setAttributes($_POST['RangeForm']); if($model->validate()) $success = true; } $this->render('index', array( 'model' => $model, 'success' => $success,
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 <?php if($success):?> <p>Success!</p> <?php endif?> <?php echo CHtml::errorSummary($model)?> <?php echo CHtml::beginForm()?> <?php $this->widget('RangeInputField', array( 'model' => $model, 'attributeFrom' => 'from', 'attributeTo' => 'to', ))?> <?php echo CHtml::submitButton('Submit')?> <?php echo CHtml::endForm()?>
153
CHNG 5
Trong chng ny bn s khm ph: Nhn d liu t database S dng scopes hin th model vi cc ngn ng khc nhau Truy cp models field vi AR Applying Markdown v HTML Hightlight code vi Yii T ng timestamp Thit lp author t ng Thc thi cc bng k tha n S dng CDbCriteria
Hu ht ng dng ngy nay u s dng database,d l mt website nh cho ti mng x hi , t nht mt phn c bo v bi database,Yii gii thiu 3 cch lm vic trn database: Active Record
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Query Builder SQL v DAO thc hin bn vo : http://dev.mysql.com/doc/sakila/en/sakila.html ti gi database v sau vo phpmyadmin import vo csdl Tip theo vo Gii to model actor v field tables Ta vo protected /controller to DbController.php
153
<?php class DbController extends Controller { protected function afterAction($action) { $time = sprintf('%0.5f', Yii::getLogger() ->getExecutionTime()); $memory = round(memory_get_peak_usage()/(1024*1024),2)."MB"; echo "Time: $time, memory: $memory"; parent::afterAction($action); } public function actionAr() { $actors = Actor::model()->findAll(array('with' => 'films', 'order' => 't.first_name, t.last_name, films.title')); echo '<ol>'; foreach($actors as $actor) { echo '<li>'; echo $actor->first_name.' '.$actor->last_name; echo '<ol>'; foreach($actor->films as $film) { echo '<li>'; echo $film->title; echo '</li>'; } echo '</ol>'; echo '</li>'; } echo '</ol>'; } public function actionQueryBuilder() {
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $rows = Yii::app()->db->createCommand() ->from('actor') ->join('film_actor', 'actor.actor_id=film_actor.actor_id') ->leftJoin('film', 'film.film_id=film_actor.film_id') ->order('actor.first_name, actor.last_name, film.title') ->queryAll(); $this->renderRows($rows); } public function actionSql() { $sql = "SELECT *
153
FROM actor a JOIN film_actor fa ON fa.actor_id = a.actor_id JOIN film f ON fa.film_id = f.film_id ORDER BY a.first_name, a.last_name, f.title"; $rows = Yii::app()->db->createCommand($sql)->queryAll(); $this->renderRows($rows); } public function renderRows($rows) { $lastActorName = null; echo '<ol>'; foreach($rows as $row) { $actorName = $row['first_name'].' '.$row['last_name']; if($actorName!=$lastActorName){ if($lastActorName!==null){ echo '</ol>'; echo '</li>'; } $lastActorName = $actorName; echo '<li>'; echo $actorName; echo '<ol>'; } echo '<li>'; echo $row['title']; echo '</li>'; } echo '</ol>'; } } Sauk hi thc hin xong bn chy trn trnh duyt v vo databse kim tra d liu mi to.
http://www.seodrupal.vn | Learn Drupal Online
bt u to mi databse: vo phpmyadmin v chn mc SQL : DROP TABLE IF EXISTS `post`; CREATE TABLE IF NOT EXISTS `post` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `lang` VARCHAR(5) NOT NULL DEFAULT 'en', `title` VARCHAR(255) NOT NULL, `text` TEXT NOT NULL, PRIMARY KEY (`id`) ); INSERT INTO `post`(`id`,`lang`,`title`,`text`) VALUES (1,'en_us','Yii news','Text in English'), (2,'de','Yii Nachrichten','Text in Deutsch'); Sau khi hon tt vo GII chn model generated g Post vo modelname v generated Sauk hi generated bn vo models/Post.php v vit li method ging nh sau: class Post extends CActiveRecord { public function defaultScope() {
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 ':lang' => Yii::app()->language, ), ); } public function lang($lang){ $this->getDbCriteria()->mergeWith(array( 'condition' => "lang=:lang", 'params' => array( ':lang' => $lang, ), )); return $this; } } Tip theo vo protected/controllers/DbtestController.php <?php class DbtestController extends CController { public function actionIndex() { // Hin th ngn ng mc nh $posts = Post::model()->findAll();
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 echo $post->text; } // Hin th ngn ng ca c $posts = Post::model()->lang('de')->findAll(); echo '<h1>German</h1>'; foreach($posts as $post) { echo '<h2>'.$post->title.'</h2>'; echo $post->text; } } } Sauk hi hon thnh vo trnh duyt g : http://localhost/skybook/dbtest/index
CREATE TABLE IF NOT EXISTS `post` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `title` VARCHAR(255) NOT NULL,
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 `text` TEXT NOT NULL, PRIMARY KEY (`id`) );
Tip theo vo Gii generated model Post Sau bn vo models/Post.php v thm hm sau: protected function beforeSave() { $this->text = preg_replace('~((?:https?|ftps?)://.*?)( |$)~iu', '<a href="\1">\1</a>\2', $this->text); return parent::beforeSave(); } Tip theo vo protected/controllers to TestController.php <?php class TestController extends CController { function actionIndex() { $post=new Post(); $post->title='links test'; $post->text='test http://www.p cht m tu kha.vn/ test';
153
$post->save(); print_r($post->text); } }
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Vo tnh duyt g http://localhost/skybook/test/index xem kt qu. Cch lm vic nh sau: beforeSave (trc khi lu) c nh ngha trong CActiveRecord class v ch thc hin hm trc khi lu models.Bi s dng biu thc quy tc, chng thay th mi th ging mt url vi mt link c s dng v gi li hm thc thi cha,s kin thc t l raised propery , trong hm saving bn c th tr v gi tr false. Mt s method bn nn bit:
AfterConstruct : Hm c gi sau khi mt model c khi to bi m ngun beforeDelete/afterDelete : Hm c gi trc/sau khi bn ghi b xa beforeSave/afterSave: Hm c khi to trc khi/sau khi lu bn ghi thnh cng. beforeValidate/afterValidate: Hm c gi khi khi to trc/sau khi validation form kt thc.
`id` int(11) unsigned NOT NULL auto_increment, `title` varchar(255) NOT NULL, `code` text NOT NULL, `html` text NOT NULL,
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 `language` varchar(20) NOT NULL, PRIMARY KEY (`id`) ); Tip theo vo Giii generated model Snippet Sauk hi generate thnh cng bn thay i hm rules trong Snippet.php protected/models/Snippet.php public function rules() { return array( array('title, code, language', 'required'), array('title', 'length', 'max'=>255), array('language', 'length', 'max' => 20), ); } Thm method sau khi validate: protected function afterValidate() { $highlighter = new CTextHighlighter(); $highlighter->language = $this->language; $this->html = $highlighter->highlight($this->code); return parent::afterValidate(); }
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 'php' => 'PHP', 'css' => 'CSS', 'html' => 'HTML', 'javascript' => 'JavaScript', ); } Tip theo vo protected/controller to SnippetController.php <?php class SnippetController extends CController { public function actionIndex() { $criteria = new CDbCriteria(); $criteria->order = 'id DESC'; $models = Snippet::model()->findAll(); $this->render('index', array( 'models' => $models, )); } public function actionView($id) { $model = Snippet::model()->findByPk($id);
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 )); } public function actionAdd() { $model = new Snippet(); $data = Yii::app()->request->getPost('Snippet'); if($data) { $model->setAttributes($data); if($model->save()) $this->redirect(array('view', 'id' => $model->id)); } $this->render('add', array( 'model' => $model, )); } public function actionEdit($id){ $model = Snippet::model()->findByPk($id); if(!$model) throw new CHttpException(404); $data = Yii::app()->request->getPost('Snippet'); if($data)
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } $this->render('edit', array( 'model' => $model, )); } }
Tip theo ta to view trong protected/views/snippet/index.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), array('view', 'id' => $model->id) )?> </li> <?php endforeach?> </ol> To tip view th 2 : protected/views/snippet/view.php <h2><?php echo CHtml::link('Snippets', array('index'))?> <?php
153
echo CHtml::encode($model->title)?> </h2> <?php echo CHtml::link('Edit', array ('edit', 'id' => $model->id))?>
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 <div> <?php echo $model->html?> </div> To view add : protected/views/snippet/add.php <h2><?php echo CHtml::link('Snippets', array('index'))?> Add snippet </h2> <?php $this->renderPartial('_form', array('model' => $model))?> To view edit: protected/views/snippet/edit.php <h2><?php echo CHtml::link('Snippets', array('index'))?> Edit snippet </h2> <?php $this->renderPartial('_form', array('model' => $model))?> To view _form : protected/views/snippet/_form.php <?php echo CHtml::beginForm()?> <ul> <li> <?php echo CHtml::activeLabel($model, 'title')?> <?php echo CHtml::activeTextField($model, 'title')?> </li> <li> <?php echo CHtml::activeLabel($model, 'code')?>
153
<?php echo CHtml::activeTextArea($model, 'code')?> </li> <li> <?php echo CHtml::activeLabel($model, 'language')?>
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 <?php echo CHtml::activeDropDownList($model, 'language', $model->getSupportedLanguages())?> </li> <li> <?php echo CHtml::submitButton('Save')?> </li> </ul> <?php echo CHtml::endForm()?> Sauk hi hon thnh vo trnh duyt g : http://localhost/skybook/snippet/index T t tn hng hiu ng:
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Cu trc k tha n gin nh: Xe |-> Xe th thao |->Xe du lch |->Xe gia nh. bt u ta vo phpmyadmin chn sql v chy query sau: CREATE TABLE `car` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `type` varchar(100) NOT NULL, PRIMARY KEY (`id`) ); INSERT INTO `car` (`name`, `type`) VALUES ('Ford Focus', 'family'), ('Opel Astra', 'family'), ('Kia Ceed', 'family'), ('Porsche Boxster', 'sport'), ('Ferrari 550', 'sport'); Ta generated model Car trong Gii Trong Protected/models/Car.php ta sa li nh sau: <?php class Car extends CActiveRecord
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } public function tableName() { return 'car'; } protected function instantiate($attributes) { switch($attributes['type']) { case 'sport': $class='SportCar'; break; case 'family': $class='FamilyCar'; break; default: $class=get_class($this); } $model=new $class(null); return $model; } }
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 public static function model($className=__CLASS__) { return parent::model($className); } public function defaultScope() { return array( 'condition'=>"type='sport'", ); } } Tip theo ta cng k tha cho protected/models/FamilyCar.php <?php class FamilyCar extends Car { public static function model($className=__CLASS__) { return parent::model($className); } public function defaultScope() { return array(
153
'condition'=>"type='family'", ); } }
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Trong protected/controller to TestController.php <?php class TestController extends CController { public function actionIndex() { echo "<h1>All cars</h1>"; $cars = Car::model()->findAll(); foreach($cars as $car) { // Mi chic xe c th l ca class car, sportcar, hoc 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 xui vo trnh duyt g : http://localhost/skybook/test/index
153
6. S dng CdbCriteria
Khi s dng Active Record method nh findAll, hoc find, chng ta c th nhn tiu chun ging nh tham s,n c th tr v mng hay mt khi to ca CdbCriteria class.Class ny hin th query tiu chun, ging nh iu kin,ordering by,limit/offset, vv Thng thng n hay c s dng nh di 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); Cch lm vic: Bn thn class Criteria khng xy dng query, nhng ch hin th d liu hoc cho php iu chnh chng, Hm lm vic thc t nm trong Active Record method ni cc tiu chun ca class ny s dng.
153
Dch code c th c nh sau: Hin th 10 dng post vi comment t approved post vi id trong khong 4,8,15,16,24 hoc 42 order by id.
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Select * from post p (nh danh post) JOIN (ni) comment c(nh danh comment) ON (iu kin ni) 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.
CHNG 6
153
K THA Yii
Trong chng ny, bn s khm ph: S dng data provides S dng grids (li) S dng lists (danh sch) To custom grid column( Ct li)
Yii c th vin hu ch gi l Zii, n ng hnh cng vi framework v mt s class khc gip cho vic pht trin tr ln d dng hn bao gi ht,hu ht thnh phn ch yu l grid v list ci cho php bn xy dng d liu trong Admin v user website rt nhanh v p. Trong chng ny bn s hc cch iu chnh component v nhng th bn cn,bn s hc v data provides,chng l mt phn trong core framework.
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $this->render('index', array( 'dataProvider' => $dataProvider, )); } public function actionArray() { $yiiDevelopers = array( array( 'name'=>'Qiang Xue', 'id'=>'2', 'forumName'=>'qiang', 'memberSince'=>'Jan 2008', 'location'=>'Washington DC, USA', 'duty'=>'founder and project lead', 'active'=>true, ), array( 'name'=>'Wei Zhuo', 'id'=>'3', 'forumName'=>'wei', 'memberSince'=>'Jan 2008', 'location'=>'Sydney, Australia',
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 'name'=>'Sebastin Thierer', 'id'=>'54', 'forumName'=>'sebas', 'memberSince'=>'Sep 2009', 'location'=>'Argentina', 'duty'=>'component development', 'active'=>true, ), array( 'name'=>'Alexander Makarov', 'id'=>'415', 'forumName'=>'samdark', 'memberSince'=>'Mar 2010', 'location'=>'Russia', 'duty'=>'core framework development', 'active'=>true, ), array( 'name'=>'Maurizio Domba', 'id'=>'2650', 'forumName'=>'mdomba', 'memberSince'=>'Aug 2010',
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 array( 'name'=>'Y!!', 'id'=>'1644', 'forumName'=>'Y!!', 'memberSince'=>'Aug 2010', 'location'=>'Germany', 'duty'=>'core framework development', 'active'=>true, ), array( 'name'=>'Jeffrey Winesett', 'id'=>'15', 'forumName'=>'jefftulsa', 'memberSince'=>'Sep 2010', 'location'=>'Austin, TX, USA', 'duty'=>'documentation and marketing', 'active'=>true, ), array( 'name'=>'Jonah Turnquist', 'id'=>'127', 'forumName'=>'jonah',
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 ), array( 'name'=>'Istvn Beregszszi', 'id'=>'1286', 'forumName'=>'pestaa', 'memberSince'=>'Sep 2009 - Mar 2010', 'location'=>'Hungary', 'duty'=>'core framework development', 'active'=>false, ), ); $dataProvider = new CArrayDataProvider( $yiiDevelopers, array( 'sort'=>array( 'attributes'=>array('name', 'id', 'active'), 'defaultOrder'=>array('active' => true, 'name' => false), ), 'pagination'=>array( 'pageSize'=>10, ), )); $this->render('index', array(
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 { $count=Yii::app()->db->createCommand('SELECT COUNT(*) FROM film')->queryScalar(); $sql='SELECT * FROM film'; $dataProvider=new CSqlDataProvider($sql, array( 'keyField'=>'film_id', 'totalItemCount'=>$count, 'sort'=>array( 'attributes'=>array('title'), 'defaultOrder'=>array('title' => false), ), 'pagination'=>array( 'pageSize'=>10, ), )); $this->render('index', array( 'dataProvider' => $dataProvider, )); } } Vo localhost /skybook/grid/aR , grid/array v grid/sql xem kt qu:
153
3. S dng lists
Zii list l cng c kh tt cho vic trnh by d liu bt k data provider kt thc user khi x l phn trang v sp xp t ng.CListView l rt d dng trong vic custom v n cho php xy dng bt k thuc tnh no trong list page. Vo website : http://dev.mysql.com/doc/sakila/en/ sakila.html download c s d liu ri vo phpmyadmin import vo database Vo gii model generated to : customer,store,address,city Tip theo m gii,chn CRug generator v nhn Customer ti model class field, nhn preview v generated Gii s generated controller trong protected/controllers Chy index action ca customer controller ta c kt qu sau : http://localhost/skybook/customer/index
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 bn vo protected/views/customer/index.php v thay th bng ni dung sau : <?php $this->widget('zii.widgets.CListView', array( 'dataProvider'=>$dataProvider, 'itemView'=>'_view', 'sortableAttributes'=>array( 'last_name', 'email', ), )); ?> Customer templates: Thay th views vi ni dung sau: <?php $this->widget('zii.widgets.CListView', array( 'dataProvider'=>$dataProvider, 'itemView'=>'_view', 'sortableAttributes'=>array( 'last_name', 'email', ), 'template' => '{sorter} {pager} {items} {sorter} {pager}', )); ?> Customer markup data display <?php $this->widget('zii.widgets.CListView', array(
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 'sortableAttributes'=>array( 'last_name', 'email', ), 'template' => '{sorter} {pager} {items} {sorter} {pager}', )); ?> Tip theo vo protected/views/customer to _views.php <li> <h2> <?php $title = CHtml::encode($data->first_name.' '.$data->last_name); echo CHtml::link($title, array('view', 'id'=> $data->customer_id)); ?> </h2> <ul> <li> <strong><?php echo CHtml::encode($data-> getAttributeLabel('store_id')); ?>:</strong> <?php echo CHtml::encode($data->store-> address->address.', '.$data->store->address->city->city.', '.$data->store->address->district); ?>
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 <?php echo CHtml::encode($data->email); ?> </li> <li> <strong><?php echo CHtml::encode($data-> getAttributeLabel('address_id')); ?>:</strong> <?php echo CHtml::encode($data->address->address.', '.$data->address->city->city.', '.$data->address->district); ?> </li> <li> <strong><?php echo CHtml::encode($data-> getAttributeLabel('active')); ?>:</strong> <?php echo $data->active ? 'Yes' : 'No'; ?> </li> </ul> </li> Vo protected/assets to customer.css ol.customers { list-style: none; margin: 1em 0; } ol.customers>li {
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } Quay li file _views trong protected/views/customer v thm on sau vo di cng <?php Yii::app()->clientScript->registerCssFile( Yii::app()->assetManager->publish(Yii::getPathOfAlias('application. assets').'/customers.css'))?> Th li trn trnh duyt bng vic F5:
Cch thc hin : Trong table chng ta c mt field active (kch hot) , chng ta mun toggle vi flag column . Column s hin th 2 trng Y v N quyt nh gi tr tr v c cliking hay ko. Vo protected/components/ to FlagColumn.php
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 <?php class FlagColumn extends CGridColumn { public $name; public $sortable=true; public $callbackUrl = array('flag'); private $_flagClass = "flag_link"; public function init() { parent::init(); $cs=Yii::app()->getClientScript(); $gridId = $this->grid->getId(); $script = <<<SCRIPT jQuery(".{$this->_flagClass}").live("click", function(e){ e.preventDefault(); var link = this; $.ajax({ dataType: "json", cache: false, url: link.href, success: function(data){ $('#$gridId').yiiGridView.update('$gridId'); }
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } protected function renderDataCellContent($row, $data) { $value=CHtml::value($data,$this->name); $this->callbackUrl['pk'] = $data->primaryKey; $this->callbackUrl['name'] = urlencode($this->name); $this->callbackUrl['value'] = (int)empty($value); $link = CHtml::normalizeUrl($this->callbackUrl); echo CHtml::link(!empty($value) ? 'Y' : 'N', $link, array( 'class' => $this->_flagClass, )); } protected function renderHeaderCellContent() { if($this->grid->enableSorting && $this->sortable && $this->name!==null) echo $this->grid->dataProvider->getSort()->link( $this->name,$this->header); else if($this->name!==null && $this->header===null) { if($this->grid->dataProvider instanceof CActiveDataProvider) echo CHtml::encode($this->grid->dataProvider-> model->getAttributeLabel($this->name));
153
Tip theo vo protected/controllers/CustomerController.php v thay i action Flag public function actionFlag($pk, $name, $value){ $model = $this->loadModel($pk); $model->{$name} = $value; $model->save(false); if(!Yii::app()->request->isAjaxRequest){ $this->redirect('admin'); } } Cui cng vo protected/views/customer/admin.php Thay i dng widget: <?php $this->widget('zii.widgets.grid.CGridView', array( 'id'=>'customer-grid', 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( 'customer_id', 'store_id',
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 array( 'class' => 'FlagColumn', 'name' => 'active', ), /* 'create_date', 'last_update', */ array( 'class'=>'CButtonColumn', ), ), )); ?> Sau k hi thnh cng vo Http://localhost/skybook/customer/admin
153
Bn c th thy mt lot cng c kch hot, CRUD hin ln, customer tht d dng ng ko , t m tu kha.
CHNG 7
Trong chng ny bn s khm ph: To component To controller action To reusable controller To mt widget To CLI commands To filter To modules To mt customer view renderer Lm m rng distribution-ready
K THA Yii
1. To component
Nu bn c mt vi on code c th ti s dng c nhng bn khng bit cch thc,widget,behavior hy s dng component. Component k tha t CComponent hoc CApplicationComponent.Sau mt component c th kch hot ti ng dng v cu hnh s dng trong protected/config/main.php. v d chng ta nh ngha: EImageManage ng dng thnh phn s dng resize nh s dng th vin GD, kch hot n ti ng dng v s dng n. Vo protected/components to EImageManage.php <?php class EImageManager extends CApplicationComponent
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 protected $newWidth; protected $newHeight; public function resize($width = false, $height = false){ if($width!==false) $this->newWidth = $width; if($height!==false) $this->newHeight = $height; return $this; } public function load($filePath) { list($this->width, $this->height, $type) = getimagesize($filePath); switch ($type) { case IMAGETYPE_GIF: $this->image = imagecreatefromgif($filePath); break; case IMAGETYPE_JPEG: $this->image = imagecreatefromjpeg($filePath); break; case IMAGETYPE_PNG: $this->image = imagecreatefrompng($filePath); break;
153
default: throw new CException('Unsupported image type ' . $type); } return $this;
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } public function save($filePath) { $ext = pathinfo($filePath, PATHINFO_EXTENSION); $newImage = imagecreatetruecolor($this->newWidth, $this->newHeight); imagecopyresampled($newImage, $this->image, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->width, $this->height); switch($ext) { case 'jpg': case 'jpeg': imagejpeg($newImage, $filePath); break; case 'png': imagepng($newImage, $filePath); break; case 'gif': imagegif($newImage, $filePath); break; default:
153
imagedestroy($newImage);
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 if(!is_file($filePath)) throw new CException("Failed to write image."); } function __destruct() { imagedestroy($this->image); } } Tip theo vo main.php trong protected/config kch hot: Tm v thm vo on sau : // application components 'components'=>array( 'image' => array( 'class' => 'EImageManager', ), Tip theo chng ta s s dng on component mi nh sau: Yii::app()->image ->load(Yii::getPathOfAlias('webroot').'/src.png') ->resize(100,100) ->save(Yii::getPathOfAlias('webroot').'/dst.png');
153
T i application component t n t i
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Hu ht thi gian chng ta cn to ng dng thnh phn ca ring ta, tuy nhin vic ti code tn ti gip ta gim thi gian lp trnh v tit kim cng sc. V d hin user role t databse s dng Yii::app()->user->role c th k tha t CwebUser component ging nh sau: <?php class WebUser extends CWebUser { private $_model = null; function getRole() { if($user = $this->getModel()){ return $user->role; } else return 'guest'; } private function getModel(){ if($this->_model === null){ if($this->id === null) return null; $this->_model = User::model()->findByPk($this->id); } return $this->_model; } } V trong main.php ta phi cu hnh li nh sau:
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 'user'=>array( 'class' => 'WebUser', // other properties ),
2. To controller action
Trc tin bn vo phpmyadmin chn sql v thc hin query sau: CREATE TABLE `post` ( `id` int(11) NOT NULL auto_increment, `text` text, `title` varchar(255) default NULL, PRIMARY KEY (`id`) ); CREATE TABLE `comment` ( `id` int(11) NOT NULL auto_increment, `text` text, PRIMARY KEY (`id`) ); Generated model vi : post v comment trong Gii. Vo protected/extensions/actions to EDeleteAction.php <?php class EDeleteAction extends CAction
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 * Runs the action. * This method is invoked by the controller owning this action. */ public function run($pk) { CActiveRecord::model($this->modelName)->deleteByPk($pk); if(Yii::app()->getRequest()->getIsAjaxRequest()) { Yii::app()->end(200, true); } else { $this->getController()->redirect($this->redirectTo); } } } Tip theo vo kch hot controller : protected/controllers/ to DeleteController.php: <?php class DeleteController extends CController { public function actions() {
153
return array( 'deletePost' => array( 'class' => 'ext.actions.EDeleteAction', 'modelName' => 'Post',
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 'redirectTo' => array('indexPosts'), ), 'deleteComment' => array( 'class' => 'ext.actions.EDeleteAction', 'modelName' => 'Comment', 'redirectTo' => array('indexComments'), ), ); } public function actionIndexPosts() { echo "I'm index action for Posts."; } public function actionIndexComments() { echo "I'm index action for Comments."; } }
3. To reusable Controller
Trong Yii bn c th ti s dng controller , nu bn to nhiu ng dng vi controller c thuc tnh ging nhau, di chuyn tt c cc lnh code ti controller ti s dng s tit kim nhiu thi gian cho bn.
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 Trong bi ny,chng ta s to n gin api controller s c thi hnh vi JSON,CRUD API cho mt model, n s a input data t POST hoc GET v s s l bng JSON data tip theo l HTTP code Vo Gii,to 1 model generated l Post Tip theo vo protected/extensions/ to json_api to JsonApiController.php: <?php class JsonApiController extends CController { const RESPONSE_OK = 'OK'; const RESPONSE_NO_DATA = 'No data'; const RESPONSE_NOT_FOUND = 'Not found'; const RESPONSE_VALIDATION_ERRORS = 'Validation errors'; public $modelName; public function init() { parent::init(); if(empty($this->modelName)) throw new CException("You should set modelName before using JsonApiController."); } public function actionCreate() { if(empty($_POST))
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 if($model->save()) $this->respond(200, self::RESPONSE_OK); else $this->respond(400, self::RESPONSE_VALIDATION_ERRORS, $model->getErrors()); } public function actionGet($pk) { $model = CActiveRecord::model ($this->modelName)->findByPk($pk); if(!$model) $this->respond(404, self::RESPONSE_NOT_FOUND); $this->respond(200, self::RESPONSE_OK, $model->getAttributes()); } public function actionUpdate($pk) { if(empty($_POST)) $this->respond(400, self::RESPONSE_NO_DATA); $model = CActiveRecord::model ($this->modelName)->findByPk($pk); if(!$model)
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 else $this->respond(400, self::RESPONSE_VALIDATION_ERRORS, $model->getErrors()); } public function actionDelete($pk) { if(CActiveRecord::model($this->modelName)->deleteByPk($pk)) { $this->respond(200, self::RESPONSE_OK); } else { $this->respond(404, self::RESPONSE_NOT_FOUND); } } protected function respond($httpCode, $status, $data = array()) { $response['status'] = $status; $response['data'] = $data; echo CJSON::encode($response); Yii::app()->end($httpCode, true); } }
153
Tip theo bn cn kt ni t i ng dng vi protected/conFig/main.php N c th hon thnh vic thm con troller,cu hnh ti controllerMap property ca CwebApplication v tat hay th cu hnh sau trong main.php
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 'controllerMap' => array( 'api' => array( 'class' => 'ext.json_api.JsonApiController', 'modelName' => 'Post', ), ),
Chng ta cn kt ni ti controller v c bit n s lm vic vi post model. Bn s cn form ti post data nhng nu bn c mt s d liu tn ti bn c th s dng phng thc nhn bng cch http://localhost/skybook/api/get/pk/1 ng dng tr v cho bn nh sau: {"status":"OK","data":{"id":"1","text":"post1", "title":"post1","is_deleted":"0"}}
4. To mt widget
Mt widget l mt phn ti s dng ca khung nhn views n khng ch render mt s d liu m cn c mt s logic. N c th l mt s kin nhn d liu t models v s dng n trong bn thn views. Hy to mt widget v v mt chart biu ngh thut s dng google API. Trong protected/extensions/ to folder chart, to EChartWidget.php:
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 public $data=array(); public $labels=array(); public function run() { echo "<img src=\"http://chart.apis.google.com/chart?chtt=".urlencode ($this->title)."&cht=pc&chs=300x150&chd=". $this->encodeData($this->data)."&chl=".implode ('|', $this->labels)."\">"; } protected function encodeData($data) { $maxValue=max($data); $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789'; $chartData="s:"; for($i=0;$i<count($data);$i++) { $currentValue=$data[$i]; if($currentValue>-1) $chartData.=substr($chars,61*($currentValue/$maxValue),1); else
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } Tip theo vo protected/controllers/ to 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', ), )); } } Vo trnh duyt g : http://localhost/skybook/chart/index lu nh phi kt ni vi internet mi truy nhp vo c google th mi thy ci biu ny.
153
5. To filters (b lc)
Mt filters l mt class c th chy trc/sau mt action ang thc hin. N c th s dng v thay i ni dung thc hin hoc thay i output, trong v d ny bn s thc thi mt output n gin c filter vi compress HTML output v xa tt c mi nh dng. Vo protected/extensions/ to compress_html folder, to 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 Tip theo chng ta cn kt ni ti ng dng, chng ta vo protected/controllers/ SiteController v thm filter: public function filters() { return array( array( 'ext.compress_html.ECompressHtmlFilter' ), ); } Chy ng dng v kim tra source code ta s thy 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. To mt modules
Nu bn mun to mt ng dng y v mun s dng n vi vic custom theo bn, hu ht iu bn mun l vic bn cn phi to mt modules. Trong bi ny,chng ta s nhn vic to modules wiki,chng ta s khng focus user v qun l phn quyn v mi ngi iu khin mi th.
153
Trc tin vo php myadmin chn SQL : to query sau : CREATE TABLE `wiki` ( `id` varchar(255) NOT NULL, `text` text NOT NULL,
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 PRIMARY KEY (`id`) ) Generated : wiki model vi Gii Generated : wiki module vi Gii Di chuyn protected/models/wiki.php ti protected/modules/wiki/models/wiki.php Thm wiki ti moduels section ca protected/config/main.php 'modules'=>array( // uncomment the following to enable the Gii tool 'gii'=>array( 'class'=>'system.gii.GiiModule', 'password'=>false, ), 'wiki' ),
Cch thc hin: u tin hy thm wiki link ti CMarkdownParser. To protected/modules/wiki/components/wikiMarkdownParser.php: <?php class WikiMarkdownParser extends CMarkdownParser { public function transform($text) { $text = preg_replace_callback('~\[\[(.*?)(?:\|(.*?))?\]\]~',
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 protected function processWikiLinks($matches) { $page = $matches[1]; $title = isset($matches[2]) ? $matches[2] : $matches[1]; return CHtml::link(CHtml::encode($title), array( 'view', 'id' => $page, )); } }
Tip theo s dng getHtml method t protected/modules/wiki/models/wiki.php public function getHtml() { $parser = new WikiMarkdownParser(); return $parser->transform($this->text); } Chng ta to customer protected/modules/wiki/controller/DefaultController. Chng ta ch cn 2 action l views v edit. To protected/modules/wiki/controller/DefaultController.php class DefaultController extends Controller { public function actionIndex() {
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 { $model = Wiki::model()->findByPk($id); if(!$model) { $this->actionEdit($id); Yii::app()->end(); } $this->render('view', array( 'model' => $model, )); } public function actionEdit($id) { $model = Wiki::model()->findByPk($id); if(!$model) { $model = new Wiki(); $model->id = $id; } if(!empty($_POST['Wiki'])) { if(!empty($_POST['Wiki']['text']))
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } else { Wiki::model()->deleteByPk($id); } } $this->render('edit', array( 'model' => $model )); } }
Tip theo to views : protected/modules/wiki/views/default/view.php <h2> <?php echo CHtml::encode($model->id)?> [<?php echo CHtml::link('edit', array('edit', 'id' => $model->id))?>] </h2> <?php echo $model->html ?> To views edit: protected/modules/wiki/views/default/edit.php <h2>Editing <?php echo CHtml::encode($model->id)?></h2> <?php echo CHtml::beginForm()?>
153
<?php echo CHtml::activeTextArea($model, 'text', array('cols' => 100, 'rows' => 20))?> <br /><br /> <?php echo CHtml::submitButton('Done')?>
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 <?php echo CHtml::endForm()?> Xong xui vo http://localhost/skybook/wiki/index v localhost/skybook/wiki/edit
Tip theo vo main.php trong protected/config thay i : 'modules'=>array( // uncomment the following to enable the Gii tool 'gii'=>array( 'class'=>'system.gii.GiiModule', 'password'=>false, ), 'wiki'=>array( 'class' => 'ext.wiki.WikiModule' ), ),
Mi modules c to cha mt main modules class ging wikimodule ni chng ta c th nh ngha cu hnh thuc tnh,nh ngha import, thay i ng dn, kch hot controller, v nhiu hn.. Mc nh mi moduels generated vi Gii chy index action ca default controller:
153
Trong wiki module indexaction tat hay i nh sau: $model = Wiki::model()->findByPk($id); if(!$model) { $this->actionEdit($id); Yii::app()->end(); } $this->render('view', array( 'model' => $model, )); Nu modules ny gi mt ID chng ta s hin th n v s dng trong views. Nu khng c trang no gi ID, chng ta x l bi action khc: $model = Wiki::model()->findByPk($id); if(!$model) { $model = new Wiki(); $model->id = $id; } if(!empty($_POST['Wiki'])) {
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $this->redirect(array('view', 'id' => $id)); } else { Wiki::model()->deleteByPk($id); } } $this->render('edit', array( 'model' => $model )); NU KHNG C modules no s dng ID mi to,nu c mt models chng ta edit n,edit form data t POST v kim tra n rng hay khng chng ta delete models,nu c k t chng ta lu li.
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 public $fileExtension='.tpl'; public $filePermission=0755; private $smarty; function init() { Yii::import('application.vendors.smarty.*'); spl_autoload_unregister(array('YiiBase','autoload')); require_once('Smarty.class.php'); spl_autoload_register(array('YiiBase','autoload')); $this->smarty = new Smarty(); $this->smarty->template_dir = ''; $compileDir = Yii::app()->getRuntimePath ().'/smarty/compiled/'; if(!file_exists($compileDir)){ mkdir($compileDir, $this->filePermission, true); } $this->smarty->compile_dir = $compileDir; $this->smarty->assign('Yii', Yii::app()); } /** * Render mt file viws. * Phng thc c yu cu t {@link IViewRenderer}.
153
* @param CBaseController the controller or widget who is rendering the view file. * @param string the view file path * @param mixed the data to be passed to the view
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 * @param boolean whether the rendering result should be returned * @return mixed the rendering result, or null if the rendering result is not needed. */
public function renderFile($context,$sourceFile,$data,$return) { // current controller properties will be accessible as {this.property} $data['this'] = $context; if(!is_file($sourceFile) || ($file=realpath($sourceFile))= ==false) throw new CException(Yii::t('ext','View file "$sourceFile" does not exist.', array('{file}'=>$sourceFile))); $this->smarty->assign($data); if($return) return $this->smarty->fetch($sourceFile); else $this->smarty->display($sourceFile); } } Tip theo bn cn kt ni views renderer vi ng dng. Trong protected/config/main.php chng ta cn ti viewRenderer component:
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 'viewRenderer'=>array( 'class'=>'ext.smarty.ESmartyViewRenderer', ), ), Lu , trong component c d liu th bn nguyn ch vic thm vo : 'viewRenderer'=>array( 'class'=>'ext.smarty.ESmartyViewRenderer', ), By gi kim tra n, To protected/controllers/ To SmartyController.php <?php class SmartyController extends Controller { function actionNative() { $this->render('native', array( 'username' => 'Alexander', )); } function actionSmarty() {
153
Tip theo t o views: protected/views/smarty/native.php: Hello, <?php echo $username?>! protected/views/smarty/smarty.tpl: Hello, {$username}! By gi vo trnh duyt g : http://localhost/skybook/smarty/native Bn s thy dng : Hello,Alexander!
7. Lm extensions distribution-ready
Trong chng ny bn c hc rt nhiu cc to thuc tnh t Yii extensions. By gi chng ta ni v cch chia s thnh qu ca bn vi mi ngi v ti sao n li quan trong. Hy check trong form sau nhng iu bn suy ngh l ng nht v extensions Ni dung trong sang, d c v s dng trong API Ti liu tt Mi ngi u c th tm thy n Extensions p dng c hu ht trong ng dng user S l thnh phn chnh Tt cho vic test code, to nn tng cho tng vi bi test Bn cn c cung cp h tr cho n Tt nhin tt c yu t trn u c yu cu thc s cn thit to ra mt sn phm tt.
153
CHNG 8
S dng controller filter
BO MT
S dng CHtml v CHtmlPurifier ti s kin XSS Khm ph SQL injection Khm ph CSRF S dng RBAC
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 public function actionAuthOnly() { echo "Looks like you are authorized to run me."; } public function actionIp() { echo "Your IP is in our list. Lucky you!"; } public function actionUser() { echo "You're the right man. Welcome!"; } } Tip theo ta thm b lc sau: public function filters() { return array( 'accessControl', ); }
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 'expression' => 'strpos($_SERVER[\'HTTP_USER_AGENT\'], \'MSIE\') !== FALSE', 'message' => "You're using the wrong browser, sorry.", ), array( 'allow', 'actions' => array('authOnly'), 'users' => array('@'), ), array( 'allow', 'actions' => array('ip'), 'ips' => array('127.0.0.1'), ), array( 'allow', 'actions' => array('user'), 'users' => array('admin'), ), array('deny'), ); }
153
http://localhost/skybook/access/authonly , thay autheronly bng ip, user test By gi chng ta s th controller trn trnh duyt s dng c 2 ti khon admin v demo s u c kt qu sau
153
ng nhin trong v d ny khch ch s dng mt hm alert thong s, nhng trong form data ca bn cha nhiu d liu mt th iu tht thot l kh trnh, Yii a ra gii php sau: class XssController extends CController { public function actionSimple() { echo 'Hello, '.CHtml::encode($_GET['username']).'!'; } }
Tip theo s dng CHtmlPurifier gip loi b nhng thong tin tha do pha my khch t nhp vo
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 { $this->beginWidget('CHtmlPurifier'); echo $_GET['html']; $this->endWidget(); } public function actionHtml() { $purifier=new CHtmlPurifier(); echo $purifier->purify($_GET['html']); } Ta vo trnh duyt g http://localhost/skybook/xss/html? html=Hello,<strong>username</strong>!<script>alert(XSS);</script> s c kt qu sau:
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(100) NOT NULL, `password` varchar(32) NOT NULL,
http://www.seodrupal.vn | Learn Drupal Online
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 PRIMARY KEY (`id`) ); INSERT INTO `user`(`id`,`username`,`password`) VALUES ( '1','Alex' ,'202cb962ac59075b964b07152d234b70'); INSERT INTO `user`(`id`,`username`,`password`) VALUES ( '2','Qiang ','202cb962ac59075b964b07152d234b70'); Tip theo generated model : User s dng Gii Vo protected/controllers/ to SqlController.php <?php class SqlController extends CController { public function actionSimple() { $userName = $_GET['username']; $password = md5($_GET['password']); $sql = "SELECT * FROM user WHERE username = '$userName' AND password = '$password' LIMIT 1;"; $user = Yii::app()->db->createCommand($sql)->queryRow(); if($user) { echo "Success"; }
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } } Vo trnh duyt g : http://localhost/skybook/sql/simple? username=test&password=test bn s thy trnh duyt in : Failure. By gi thay http://localhost/skybook/sql/simple?username=%27+or+ %271%27%3D%271%2 7%3B+--&password=whatever. S thy hoc 1 =1; -N tng ng vi query : SELECT * FROM user WHERE username = '' or '1'='1'; --' AND password = '008c5926ca861023c1d2a36653fd88e2' LIMIT 1; fix vn ny bn thm vo controller action mi: public function actionPrepared() { $userName = $_GET['username']; $password = md5($_GET['password']); $sql = "SELECT * FROM user WHERE username = :username AND password = :password LIMIT 1;"; $command = Yii::app()->db->createCommand($sql); $command->bindValue('username', $userName); $command->bindValue('password', $password); $user = $command->queryRow();
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 } else { echo "Failure"; } }
4. S kin CSRF
CSRF hay XSRF vit tt cross-site l mt request gi ,mt vi th thut s dng c hi ca trnh duyt user m thm thc hin mt yu cu HTTP n vi trang web khi ngi dng ng nhp. Mt v d v cuc tn cng ny l chn mt th hnh nh v hnh vi src tr n http://example.com/site/logout. Thm ch nu cc th hnh nh c chn vo trong mt trang web khc,ngay lp tc bn s c ng nhp t example.com. Hu qu ca CSRF c th s rt nghim trng: ph hy d liu trang web, ngn chn tt c cc ngi s dng trang web ng nhp vo, phi by tin d liu, v hn th na Mt s thc trng ca CSRF: Nh CSRF nn c thc hin bi ngi s dng trnh duyt ca nn nhn, k tn cng c th khng thng thay i tiu HTTP c gi. Yii include mt token generation v token checking. Thm na c th t ng insert mt token trong HTML form: Vo protected/config/main.php thm on sau: 'components'=>array(
153
'request'=>array( 'enableCsrfValidation'=>true, ),
http://www.seodrupal.vn | Learn Drupal Online
Sauk hi cu hnh ng dng bn s dng C:Html::beginForm v CHtml::endForm khi to ca HTML form. public function actionCreate() { echo CHtml::beginForm(); echo CHtml::submitButton(); echo CHtml::endForm(); }
Yii s t ng thm mt token field n sau: <form action="/csrf/create" method="post"> <div style="display:none"><input type="hidden" value="e4d1021e79ac 269e8d6289043a7a8bc154d7115a" name="YII_CSRF_TOKEN" /> Nu bn lu form html v th submit,bn s nhn c mt li thong bo ging nh sau:
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 ... 'user'=>array( // enable cookie-based authentication 'allowAutoLogin'=>false, ), ... ),
Sau cho session timeout hot ng 'components' => array( ... 'session' => array( 'timeout' => 200, ), ... ), S dng thuc tnh GET v POST HTTP khng nh khng s dng GET cho cc hot ng thay i d liu hoc trng thi. Gn b vi nguyn tc ny l mt cch tt. N khng ngn cn tt c cc loi CSRF, nhng t nht s lm cho mt s mi trch nh <img src = tr ln v ngha....
5 . S dng RBAC
RBAC l phng php kim sot truy cp mnh m nht c sn trong Yii. N c m t trong ti liu hng dn,nhng k t khi n l kh phc tp v mnh m, n khng phi l d dng nh vy hiu lm th no n thc shot ng m khng nhn c hood . Trong bi ny, chng ta s lm r vai tr ca h thng phn cp t tiu chun hng dn, import n, v gii thch nhng g ang xy ra trong ni b. Vo protected/config/main.php sa li thong s ging nh sau:
http://www.seodrupal.vn | Learn Drupal Online
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 return array( 'components'=>array( 'authManager'=>array( 'class'=>'CDbAuthManager', 'connectionID'=>'db', ), ), );
Thm vo protected/components/UserIdentity.php on sau: $users=array( // username => password 'demo'=>'demo', 'admin'=>'admin', 'readerA'=>'123', 'authorB'=>'123', 'editorC'=>'123', 'adminD'=>'123', ); To protected/controllers/RbacController.php
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 { return array( 'accessControl', ); } public function accessRules() { return array( array( 'allow', 'actions' => array('deletePost'), 'roles' => array('deletePost'), ), array( 'allow', 'actions' => array('init', 'test'), ), array('deny'), ); } public function actionInit() {
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 $auth->createOperation('deletePost','delete a post'); $bizRule='return Yii::app()->user->id==$params ["post"]->authID;'; $task=$auth->createTask('updateOwnPost','update a post by author himself',$bizRule); $task->addChild('updatePost'); $role=$auth->createRole('reader'); $role->addChild('readPost'); $role=$auth->createRole('author'); $role->addChild('reader'); $role->addChild('createPost'); $role->addChild('updateOwnPost'); $role=$auth->createRole('editor'); $role->addChild('reader'); $role->addChild('updatePost'); $role=$auth->createRole('admin'); $role->addChild('editor'); $role->addChild('author'); $role->addChild('deletePost'); $auth->assign('reader','readerA'); $auth->assign('author','authorB'); $auth->assign('editor','editorC');
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 { echo "Post deleted."; } public function actionTest() { $post = new stdClass(); $post->authID = 'authorB'; echo "Current permissions:<br />"; echo "<ul>"; echo "<li>Create post: ".Yii::app()->user->checkAccess ('createPost')."</li>"; echo "<li>Read post: ".Yii::app()->user->checkAccess ('readPost')."</li>"; echo "<li>Update post: ".Yii::app()->user->checkAccess ('updatePost', array('post' => $post))."</li>"; echo "<li>Delete post: ".Yii::app()->user->checkAccess ('deletePost')."</li>"; echo "</ul>"; } } By gi vo localhost/skybook/rbac/init xem kt qu
153
[YII 1.1 APP DEVELOPMENT COOKBOOK ] August 28, 2012 t tn cc nt RBAC Mt h thng cp bc phc tp tr nn kh hiu m khng cn s dng mt s loi t tn mt hi ngh. Mt quy c gip khng lm cho chng ta nhm ln nh sau: [Group_] [own_] entity_action Trng hp ring c s dng khi quy tc xc nh kh nng sa i mt phn t ch khi ngi s dng hin nay l ch s hu ca cc yu t v nhm ch l mt khng gian tn. Thc th l mt tn ca thc th, chng ti ang lm vic v hnh ng l hnh ng m chng ti ang thc hin. V d, nu chng ta cn phi to ra mt quy tc xc nh nu ngi dng c th xa mt bi ng blog, chng ti s t tn n nh l blog_post_delete. Nu quy tc xc nh nu mt ngi dng c th chnh sa cc blog ca ring bnh lun, tn s c blog_own_comment_edit. Mt cch gi cho h thng phn cp n gin v hiu qu Theo nhng ngh khi c th ti a ha hiu sut v gim h thng phn cp phc tp: ff Trnh gn nhiu vai tr mt ngi dng duy nht. ff Khng kt ni cc nt cng loi. V vy, v d, trnh kt ni mt trong nhng nhim v mt s khc. gi cho h thng phn cp cn n gin, chng ta c th trnh vic to ra v s dng cc nt thm trong mt s trng hp bng cch thay th chng bng cc iu kin b sung. Mt v d l cc sa i ca Post. Chng ta c th to ra mt nt blog_own_post_edit vi bizRule nh sau: return Yii::app()->user->id==$params["post"]->author_id; Ngoi ra, chng ta c th thm cng mt logic thng xuyn la chn bi nh sau: $post = Post::model()->findByAttributes(array( 'id' => $id, 'author_id' => Yii::app()->user->id, )); If(!$post) throw new CHttpException(404); Bng cch s dng cch th hai, chng ta s trnh nhn c mt nt h thng phn cp RBAC do lu kho.
153