Настройка beforeFind() в AppModel

У меня есть поле status_id во всем, которое управляет публикацией вещей и т. д. Я создал это в своей AppModel, чтобы позаботиться обо всей фильтрации.

public function beforeFind($queryData) {
        // Force all finds to only find stuff which is live
        $queryData['conditions'][$this->alias.'.status_id'] = 1;
        return $queryData;
}

Это прекрасно работает, пока вы не войдете в маршрутизацию администратора, и в этот момент вы захотите увидеть все элементы, и они будут отфильтрованы. Есть ли способ узнать, находитесь ли вы в административной маршрутизации из AppModel?


person David Yell    schedule 04.11.2011    source источник


Ответы (4)


У меня есть опыт в подобной ситуации, когда я использую поведение «обратимого удаления».

Я рекомендую проверить, есть ли у вас уже условие в поле status_id, и установить его только в том случае, если у вас его нет. Вот так:

public function beforeFind($queryData) {
    if (! isset($queryData['conditions'][$this->alias.'.status_id'])) {
        // Force all finds to only find stuff which is live
        $queryData['conditions'][$this->alias.'.status_id'] = 1;
    } elseif ($queryData['conditions'][$this->alias.'.status_id'] == 'all') {
        unset($queryData['conditions'][$this->alias.'.status_id']);
    }
    return $queryData;
}

Таким образом, у вас есть желаемая функциональность по умолчанию, и вы также можете использовать обычные условия в поле status_id, когда это необходимо. В качестве бонуса, чтобы игнорировать условие, как вы хотите в административной маршрутизации, вы можете использовать это:

    $data = $this->paginate('YourModel', array('YourModel.status_id' => 'all'));

По сути, это просто удобство, позволяющее избежать передачи всех идентификаторов статуса как «фальшивого» условия.

Вот как бы я это сделал. Надеюсь, поможет.

person guillobuteler    schedule 01.03.2013

Вы можете проверить маршрут администратора в своем контроллере и определить его следующим образом:

App Controller:

if(isAdmin){
$queryData['conditions']['isAdmin'] = true;
}

In your AppModel:

if(!isset($queryData['conditions']['isAdmin'] & $queryData['conditions']['isAdmin'] !== true )){
$queryData['conditions'][$this->alias.'.status_id'] = 1;
        return $queryData;

} else {
       return $queryData
}

Это грязный способ, но он должен работать.

person MadeOfSport    schedule 04.11.2011
comment
Notice (8): Indirect modification of overloaded property QuicklinksController::$queryData has no effect [APP\Controller\AppController.php, line 9] Я должен упомянуть, что я в Cake2.0 - person David Yell; 05.11.2011
comment
Можете ли вы опубликовать соответствующий пример кода вашего контроллера быстрых ссылок? - person MadeOfSport; 05.11.2011
comment
Вот где ваше решение! ;) - person David Yell; 05.11.2011
comment
Я думаю, это потому, что конструкция условий в 2.0 отличается от 1.3, так же как $this->data теперь $this->request->data - person David Yell; 07.11.2011

у модели нет причин знать, каков маршрут. Его цель - передать контроллеру то, что запрошено. Другими словами, вы должны задавать условие в контроллере, а не в модели.

Извините, что был слишком краток.

То, что вы пытаетесь сделать, идет вразрез с шаблоном проектирования MVC. Это контроллер, который обрабатывает и направляет запросы, сделанные клиентом.

In your controller:
function index(){
    $data = $this->paginate('YourModel', array('YourModel.status_id' => 1));
    $this->set('data', $data);
}

function admin_index(){
    $data = $this->paginate();
    $this->set('data', $data);
}

Еще менее многословный

Вы пытаетесь определить в модели, был ли запрос сделан из административной маршрутизации, что является неправильным путем. Контроллер обрабатывает это автоматически. admin_index() обрабатывает запрос индекса, сделанный через административный маршрут, запрос index(), сделанный через обычный маршрут.

Именно в контроллере вы решаете, какие данные вам нужны. Вы должны переместить логику, которая у вас есть в вашем методе beforeFind, в ваш контроллер, как в примере выше.

person kaklon    schedule 05.11.2011
comment
Более подробный ответ был бы полезен. Поскольку настройка свойств модели в контроллере приложения работает до некоторой степени, но это надежно. - person David Yell; 05.11.2011
comment
извините за это, см. изменения в моем ответе - person kaklon; 05.11.2011
comment
Я думаю, вы неправильно поняли вопрос. beforeFind() запускается в модели перед выполнением вызова поиска. Этот вызов поиска запускается с контроллера. Значит, он за контроллером. - person David Yell; 07.11.2011
comment
Кажется, я понял ваш вопрос. Вы пытаетесь определить в модели, был ли запрос сделан из административной маршрутизации, что является неправильным путем. Смотрите мое редактирование - person kaklon; 07.11.2011
comment
Я не хочу вставлять одну и ту же функцию в каждый контроллер. Думаю, я могу переместить его в AppControllers beforeFilter(), и тогда я потеряю beforeFind() - person David Yell; 09.11.2011
comment
Да, если вам это нужно в каждом контроллере, это правильный путь. - person kaklon; 10.11.2011

Ответ, который я получил, состоял бы в том, чтобы установить маршрут в качестве атрибута в модели из контроллера, который вы затем можете проверить из модели.

Однако у CakeDC есть пакет плагинов Utils, который включает в себя поведение SoftDeletable, которое я использую сейчас. https://github.com/cakedc/utils

person David Yell    schedule 01.03.2013