Yii 框架提供有优秀的第三方扩展接口,我们通过一点点的改变,来完成类似于C# 中Html.RenderAction
我们都知道C#中的Html.RenderAction
是通过调用Action。重新执行一次Controller → Model → View的顺序。也就是说使用C#中的Html.RenderAction
方法会发起一次新的http请求,来完成从control到action 的调用。
看过上边的解释有没有发现在Yii 框架中的widget 很相似,widget 作为一种特殊的局部页面存在。可以帮我们剩下更多的开发时间。比如我们可以使用widget来构造通过导航栏等。
但是我们还有一部分局部页只是存在于两三个页面中,构造成widget会觉得比较浪费,因为就只有几个页面用到了,可是如果使用widget就需要在这几个action中都写上这部分代码,这时候我们会想有没有一种方法可以让我们在渲染页面的时候通过一种类似的widget方法,但是比widget要轻量级的东西来实现这个功能呢。在C#里就有这样一个类似的功能,Html.RenderAction 这个方法可以让我们在views上直接通过Html.RenderAction('action','controller',params);
这样类似的方式来完成直接对某一个指定的action的调用,并将渲染的视图添加到当然视图中来。
我们的目的就是打造一个通用的方法来实现类似C#中的功能。当然在Yii 框架下内部就已经实现了类似的方法 就是Yii 中的
public function runController($route){ ........... }
我们的目标就是封装这个方法,并且增加一个参数传递的功能。通过阅读Yii 框架的源码我们找到了Yii 中是通过$_GET 来完成参数传递的
/** * Returns the request parameters that will be used for action parameter binding. * By default, this method will return $_GET. You may override this method if you * want to use other request parameters (e.g. $_GET+$_POST). * @return array the request parameters to be used for action parameter binding * @since 1.1.7 */ public function getActionParams() { return $_GET; }
Yii 中默认返回的是$_GET的参数,我们可以通过重写这个方法来完成RenderAction 方法上参数的传递,从而避免和其他action中参数互相干扰。
我们首先来定义我们自己的入口文件并继承Yii
$yii = dirname(__FILE__) . '/../ITS3.0.Include/yii.php'; defined('RUN_YII_PATH') or define('RUN_YII_PATH', dirname(__FILE__)); require_once ($yii); class RunYii extends Yii { public static function createWebApplication($config = null) { RunYii:: RunYiiautoload(); return parent::createApplication('RunWebApplication', $config); } public static function RunYiiautoload() { YiiBase::$classMap['RunWebApplication'] = RUN_YII_PATH . '/web/RunWebApplication.php'; } }
我们通过继承在入口文件初引入了自己的RunWebApplication 类。
class RunWebApplication extends CWebApplication { public function runController($route, array $params = null) { if ($params) { if (($ca = $this->createController($route)) !== null) { list($controller, $actionID) = $ca; $oldController = parent::getController(); parent::setController($controller); $controller->init(); $controller->run($actionID, $params); parent::setController($oldController); } else throw new CHttpException(404, Yii::t('yii', 'Unable to resolve the request "{route}".', array('{route}' => $route === '' ? $this->defaultController : $route))); } else { parent::runController($route); } } }
在这个类中我们重写类runController方法,增加了一个$params 数组参数,
然后接着我们引入自定义的RunController类
class RunController extends CController { private $_params = array(); public function run($actionID, array $params = array()) { $this->_params = $params; parent::run($actionID); } public function getActionParams() { if ($this->_params) { return $this->_params; } else { return parent::getActionParams(); } } }
在RunController 中我们首先重写run方法,将通过Controller中传递过来的参数对象在run方法中接收到。我们定义一个私有变量用来存储params参数对象的值。
上边我们说到了Yii 中是getActionParams() 方法来返回action所需要的参数,这个方法也很简单就只有一行就是return $_GET;
我们在自定义的RunController 中重写这个方法, 通过判断私有变量$_params 中是否存在值来绝对当然action的参数来源是什么。
我们只是在Yii 框架的运行中插入一段自己的逻辑代码。用来实现我们自己的一点点小想法。
接下来看我们的index 文件
$runyii = dirname(__FILE__) . '/RunYii.php'; $config = dirname(__FILE__) . '/protected/config/main.php'; require_once ($runyii); RunYii::createWebApplication($config)->run();
我们在入口文件中使用我们RunYii 这样在项目中我们就可以使用
/** * @name 通过内联方式将指定action的视图加载到当前页面 * @param string $actionName */ public static function RenderAction($actionName) { Yii :: app()->runController('/' . lcfirst(Yii :: app()->getController()->id) . '/' . $actionName); } /** * @name 通过内联方式将指定action的视图加载到当前页面 * @param string $actionName * @param array $routeArray */ public static function RenderAction_Route($actionName, array $routeArray = array()) { RunYii :: app()->runController('/' . lcfirst(Yii :: app()->getController()->id) . '/' . $actionName, $routeArray); } /** * @name 通过内联方式将指定action的视图加载到当前页面 * @param string $actionName * @param string $controllerName */ public static function RenderAction_Controller($actionName, $controllerName) { Yii :: app()->runController('/' . lcfirst($controllerName) . '/' . $actionName); } /** * @name 通过内联方式将指定action的视图加载到当前页面 * @param string $actionName * @param string $controllerName * @param array $routeArray */ public static function RenderAction_Controller_Route($actionName, $controllerName, array $routeArray = array()) { RunYii :: app()->runController('/' . lcfirst($controllerName) . '/' . $actionName, $routeArray); }
以上是我们使用RunYii 来调用runController 来实现调用指定的action 并且action上参数对象
RenderAction_Controller_Route('actionname','controllername',array('par'=>1,'par1'=>'string','par2'=>array()));
我们可以传递任意的参数给我们指定的action
在action中我们只需要在方法上指定这些参数
pubulic funtion actionActionName($par,$par1,array $par2){
....
$this->renderPartial();
}
注意昂 必须使用renderPartial 这个来完成页面渲染,如果你使用layout来完成布局,使用render 会将你的框架页面视图也会渲染到里边页面就显示错乱了。
第一次写博客,如果谁用到这些不懂或者有疑问的地方欢迎提问啊。我的微博http://weibo.com/dearlv