问题:
在yii中,一个controller会包含若干个action。有时为了重用或代码管理等目的,我们希望这些action可以单独定义成一个类,然后在
controller中使用。那么在yii中要如何实现呢?
假设我们有这样一个例子
TestController.php,文件位于wwwroot/blog/controllers/,wwwroot对应http://www.example.com/
代码如下:
<?php
class TestController extends Controller {
public function actionHello($name='ball'){
echo "hello $name";
}
}
代码功能很简单,接收一个名字参数,显示hello $name。
访问:
http://www.example.com/blog/index.php?r=test/hello&name=xuan
页面显示:
页面显示:
hello xuan
注:
actionHello函数的$name参数最好有默认值。不然当url中无$name参数时页面会报错。
注:
actionHello函数的$name参数最好有默认值。不然当url中无$name参数时页面会报错。
实现
下面我们要做的是,将actionHello形成一个单独的类,在TestController中调用它。
1. 建立wwwroot/blog/controllers/test/目录
目录名定为test是yii推荐的写法,建议action所在的目录与对应的controller同名,当然不这样也没有关系。
2.在test目录中创建HelloAction.php文件。
文件内容如下:
<?php
class HelloAction extends CAction{
public function run($name='ball'){
echo "Hello $name";
}
}
注意:
1.此类一定要继承自CAction类
2.必须有run方法供外部调用
3.run方法的参数,即为url中的请求参数。当然也可以通过$_GET的方式在函数内部取得
详见
http://www.yiiframework.com/doc/guide/1.1/en/basics.controller#action一节中的Action Parameter Binding
3.修改TestController.php
<?php
class TestController extends Controller {
public function actions(){
return array('hello'=>array(
'class'=>'application.controllers.test.HelloAction',
)
);
}
}
好了,看看我们的成果吧,访问:
http://www.example.com/blog/index.php?r=test/hello&name=xuan
页面显示:
hello xuan
页面显示:
注:
对于'class'=>'application.controllers.test.HelloAction'在官方例子中你也许会看到类似'class'=>'HelloAction'的写法。
不要困惑,其实目的是一样。本例中之所以写为“application.controllers.test.HelloAction”,是因为test目录不在yii自动加载范畴。
如果之前有导入: Yii::import('application.controllers.test.*');
那么 'class'=>' HelloAction'就可以正常工作了。
对于'class'=>'application.controllers.test.HelloAction'在官方例子中你也许会看到类似'class'=>'HelloAction'的写法。
不要困惑,其实目的是一样。本例中之所以写为“application.controllers.test.HelloAction”,是因为test目录不在yii自动加载范畴。
如果之前有导入: Yii::import('application.controllers.test.*');
那么 'class'=>' HelloAction'就可以正常工作了。
More
1. 如果TestController同时定义了上述actions规则,又包含了actionHello方法会怎么样呢?
答案是优先执行actionHello方法,actions相应的规则不生效。
2.controller中如果有特殊的参数要传给actoin,如何处理?
通过actoins方法中的规则传递。
代码类似
对应本文的例子,假设TestController要传一个somthingToSay给HelloAction,代码如下:
TestController.php
http://www.example.com/blog/index.php?r=test/hello&name=xuan 页面显示:
Hello xuan, welcome to yii.
return array(
'action'=>array(
'class'=>'path.to.ActionClass',
'property1'=>'value1',
'property2'=>'value2',
),
);
但action中必须有相应的property属性,且设为public。
对应本文的例子,假设TestController要传一个somthingToSay给HelloAction,代码如下:
TestController.php
<?php
class TestController extends Controller {
public function actions(){
return array('hello'=>array(
'class'=>'application.controllers.test.HelloAction',
'somethingToSay'=>'welcome to yii',
));
}
}
HelloAction.php
<?php
class HelloAction extends CAction{
public $somethingToSay = '';
public function run($name='ball'){
echo "Hello $name, {$this->somethingToSay}.";
}
}
访问http://www.example.com/blog/index.php?r=test/hello&name=xuan 页面显示:
Hello xuan, welcome to yii.