作者:老王
CakePHP会根据我们
定义的模型间一对多,多对多...之类的关系自动创建相关模型的
实例,并作为
控制器属性存在,但是如果我们要加载一个不相关的对象,我们应该如何做呢?
似乎我们可以使用控制器的 var $uses 属性来实现这样的要求,但是这样的话,每次创建控制器都会建立$uses指定的模型对象,而对我们来说,我们可能仅仅在某个控制器方法里临时需要用一下而已,这样无疑是低效的。
通过查看CakePHP的
源代码,我们可以发现类似下面的解决方案:
复制内容到剪贴板
代码:
loadModel("Xxx");
$Xxx =& New Xxx();但是这样还有一个问题,如果我们在控制器方法里直接硬编码实现,会导致我们的代码无法测试,因为我们没法Mock掉Xxx,所以,最后我们应该把临时创建对象的任务放在一个适当的注入点里,如下:
复制内容到剪贴板
代码:
class AppController extends Controller
{
......
function & importModelInstace($name)
{
if(empty($this))
{
trigger_error('Not in object context', E_USER_ERROR);
}
static $modelInstance = array();
if(! array_key_exists($name, $modelInstance))
{
loadModel($name);
$modelInstance[$name] = & new $name;
}
return $modelInstance[$name];
}
......
}完活儿
附录:加上CakePHP中对于$uses的描述,方便对比
引用:
$uses
Does your controller use more than one model? Your FragglesController will automatically load $this->Fraggle, but if you want access to $this->Smurf as well, try adding something like the following to your controller:
var $uses = array('Fraggle','Smurf');
Please notice how you also need to include your Fraggle model in the $uses array, even though it was automatically available before.
补充:似乎直接在控制器里使用requestAction也是不错的方法。
补充:偶然发现了一个写得更好的方法(
http://www.thinkingphp.org/2007/ ... -instance-manually/)
复制内容到剪贴板
代码:
1.
function &getModel($model)
2.
{
3.
// Make sure our $modelClass name is camelized
4.
$modelClass = Inflector::camelize($model);
5.
6.
// If the Model class does not exist and we cannot load it
7.
if (!class_exists($modelClass) && !loadModel($modelClass))
8.
{
9.
// Can't pass false directly because only variables can be passed via reference
10.
$tmp = false;
11.
12.
// Return false
13.
return $tmp;
14.
}
15.
16.
// The $modelKey is the underscored $modelClass name for the ClassRegistry
17.
$modelKey = Inflector::underscore($modelClass);
18.
19.
// If the ClassRegistry holds a reference to our Model
20.
if (ClassRegistry::isKeySet($modelKey))
21.
{
22.
// Then make this our $ModelObj
23.
$ModelObj =& ClassRegistry::getObject($modelKey);
24.
}
25.
else
26.
{
27.
// If no reference to our Model was found in trhe ClassRegistry, create our own one
28.
$ModelObj =& new $modelClass();
29.
30.
// And add it to the class registry for the next time
31.
ClassRegistry::addObject($modelKey, $ModelObj);
32.
}
33.
34.
// Return the reference to our Model object
35.
return $ModelObj;
36.
}