设计模式中,MVC结构是使用最多的。现在大部分PHP框架的必备标准就是拥有MVC模式。这是最基本的要求。如果不具备这个要求,就不能称之为框架,只能说是一个工具类集合。M-V-C中是控制器,可以认为是MVC结构的核心,调度者,像一个国家的领导人。大部分程序的实现还是在此部分,(如果没有涉及的很多数据逻辑的时候,因为对数据库的访问操作,我们大部分都可以用YII提供的功能实现,绝大部分无非就是CRUD。),所以你的MVC中C的代码决定了你的代码的质量。你的水平也可以通过C层的代码来衡量。当然这不是绝对的。
MVC结构中action也是很重要的角色。
控制器C的功能其实是action实现的。所以C如果是是领导人。那么他内部的action可以认为是一个个的政府官员。所以action决定了这个国家的。。。。aciton的所作所为,他的好坏决定了整个政府体系的好坏。所以作为一个aciton要做好自己的职责。为人民服务。
来看看YII中C的规则:
C类文件的存放位置以及规范:
一般是在protected/controllers文件夹中。如果你的框架中存在modules.就位于/protected/modules/模块名称/controllers下面
C类的文件名通常是一Controller.php结尾。的前面是你的类名。例如TestController.php。Test就是控制器的名称。如果是TestTestController.php,注意了默认的访问的时候的路由是第一个字母变为小写其他的保持不变。即http://www.localyii.com/testwebap/index.php?r=testTest。 对应View中文件夹应该为testTest和默认路由保持一直。所以C类的名称大小写敏感。并且敏感到VIew层。
C类的结构
1.必须extends Controller或者CController
2.类名一般和文件名保持一直必须一Controller结尾。
<?php class UserController extends Controller { }
<?php class SiteController extends CController { }
CController和Controller的关系是什么
看看代码
<?php /** * Controller is the customized base controller class. * All controller classes for this application should extend from this base class. */ class Controller extends CController { /** * @var string the default layout for the controller view. Defaults to '//layouts/column1', * meaning using a single column layout. See 'protected/views/layouts/column1.php'. */ public $layout='//layouts/column1'; /** * @var array context menu items. This property will be assigned to {@link CMenu::items}. */ public $menu=array(); /** * @var array the breadcrumbs of the current page. The value of this property will * be assigned to {@link CBreadcrumbs::links}. Please refer to {@link CBreadcrumbs::links} * for more details on how to specify this property. */ public $breadcrumbs=array(); }
可以看到他们之间的关系。看看注释就知道了他们直接的区别。可以认为Controller是CController边角料,实质上还是CController是做主要工作的。不信可以找到CController类的实现代码看看,就发现了。这里用Controller,毕竟可以少些一个字母。
下面看看控制器的内部的结构,打开SiteController.php文件
<?php class SiteController extends Controller { /** * Declares class-based actions. */ public function actions() { return array( // captcha action renders the CAPTCHA image displayed on the contact page 'captcha'=>array( 'class'=>'CCaptchaAction', 'backColor'=>0xFFFFFF, ), // page action renders "static" pages stored under 'protected/views/site/pages' // They can be accessed via: index.php?r=site/page&view=FileName 'page'=>array( 'class'=>'CViewAction', ), ); } /** * This is the default 'index' action that is invoked * when an action is not explicitly requested by users. */ public function actionIndex() { // renders the view file 'protected/views/site/index.php' // using the default layout 'protected/views/layouts/main.php' $this->render('index'); } /** * This is the action to handle external exceptions. */ public function actionError() { if($error=Yii::app()->errorHandler->error) { if(Yii::app()->request->isAjaxRequest) echo $error['message']; else $this->render('error', $error); } } /** * Displays the contact page */ public function actionContact() { $model=new ContactForm; if(isset($_POST['ContactForm'])) { $model->attributes=$_POST['ContactForm']; if($model->validate()) { $headers="From: {$model->email}\r\nReply-To: {$model->email}"; mail(Yii::app()->params['adminEmail'],$model->subject,$model->body,$headers); Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.'); $this->refresh(); } } $this->render('contact',array('model'=>$model)); } /** * Displays the login page */ public function actionLogin() { $model=new LoginForm; // if it is ajax validation request if(isset($_POST['ajax']) && $_POST['ajax']==='login-form') { echo CActiveForm::validate($model); Yii::app()->end(); } // collect user input data if(isset($_POST['LoginForm'])) { $model->attributes=$_POST['LoginForm']; // validate user input and redirect to the previous page if valid if($model->validate() && $model->login()) $this->redirect(Yii::app()->user->returnUrl); } // display the login form $this->render('login',array('model'=>$model)); } /** * Logs out the current user and redirect to homepage. */ public function actionLogout() { Yii::app()->user->logout(); $this->redirect(Yii::app()->homeUrl); } }
3.action方法的的规范可以从上述代码中看到。就是以action开头。然后是action的具体名称
类中有一个actions方法。看具体代码
/** * Declares class-based actions. */ public function actions() { return array( // captcha action renders the CAPTCHA image displayed on the contact page 'captcha'=>array( 'class'=>'CCaptchaAction', 'backColor'=>0xFFFFFF, ), // page action renders "static" pages stored under 'protected/views/site/pages' // They can be accessed via: index.php?r=site/page&view=FileName 'page'=>array( 'class'=>'CViewAction', ), ); }
public function actions() { // return external action classes, e.g.: return array( 'action1'=>'path.to.ActionClass', 'action2'=>array( 'class'=>'path.to.AnotherActionClass', 'propertyName'=>'propertyValue', ), ); }
public function createAction($actionID) { if($actionID==='') $actionID=$this->defaultAction; if(method_exists($this,'action'.$actionID) && strcasecmp($actionID,'s')) // we have actions method return new CInlineAction($this,$actionID); else { $action=$this->createActionFromMap($this->actions(),$actionID,$actionID); if($action!==null && !method_exists($action,'run')) throw new CException(Yii::t('yii', 'Action class {class} must implement the "run" method.', array('{class}'=>get_class($action)))); return $action; } } protected function createActionFromMap($actionMap,$actionID,$requestActionID,$config=array()) { if(($pos=strpos($actionID,'.'))===false && isset($actionMap[$actionID])) { $baseConfig=is_array($actionMap[$actionID]) ? $actionMap[$actionID] : array('class'=>$actionMap[$actionID]); return Yii::createComponent(empty($config)?$baseConfig:array_merge($baseConfig,$config),$this,$requestActionID); } else if($pos===false) return null; // the action is defined in a provider $prefix=substr($actionID,0,$pos+1); if(!isset($actionMap[$prefix])) return null; $actionID=(string)substr($actionID,$pos+1); $provider=$actionMap[$prefix]; if(is_string($provider)) $providerType=$provider; else if(is_array($provider) && isset($provider['class'])) { $providerType=$provider['class']; if(isset($provider[$actionID])) { if(is_string($provider[$actionID])) $config=array_merge(array('class'=>$provider[$actionID]),$config); else $config=array_merge($provider[$actionID],$config); } } else throw new CException(Yii::t('yii','Object configuration must be an array containing a "class" element.')); $class=Yii::import($providerType,true); $map=call_user_func(array($class,'actions')); return $this->createActionFromMap($map,$actionID,$requestActionID,$config); }
主要功能:
1.可以把action的功能放到一个单独的类文件中,这里就是可来绑定action和action的具体类文件。可以不action写到外部,其他的框架应该没这个功能。
例如。
自带的验证码的例子,生成验证码
http://www.localyii.com/testwebap/index.php?r=site/captcha
自定义例子
目录结构
├── controllers
│ ├── post
│ │ └── UpdateAction.php
│ ├── SiteController.php
│ ├── TestTestController.php
│ └── UserController.php
文件TestTestController.php
public function actions() { // return external action classes, e.g.: return array( 'update'=>'application.controllers.post.UpdateAction', ); }
文件UpdateAction.php
<?php class UpdateAction extends CAction { public function run() { exit('Test1 ,run update action') ; } }
http://www.localyii.com/testwebap/index.php?r=testTest/update
会看到打印如下结果
Test1 ,run update action
大体对控制器和action的使用有所了解了。具体的还需要慢慢写代码体会。具体的细节也需也自己在代码中学习理解。这里只是简单的例子。