CakePHP 2.0对象不是数组


CakePHP 2.0 Object not Array

我目前是CakePHP的初学者,并且玩过CakePHP 1.3,但最近CakePHP 2.0已经发布。

到目前为止,我喜欢它,但唯一的事情是一个痛苦的事实是,它不返回对象,而只是返回数组。我的意思是,$post[' post ']['id']几乎没有意义。它是(在我看来)更实际的只是做$post->id。

现在在谷歌我偶然发现了这个链接,然而,这一直产生错误的索引没有被定义时,使用Form类(猜测这是因为它得到的是物化版本,而不是数组版本)。

我遵循博客教程(已经遵循了1.3版本,但在2.0版本中又重复了一遍)

所以,谁知道如何实现这一点,而不干扰表单类?

Hosh

鲜为人知的事实:Cake确实将它们作为对象返回,或者作为对象的属性返回。数组是语法糖:

    // In your View:
    debug($this->viewVars);

Shwoing $this是View对象 viewVars属性对应控制器动作的$this->set('key', $variable)$this->set(compact('data', 'for', 'view'))

为了击键而将它们压入$Post->id的问题是Cake是为什么。Cake被设计成一个沉重的提升器,所以它的内置ORM非常强大,不可避免,用于处理无限关联表的无限行——自动回调、自动数据传递、查询生成等。多维数组的基本深度取决于您的find方法,一旦您使用多个具有多个相关模型的$Post(例如),您就已经将数组引入到混合中,并且无法避免。

不同的find方法返回不同深度的数组。从默认生成的控制器代码中,您可以看到索引使用$this->set('posts', $this->paginate()); -视图使用$this->set('post', $this->Post->read(null, $id));,编辑根本不使用$this->set和Post查找-它分配$this->data = $this->Post->read(null, $id);

fww, Set::map可能抛出那些undefined index错误,因为(猜测)你碰巧试图映射一个编辑动作,不是吗?默认情况下,编辑操作只使用$this->set来设置与视图相关的模型查找。$this->read的结果被发送给$this->data。这可能就是Set::map失败的原因。无论哪种方式,您仍然将最终瞄准$Post[0]->id$Post->id(取决于您使用的方法),这并不是很大的改进。

下面是Set::map()属性深度的一些通用示例:

    // In posts/index.ctp
    $Post = Set::map($posts);
    debug($Post);
    debug($Post[0]->id);
    // In posts/edit/1
    debug($this-viewVars);
    debug($this->data);
    // In posts/view/1
    debug($this-viewVars);
    $Post = Set::map($post);
    debug($Post->id);

http://api13.cakephp.org/class/controller method-Controllerset

http://api13.cakephp.org/class/model method-Modelread

http://api13.cakephp.org/class/model method-ModelsaveAll

HTH .

您可以创建额外的对象变量。这样,您就不会干扰Cake的自动操作,但可以使用像$modelNameObj->id;格式访问数据。

首先,在/app/Controller中创建一个AppController.php,如果你还没有的话。然后创建一个beforeRender()函数。这将在Cake的标准命名约定中查找数据,并从中创建额外的对象变量。

<?php
App::uses('Controller', 'Controller');
class AppController extends Controller {
  public function beforeRender() {
    parent::beforeRender();
    // camelcase plural of current model
    $plural = lcfirst(Inflector::pluralize($this->modelClass));
    // create a new object
    if (!empty($this->viewVars[$plural])) {      
      $objects = Set::map($this->viewVars[$plural]);
      $this->set($plural . 'Obj', $objects);     
    }
    // camelcase singular of current model
    $singular = lcfirst(Inflector::singularize($this->modelClass));    
    // create new object 
    if (!empty($this->viewVars[$singular])) {      
      $object = Set::map($this->viewVars[$singular]);
      $this->set($singular . 'Obj', $object);
    }
  }
}

在你的视图中,你可以像这样访问对象:

index.ctp

$productsObj;

view.ctp

$productObj->id;

我们所做的只是将'Obj'添加到Cake已经提供的变量名中。一些映射示例:

Products -> $productsObj

ProductType -> $productTypesObj

我知道这不是完美的,但它基本上可以达到你想要的效果,并且可以在你所有的模型中使用。

虽然我喜欢Moz提出的想法,但对于这个问题有许多现有的解决方案。

我发现最快的一个是https://github.com/kanshin/CakeEntity -但看起来你可能需要重构它为2。X,可能已经有一个2了。

这个问题我也在脑子里想了好几次。现在一些基于Cake的应用程序之后,我看到了能够分支和合并(am, in_array等)结果集的好处,数组比使用对象更方便。$Post->id形式是一个很好的语法糖,但与数组相比并没有真正的好处。

您可以编写一个函数,迭代您的公共属性(参见ReflectionClass::getProperties),并将其保存在数组中(并返回该数组)。

如果你可以访问该类,你可以实现ArrayAccess接口,并轻松地将对象作为数组访问。

注::对不起,我从来没有使用过CakePHP,但我认为对象到数组的转换不一定是框架特定的问题