【问题标题】:cakePHP hasOne relationship not auto completing dropdown fieldcakePHP hasOne 关系不自动完成下拉字段
【发布时间】:2011-06-22 23:08:22
【问题描述】:

我正在尝试在 2 个模型之间实现 hasone 关系,但我无法使用第二个模型中的可能选项(belongsTo 第一个模型)让“添加”表单自动完成一)。这是我的代码:

- 模型 1: item.php

<?php
class Item extends AppModel{ 

    var $name = 'Item';
    var $primaryKey = 'id';
    var $hasOne = 'CoverImage';
    }
?>

- 模型 2: cover_image.php

<?php
class CoverImage extends AppModel{ 

    var $name = 'CoverImage';
    var $primaryKey = 'id';
    var $belongsTo = array(
                 'Item' => array(
                    'className' => 'Item',
                    'foreignKey' => 'item_id'
                        )); 
}
?>

- 添加模型 2 的视图: add.ctp

<?php echo $this->Form->create('CoverImage',array('url' => array('controller' => 'admins', 'action' => 'add')));?>
    <fieldset>
        <legend><?php __('Info'); ?></legend>
    <?php
        echo $this->Form->input('item_id');
        echo $this->Form->input('description');
    ?>
    </fieldset>
    <?php echo $this->Form->end(__('Create', true));?>

对于我在 Cake 的文档中看到的,通过这种关系,在 add 视图中,我应该在 item_id 字段中看到一个下拉列表,以便能够选择哪个这个 CoverImage 属于 item,但下拉列表是空的(是的,我在 items 表中已经有一些 items)。

也许我遗漏了什么或者我做错了什么,但我想不通。非常感谢您提供任何线索!

编辑

我刚刚意识到,如果我这样做:

echo $this->Form->input('item_id', array('type'=>'text'));

而不是这个:

echo $this->Form->input('item_id');

我可以添加/编辑 *item_id* 字段,我可以在文本框中看到它的值。但是,如果我离开另一个,我只会看到一个空的 Dropbox,当我尝试添加/编辑一个 CoverImage 时,它不起作用,它只是显示一个空白页面,即使没有错误...

也许这是通往某事的线索……

【问题讨论】:

  • 试试:echo $this-&gt;Form-&gt;inputs(); 这是一种自动生成所有属性的表单字段的方法,一次。这不是一个直接的答案/解决方案,但也许它可以帮助您找到线索。

标签: cakephp relationship has-one


【解决方案1】:

为了让它工作,你必须在控制器中创建一个可能的选项列表。这不会自动发生。

public function add() {
    $items = $this->CoverImage->Item->find('list');
    $this->set(compact('items'));
}

FormHelper 仅自动推断字段 item_id 应由变量 $items 中的选项填充(复数,没有 _id)。

请注意,已经拥有一个 CoverImage 的项目不应成为该列表的一部分。 find('list', array('conditions' =&gt; array('CoverItem.id' =&gt; null)))可能*会解决这个问题,但你也需要在保存之前重新检查,或者你需要重新考虑你的关联。

* 不确定这是否适用于 'list' 搜索。

【讨论】:

  • 我有 85% 的把握,因为 hasOne 会自动键入 id,所以该查询实际上会提取关联的 CoverImage + Item 对的列表。当然,您可以对其进行操作以产生一种印象,即您已经为 CoverImage 提取了所有可用的项目以供选择,这在第一个 hack 之上堆积了第二个 hack。然后,假设用户选择了一个已经有 CoverItem 的项目。将其保存在 Item 的 hasOne 周围将是第三种,可能是 db-trashing / app-break hack。 foreach($compounding as $hack) { $this->answer-- }
  • @satyr 我真的不确定你在说什么。 find('list') 将简单地以array($id =&gt; $name) 的形式获取所有项目的数组。你是对的,这可能与 "hasOne" 的概念相冲突(如果这就是你想说的话),添加了一个关于那个的注释。
  • 我试过了,效果很好!尽管我不确定您在评论的第二部分中的意思(关于要小心)。我已经在我的 edit 操作中尝试过这个,并且似乎工作正常,没有使用 find 中的条件数组。我应该使用它们吗?如果你不介意解释,为什么?
  • @Albert 你的物品目前haveOne CoverImage。这意味着您不能为两个不同的 CoverImages 选择相同的项目(因为那样项目将 haveMany CoverImages)。这就是您需要注意或确认您是否真的选择了正确的关联。
  • 在 OP 问题的上下文中。我试图描述的问题不是它不起作用,而是——在这种情况下——这将是你最不想做的事情。银行有很多用户,有很多账户。用户属于银行。帐户有一个用户。因为可以通过其用户访问帐户的银行。 如果您不尊重该关系的排他性,以至于您发现自己故意编写“俯冲”发现并围绕其结果跳舞,这通常意味着真正的问题是分配的关系不合适。
【解决方案2】:

很好的问题。你已经与 Cake 的联想的一个不诚实的特征发生了冲突:

考虑到您将关系定义为 hasOne?猜测跟踪,但 Cake 甚至可能正确地推断出您对列表功能的偏好。你得到了你的自动列表...

...一个。

$hasOne 是非常独特的。它“用完”那些“有”关系(它使关系成为事实上的单例 - 所以用户只有 1 个配置文件 配置文件只有 1 个用户)。考虑 - 数据库可以有多种配置,但 Dbo 一次只能有一个 Connection,而 Connection 只能有一个 Dbo。因此 -> hasOne 是为了让两个模型结婚直到 die() 他们分开。

-- 所以它几乎没有 hasMany 和 belongsTo 那样被使用。

出于您的目的,您可能希望更改为不同的关联。

添加一个额外的 $this->Item->find 并不能真正解决问题(我不推荐它,除非你大部分都完成了两个模型/控制器,或者你积极希望事情开始得到快得离谱。)

另外,改变你调用表单助手方法的方式——如果你从一个 find 中返回一个 'list' 类型的 fetch,Cake 会自动生成一个选项列表。实际发生的情况是,您在模型的视图功能非常薄弱的​​边缘偷偷摸摸。这就是为什么不鼓励将输入类型指定为“打破魔法”的原因(如果您愿意,您完全可以这样做。只需了解实际发生的情况,或者:看,奇怪,快。)

但是您可能想要重新考虑如何关联模型 - 说每个项目都属于一个 CoverImage 是否也是正确的(就像每个 CoverImage 属于一个项目一样) - 因为你有一个明确的表格允许 CoverImage 选择要显示的项目,任何项目?你可能会得到更好的结果。

HTH。 :)

【讨论】:

  • 感谢您的解释。问题是我看不到将关系顺序从 Item->CoverImage 切换到 CoverImage->Item 的好处,如果这就是你的意思的话.. . 我尝试了 deceze 给出的解决方案,但是对于他所说的和你所说的,这样做可能会有一些不好的地方,尽管我似乎无法意识到这是什么......
  • 切换顺序不会改变任何东西,除非您在 Items $uses 数组中包含 CoverImage 表,否则这样做会引发错误。我的意思是,除非您打算拉出所有项目并在选择新项目时覆盖那些已经具有 Cover_Id 的项目, 或引入过滤步骤等,否则您将得到不希望的结果。如果您打算全力以赴并保存,那么恭喜^_^如果您没有 - 我的建议是,更改 $hasOne 关联比对抗它更安全、更容易。
猜你喜欢
  • 1970-01-01
  • 2011-03-17
  • 2013-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多