简体   繁体   English

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

[英]How can I do this without breaking the MVC framework in CakePHP?

Sorry for what is a generic title. 对不起,通用标题是什么。 I'm not the best at titles. 我不是最好的头衔。

Anyway the way Cake passes around data (as a hash) is pretty much the reason why I even need to ask this question. 无论如何,Cake传递数据(作为散列)的方式几乎是我什至需要问这个问题的原因。 If when I passed a variable/obj from the controller to the view, it was an object that I can ask questions to (ie $duck->quack() ) rather than having it be an array/dictionary (ie $duck['Duck']['quack'] == true) this would be easy. 如果当我从控制器向视图传递变量/ obj时,它是我可以询问的对象(即$ duck-> quack()),而不是让它成为数组/字典(即$ duck [') Duck'] ['quack'] == true),这很容易。

What I have in my app is a list of items that a user x can own or not. 我的应用程序中包含用户x可以拥有或不可以拥有的项目的列表。 In certain views I display all the items in the database/app (ie paginate) and for each item I need to know if the logged in user owns it or not. 在某些视图中,我显示数据库/应用程序中的所有项目(即分页),对于每个项目,我需要知道登录用户是否拥有它。 To answer this question I need to do a query (due to a complicated HABTM relationship), which is done inside the Model. 为了回答这个问题,我需要进行查询(由于复杂的HABTM关系),该查询在模型内部完成。 In other words my Item model has a function isOwnedByUser($user_id, $item_id) which is true if it is owned by user. 换句话说,我的Item模型具有一个函数isOwnedByUser($ user_id,$ item_id),如果该函数归用户所有,则为true。 I want to call this function from the view. 我想从视图中调用此函数。

Naturally this is violating the MVC framework, but I'm not sure how else to do it. 自然,这违反了MVC框架,但是我不确定还有其他方法。 I had four ideas: 我有四个想法:

Idea 1: 想法1:

Do this inside a helper: 在助手中执行此操作:

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

and call the helper from the view (and pass in the $item_id and $user_id of course). 并从视图中调用帮助程序(并传入$ item_id和$ user_id)。 But this REALLY violates the MVC framework. 但这确实违反了MVC框架。

Idea 2: 想法2:

Create a action inside item_controller.php and call the action from the view using requestAction(). 在item_controller.php中创建一个动作,并使用requestAction()从视图中调用该动作。 But I heard that this was extremeley inefficent 但是我听说这是非常无效的

Now these two ideas I found when I was looking for a solution to my problem but according to them those two ideas are bad so I came up with two more solutions: 现在,当我在寻找问题的解决方案时发现了这两个想法,但根据他们的看法,这两个想法很糟糕,因此我又提出了两个解决方案:

Idea 3: 理念3:

When returning the paginated data to the view, I can make sure that all items have a 'user_id' key so that I can check the key in the view against the logged in user's id to see if he/she owns item. 将分页数据返回到视图时,我可以确保所有项目都具有“ user_id”键,以便可以对照已登录用户的ID检查视图中的键,以查看他/她是否拥有该项目。 But this would require a) me to re-write pagination b) very ugly queries especially for certain views (search), c) overall ugliness and slowness. 但这将要求a)我重新编写分页b)非常丑陋的查询,尤其是对于某些视图(搜索),c)整体丑陋和缓慢。 So I decided to abandon this idea 所以我决定放弃这个想法

Idea 4: 理念4:

Every time a view needs to know if an item is owned by user, I'll just pass along another array from the controller that contains ALL the items a user owns and in the view you can just use in_array() to check if user owns said item. 每当视图需要知道某个项目是否归用户所有时,我都会从控制器中传递另一个数组,该数组包含用户拥有的所有项目,在视图中,您可以使用in_array()来检查用户是否拥有说的项目。 Of course the problem to this is obvious: what if the user has lots of items? 当然,问题很明显:如果用户有很多物品怎么办?

In short I'm stuck at this and I have no clue where to go from here and I'd appreciate all help! 简而言之,我对此一无所知,不知道从这里到哪里去,我将不胜感激! Thanks! 谢谢!

I'd combine 3 and 4. 我将3和4结合在一起。

In your action, after you get all the paginated items: 在您获得所有分页项目后的操作:

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

Get their IDs and combine that with the user ID to fetch all the user's items. 获取他们的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')
        )
);

Now you can set the $usersItems in a format you prefer and set both that and $items for the view. 现在,您可以按照自己喜欢的格式设置$ usersItems,并为视图设置它和$ items。 That would bring you to your option 4 and in_array(), except it would probably be Set::extract() or Set::check(). 这将带您进入选项4和in_array(),但它可能是Set :: extract()或Set :: check()。

Something like this should do it: 这样的事情应该做到:

if (Set::extract(sprintf('/Item[id=%s]', $itemId), $usersItems))
{
    // user has the item
}

(I wrote this from my memory so... you know what to do if it fails :)) (我是从我的记忆中写出来的,所以...您知道如果失败了该怎么办:))

Edit: 编辑:

Alternatively, you can do something like this (it should be faster than the above, just make sure to move Set::extract() out of the loop): 或者,您可以执行以下操作(它应该比上述速度更快,只需确保将Set::extract()移出循环即可):

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

if (in_array($itemId, $usersItemIds))
{
    // user has the item
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM