Как я могу сделать это, не нарушая инфраструктуру MVC в CakePHP? - PullRequest
1 голос
/ 11 мая 2009

Извините за общее название. Я не лучший в названиях.

В любом случае, способ, которым Cake передает данные (как хэш), в значительной степени является причиной, по которой мне даже нужно задать этот вопрос. Если, когда я передавал переменную / obj из контроллера в представление, это был объект, к которому я могу задавать вопросы (например, $ duck-> quack ()), вместо того, чтобы иметь массив / словарь (то есть $ duck [' Duck '] [' quack '] == true) это будет легко.

В моем приложении есть список элементов, которыми пользователь x может владеть или нет. В определенных представлениях я отображаю все элементы в базе данных / приложении (т. Е. Разбивку на страницы) и для каждого элемента мне нужно знать, принадлежит ли зарегистрированный пользователь или нет. Чтобы ответить на этот вопрос, мне нужно выполнить запрос (из-за сложного отношения HABTM), который выполняется внутри модели. Другими словами, моя модель Item имеет функцию isOwnedByUser ($ user_id, $ item_id), которая имеет значение true, если она принадлежит пользователю. Я хочу вызвать эту функцию из представления.

Естественно, это нарушает структуру MVC, но я не уверен, как еще это сделать. У меня было четыре идеи:

Идея 1:

Сделайте это внутри помощника:

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

и вызовите помощника из представления (и, конечно, передайте $ item_id и $ user_id). Но это ДЕЙСТВИТЕЛЬНО нарушает рамки MVC.

Идея 2:

Создайте действие внутри item_controller.php и вызовите действие из представления, используя requestAction (). Но я слышал, что это было крайне неэффективно

Теперь эти две идеи я нашел, когда искал для решения своей проблемы, но в соответствии с ними эти две идеи плохие, поэтому я предложил еще два решения:

Идея 3:

При возврате разбитых на страницы данных в представление я могу убедиться, что у всех элементов есть ключ 'user_id', чтобы я мог сравнить ключ в представлении с идентификатором вошедшего в систему пользователя, чтобы узнать, владеет ли он / она элементом. Но это потребует: а) от меня переписать нумерацию страниц, б) очень уродливые запросы, особенно для определенных просмотров (поиск), в) общее уродство и медлительность. Поэтому я решил отказаться от этой идеи

Идея 4:

Каждый раз, когда представление должно знать, принадлежит ли элемент пользователю, я просто передаю другой массив из контроллера, который содержит ВСЕ элементы, которыми владеет пользователь, и в представлении вы можете просто использовать in_array () для проверки если пользователь владеет указанным предметом. Конечно, проблема в этом очевидна: что, если у пользователя много предметов?

Короче говоря, я застрял в этом, и я понятия не имею, куда идти отсюда, и я был бы признателен за любую помощь! Спасибо!

Ответы [ 2 ]

3 голосов
/ 11 мая 2009

Я бы скомбинировал 3 и 4.

В вашем действии после того, как вы получите все постраничные предметы:

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

Получите их идентификаторы и объедините их с идентификатором пользователя, чтобы получить все элементы пользователя.

$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 в формате, который вы предпочитаете, и установить и тот, и другой элемент для представления. Это приведет вас к вашему варианту 4 и in_array (), за исключением того, что это, вероятно, будет Set :: extract () или Set :: check ().

Что-то вроде этого должно сделать это:

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

(я написал это по памяти, так что ... вы знаете, что делать, если это не получается :))

Edit:

В качестве альтернативы, вы можете сделать что-то подобное (это должно быть быстрее, чем указано выше, просто убедитесь, что Set::extract() выведено из цикла):

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

if (in_array($itemId, $usersItemIds))
{
    // user has the item
}
0 голосов
/ 14 ноября 2009

Я знаю, что это старый вопрос, но кажется, что, возможно, компонент ACL будет хорошим вариантом здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...