2

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

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

然而,在谷歌之后,我偶然发现了这个链接,这不断产生关于使用 Form 类时未定义索引的错误(猜测这是因为它获取的是对象化版本而不是数组版本)。

我正在关注博客教程(已经在 1.3 下关注了它,但在 2.0 版中再过一遍)

那么,有谁知道如何在不干扰 Form 类的情况下实现这一点?

霍什

4

5 回答 5

3

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

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

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

$Post->id为了击键而将它们压入的问题是Cake就是原因。Cake 被设计成一个举重的工具,因此它的内置 ORM 非常强大,不可避免,并且旨在解决无限关联表的无限行 - 自动回调,自动数据传递,查询生成等。多维数组的基本深度取决于在您的 find 方法中,一旦您使用多个关联模型的多个 $Post(例如),您就已经将数组引入了组合中,并且无法避免这种情况。

不同find的方法返回不同深度的数组。从默认生成的控制器代码中,您可以看到 index 使用$this->set('posts', $this->paginate());- view 使用$this->set('post', $this->Post->read(null, $id));和 edit 根本不$this->set与 Post find 一起使用 - 它分配$this->data = $this->Post->read(null, $id);.

FWIW,Set::map可能会抛出这些undefined index错误,因为(猜测)你碰巧试图映射一个编辑动作,amirite?默认情况下,编辑操作仅用于$this->set将关联的模型查找设置到视图。$this->read 的结果被发送到$this->data。这可能就是 Set::map 失败的原因。无论哪种方式,你最终还是会瞄准$Post[0]->idor $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。

于 2011-11-12T09:25:21.940 回答
2

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

首先,如果您还没有 AppController.php,请在 /app/Controller 中创建一个。然后创建一个 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);
    }
  }
}

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

索引.ctp

$productsObj;

视图.ctp

$productObj->id;

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

产品 -> $productsObj

产品类型 -> $productTypesObj

我知道这并不完美,但它基本上可以实现您想要的,并且可以在您的所有模型中使用。

于 2011-11-11T11:42:02.017 回答
2

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

我找到的最快的是https://github.com/kanshin/CakeEntity - 但看起来你可能需要为 2.x 重构它 - 甚至可能已经有一个 2.x 分支或分支,但我没有看。

于 2011-11-11T16:51:47.090 回答
0

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

于 2011-10-30T18:59:57.700 回答
0

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

如果您有权访问该类,则可以实现ArrayAccess 接口并轻松地以数组的形式访问您的对象。

PS:抱歉,我从未使用过 CakePHP,但我认为对象到数组的转换不一定是特定于框架的问题

于 2011-11-11T11:49:46.077 回答