如何在不破坏 CakePHP 中的 MVC 框架的情况下做到这一点?

Posted

技术标签:

【中文标题】如何在不破坏 CakePHP 中的 MVC 框架的情况下做到这一点?【英文标题】:How can I do this without breaking the MVC framework in CakePHP? 【发布时间】:2009-05-11 03:08:14 【问题描述】:

对不起,什么是通用标题。我不是最擅长头衔的人。

无论如何,Cake 传递数据的方式(作为哈希)几乎就是我什至需要问这个问题的原因。如果当我将一个变量/obj 从控制器传递到视图时,它是一个我可以向其提问的对象(即 $duck->quack() ),而不是让它成为一个数组/字典(即 $duck[' Duck']['quack'] == true) 这很容易。

我的应用中有一个用户 x 可以拥有或不拥有的项目列表。在某些视图中,我显示数据库/应用程序中的所有项目(即分页),并且对于每个项目,我需要知道登录用户是否拥有它。要回答这个问题,我需要做一个查询(由于复杂的 HABTM 关系),这是在模型内部完成的。换句话说,我的 Item 模型有一个函数 isOwnedByUser($user_id, $item_id) 如果它归用户所有,则该函数为真。我想从视图中调用这个函数。

这自然违反了 MVC 框架,但我不知道该怎么做。我有四个想法:

想法 1:

在 helper 中执行此操作:

App:Import('Model','Item');
$item = new Item();
$item->isOwnedByUser($user_id,$item_id);

并从视图中调用帮助程序(当然还传入 $item_id 和 $user_id)。但这确实违反了 MVC 框架。

想法 2:

在 item_controller.php 中创建一个动作并使用 requestAction() 从视图中调用该动作。但是我heard that this was extremeley inefficent

现在我在looking 时发现了这两个想法来解决我的问题,但根据他们的说法,这两个想法很糟糕,所以我想出了另外两个解决方案:

想法 3:

当将分页数据返回到视图时,我可以确保所有项目都有一个“user_id”键,以便我可以根据登录用户的 ID 检查视图中的键,以查看他/她是否拥有项目。但这需要a)我重新编写分页b)非常丑陋的查询,尤其是对于某些视图(搜索),c)整体丑陋和缓慢。所以我决定放弃这个想法

想法 4:

每次视图需要知道一个项目是否归用户所有时,我都会从控制器传递另一个数组,其中包含用户拥有的所有项目,在视图中你可以使用 in_array() 来检查如果用户拥有所述项目。当然这个问题很明显:如果用户有很多物品怎么办?

简而言之,我被困在这个问题上,我不知道从哪里开始,我会感谢所有帮助!谢谢!

【问题讨论】:

我还应该补充一点,Cake 处理 HABTM 关系的方式也很糟糕。真的很烂。但这与这个问题无关。 【参考方案1】:

我会把 3 和 4 结合起来。

在你的行动中,在你获得所有分页项目之后:

$items = $this->paginate('Item');

获取他们的 ID 并将其与用户 ID 结合以获取所有用户的项目。

$itemIds = Set::extract('/Item/id', $items);

$usersItems = $this->Item->User->find
    (
        'all',
        array
        (
            'conditions' => array
            (
                'User.id' = $userId,
                'Item.id' => $itemIds
            ),
            'fields' => array('User.id', 'Item.id')
        )
);

现在您可以将 $usersItems 设置为您喜欢的格式,并为视图设置该格式和 $items。这将带你到你的选项 4 和 in_array(),除了它可能是 Set::extract() 或 Set::check()。

应该这样做:

if (Set::extract(sprintf('/Item[id=%s]', $itemId), $usersItems))

    // user has the item

(我是凭记忆写的,所以……你知道如果失败了该怎么办:))

编辑:

或者,您可以执行以下操作(它应该比上述更快,只需确保将Set::extract() 移出循环):

$usersItemIds = Set::extract('/Item/id', $usersItems);

if (in_array($itemId, $usersItemIds))

    // user has the item

【讨论】:

抱歉,我花了将近一天的时间才回复,但这很好用!我完全不知道 Set 实用程序,现在我可以重构一大堆低效编写的代码!再次感谢! 没问题!设置类是蛋糕中最好的东西之一,但不知何故不为公众所知。所以,广而告之! :)【参考方案2】:

我知道这是一个老问题,但似乎 ACL 组件在这里可能是一个不错的选择。

【讨论】:

以上是关于如何在不破坏 CakePHP 中的 MVC 框架的情况下做到这一点?的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何在不破坏嵌套的情况下过滤 RECORD 中的列?

CakePHP 教程:PHP 开发框架

用于CakePHP的Eclipse插件

AOP的理解与实现

CakePHP 3.4.10 发布,PHP 开发框架

CakePHP 2.8.8 发布,PHP 开发框架