发新话题
打印

如何在CakePHP里临时加载一个Model对象

如何在CakePHP里临时加载一个Model对象

作者:老王

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.
      }

TOP

cakephp 的model设计的比较失败。。。。。自己重写吧
一個偽裝成白癡的天纔!

TOP

requestAction 就可以了,参考:http://bakery.cakephp.org/articl ... -with-requestaction

TOP

发新话题