AccessControl не вызывает bizRule

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
mickgeek
Сообщения: 957
Зарегистрирован: 2014.05.31, 20:50
Откуда: Санкт-Петербург
Контактная информация:

Re: AccessControl не вызывает bizRule

Сообщение mickgeek »

taral14, "способ" - не есть "функция".
taral14 писал(а):По поводу кеширования запроса в переменную при вызове findModel. Если уже и делать так то метод нужно точно назвать по другому. Например getModel. Потому что название findModel означает что мы делаем запрос на поиск модели. И прямо в методе делать такой кеш я считаю плохим решением.
Здесь согласен, грамотнее всего, конечно, в модели обрабатывать такие вещи. А "getModel()" или "loadModel()", ну измените название, если не нравится. В моём примере это не принципиально.
taral14 писал(а):Да может. К примеру вы берете модель. Вносите в нее изменения. Сохраняете. При сохранении модель производит некоторые операции с базой. Но не все изменения отображаются в данных модели. Дальше вы делаете еще запрос на Controller::findModel и думаете что работаете уже с новой моделью которая правильно инициализировалась с данных из базы. В этом случае могут быть неприятные ошибки. Естественно это просто решается рефрешем страницы после изменений в моделе. Но сама ситуация вполне возможна.
Возможна. Но это уже сложная система, где и требуются сложные функции, а не та, "классическая". Всё зависит от ситуации.
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

zelenin писал(а): Вы написали, что вам не нравится, что происходит повторный запрос в случае использования matchCallback, но для проверки этого свойства в независимости от того, где происходит проверка, будет запрос. Как может правило провериться, если в его основе сравнение атрибута модели?
Если проверку делать в екшене контроллера то повторного запроса не будет.
zelenin писал(а): а если эта функция будет использована для получения другой модели (с другим id)?
Я выше писал что в этом случае будет серьезный баг. И написал пример как эту функцию стоит переписать что бы хотя бы модель возвращалась соответствующая.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

taral14 писал(а):
zelenin писал(а): Вы написали, что вам не нравится, что происходит повторный запрос в случае использования matchCallback, но для проверки этого свойства в независимости от того, где происходит проверка, будет запрос. Как может правило провериться, если в его основе сравнение атрибута модели?
Если проверку делать в екшене контроллера то повторного запроса не будет.
не будет, если внести в переменную. это то же, что и предложенное ранее $this->_model
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

taral14 писал(а): Я выше писал что в этом случае будет серьезный баг. И написал пример как эту функцию стоит переписать что бы хотя бы модель возвращалась соответствующая.
проглядел) да, устраивает)
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

zelenin писал(а):не будет, если внести в переменную. это то же, что и предложенное ранее $this->_model
Ну я бы не назвал это тем же. Вот пример как я рекомендую использовать проверку с параметрами.

Код: Выделить всё

    public function actionUpdate($id)
    {
        $model = $this->findModel($id);
        if(!Yii::$app->user->can('updateProfile', ['user' => $model])) {
            throw new ForbiddenHttpException(Yii::t('yii', 'Вы не можете изменить этот профиль пользователя.'));
        }
       ...
    }
 
По крайней мере это решение мне нравится больше всего. А matchCallback мне кажется лучше всего использовать для простых проверок. Типа определенных значений гет параметров и т.д.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

taral14 писал(а):
zelenin писал(а):не будет, если внести в переменную. это то же, что и предложенное ранее $this->_model
Ну я бы не назвал это тем же.
не называйте, но это тем же и является.

зачем проверку разносить по разным местам, если можно в одном месте проверять? меньше шанс ошибиться.
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

zelenin писал(а):не называйте, но это тем же и является.
Общего у этих способов только то что оба проверяют права пользователя и оба передают одну и ту же модель в метод can. А способы реализации кардинально отличаются. В прочем вы можете оставаться при своем мнении.
зачем проверку разносить по разным местам, если можно в одном месте проверять? меньше шанс ошибиться.
Я не считаю AccessControl панацеей. Также использовать User::can придется в многих местах если вы захотите сделать приложение более привлекательным для пользователя. А именно скрывать кнопку удаления если у пользователя нет таких прав и т.д. Потому метод User::can будет повсеместно использоваться. Потому для себя в ходе наших обсуждений я пришел к выводу что лучше все же использовать его именно в екшене контроллера. А в конечном итоге это дело вкуса потому что и то и то решение не идеально.
У моего варианта проверка происходить в екшене. У вашего варианта или происходит 2 запроса в базу (1 при проверка и второй при начале работы екшена) или происходит кеширование модели в переменной которое может вызывать ошибку в некоторых случаях.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

taral14 писал(а):
zelenin писал(а):не называйте, но это тем же и является.
Общего у этих способов только то что оба проверяют права пользователя и оба передают одну и ту же модель в метод can. А способы реализации кардинально отличаются. В прочем вы можете оставаться при своем мнении.
да чем способы реализации отличаются? тем что в первом это происходит в разных местах проверка? способы идентичны. Один и тот же метод используется. Делается одинаковое количество запросов. Только в одном случае модель не кэшируется, т.к. надо модифицировать findModel, а во втором случае кэшируется, потому что модификация прошла через внедрение переменной.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

taral14 писал(а):Я не считаю AccessControl панацеей. Также использовать User::can придется в многих местах если вы захотите сделать приложение более привлекательным для пользователя. А именно скрывать кнопку удаления если у пользователя нет таких прав и т.д. Потому метод User::can будет повсеместно использоваться. Потому для себя в ходе наших обсуждений я пришел к выводу что лучше все же использовать его именно в екшене контроллера. А в конечном итоге это дело вкуса потому что и то и то решение не идеально.
У моего варианта проверка происходить в екшене. У вашего варианта или происходит 2 запроса в базу (1 при проверка и второй при начале работы екшена) или происходит кеширование модели в переменной которое может вызывать ошибку в некоторых случаях.
причем тут панацея? Access control создан для ограничения доступа к экшну. Так и используйте его для этого.
Вы почему-то разделяете права, которые требуют для проверки модель и которые не требуют, и почему-то требующие модель, хотите вынести в экшн. Зачем?

Зачем-то сравниваете проверку доступа к экшну и проверку отображения кнопок - это разные задачи.
mickgeek
Сообщения: 957
Зарегистрирован: 2014.05.31, 20:50
Откуда: Санкт-Петербург
Контактная информация:

Re: AccessControl не вызывает bizRule

Сообщение mickgeek »

taral14, вызов User::can() в ActionColumn не требует эксепшена, а решение с проверкой прав в экшене является не только самым тривиальным, но и фактически имеет дублирование ошибки доступа. Судя по тому, что изначально Вы не удосужились воспользоваться поиском или поискать упоминания о "bizRule" в документации, вряд ли Вам нужна сложная функция с кешированием модели. Но Вы правы, выбор решения - дело вкуса, а качество кода пропорционально зависит от квалификации разработчика.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

напомню ваши фразы
Как мне передать дополнительные параметры на права доступа updateOwnProfile? Как сделать это в контроллере понятно. Походу так это не сделать...
Хотя я не уверен на сколько хорошо использовать в них web\User::can. Поскольку мы делаем дополнительный запрос в $this->findModel который без модификации 2 раза запросит с базы информацию.
на первое вам дал ответ
на второе возразил, что вы используете одинаковый метод, который делает необходимое количество запросов. Вы вынесли в экшн и закэшировали модель в переменную, а можно аналогично закэшировать модель в findModel. Таким образом лишний запрос никак не может сказаться на правильности использования одного или второго способа.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

mickgeek писал(а):taral14, вызов User::can() в ActionColumn не требует эксепшена, а решение с проверкой прав в экшене является не только самым тривиальным, но и фактически имеет дублирование ошибки доступа. Судя по тому, что изначально Вы не удосужились воспользоваться поиском или поискать упоминания о "bizRule" в документации, вряд ли Вам нужна сложная функция с кешированием модели. Но Вы правы, выбор решения - дело вкуса, а качество кода пропорционально зависит от квалификации разработчика.
я ждал когда поднимется тема ненужности исключения, поэтому не указал вам ранее, когда может понадобиться несколько раз воспользоваться findModel(), т.к. исключение нужно выбросить только если запрашиваем доступ к странице с отсутствующей сущностью. В остальных случаях, как правило нужно вернуть null.

Соответственно findModel() используем только для получения страниц по id, а для получения моделей используем какую-то обертку над find()->all()
mickgeek
Сообщения: 957
Зарегистрирован: 2014.05.31, 20:50
Откуда: Санкт-Петербург
Контактная информация:

Re: AccessControl не вызывает bizRule

Сообщение mickgeek »

Но это опять же, описание сложной системы, где при одном запросе в контроллере нужно получить разные экземпляры модели. Для стандартного контроллера, где присутствуют функции CRUD без каких-либо наворотов, можно обойтись и простейшим кэшированием. В ином случае, разработчику с опытом не составит труда сообразить и модифицировать код :)
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

mickgeek писал(а):Но это опять же, описание сложной системы, где при одном запросе в контроллере нужно получить разные экземпляры модели. Для стандартного контроллера, где присутствуют функции CRUD без каких-либо наворотов, можно обойтись и простейшим кэшированием. В ином случае, разработчику с опытом не составит труда сообразить и модифицировать код :)
имеется в виду, что в гриде например findModel() не подойдет. А этов принципе несложный пример.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

Код: Выделить всё

    protected function findModel($id)
    {
        $model = $this->getModels($id);
        if (!empty($model)) {
            return $model;
        } else {
            throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist'));
        }
    }

    private function getModels($ids)
    {
        if (is_array($ids)) {
            if (in_array($ids, array_keys($this->models))) {
                $models = [];
                foreach ($ids as $id) {
                    $models[$id] = $this->models[$id];
                }
            } else {
                $models = User::find()->where(['id' => $ids])->indexBy('id')->all();
                if ($models) {
                    $this->models = array_merge($this->models, $models);
                }
            }
        } else {
            $id = $ids;
            if (isset($this->models[$id])) {
                $models = $this->models[$id];
            } else {
                $models = User::find()->where(['id' => $id])->indexBy('id')->one();
                if ($models) {
                    $this->models[$id] = $models;
                }
            }
        }
        return $models;
    }
 
вот такое набросал.
findModel используется дляполучение модели страницы (в экшнах update/create). getModel для получения любых моделей по id.
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

zelenin писал(а):да чем способы реализации отличаются? тем что в первом это происходит в разных местах проверка? способы идентичны.
Да тем что проверка происходит в разных местах. У одного в екшене контроллера у другого в анонимной функции поведения. И я называю это разными реализациями. Дальше на этот счет спорить не вижу смысла.
zelenin писал(а):Вы почему-то разделяете права, которые требуют для проверки модель и которые не требуют, и почему-то требующие модель, хотите вынести в экшн. Зачем?
Нет. Я просто проверяю права по ходу получения информации приложением. Конкретно в этом примере получить модель которую мы передаем в проверку достаточно просто. Вызовом findModel. Но могут быть ситуации где прежде чем мы получим модель которую отправим на проверку мы должны будем проделать много операций. Грубо говоря гет параметр нельзя будет тривиально превратить в модель.
mickgeek писал(а): вызов User::can() в ActionColumn не требует эксепшена, а решение с проверкой прав в экшене является не только самым тривиальным, но и фактически имеет дублирование ошибки доступа. Судя по тому, что изначально Вы не удосужились воспользоваться поиском или поискать упоминания о "bizRule" в документации, вряд ли Вам нужна сложная функция с кешированием модели. Но Вы правы, выбор решения - дело вкуса, а качество кода пропорционально зависит от квалификации разработчика.
Я удосужился поискать упоминание о bizRule. Я даже нашел пользовательскую документацию где описывалось как все это реализовать в yii 2.0
Как видим в дальнейшем этот параметр уже убрали с второй версии. И та документация стала не актуальной. Что и ввело меня в замешательство. По поводу метода с кешированием я уже сказал что это 2 стороны одной медали. И привел пример когда из за него может быть ошибка.
zelenin писал(а): на второе возразил, что вы используете одинаковый метод, который делает необходимое количество запросов. Вы вынесли в экшн и закэшировали модель в переменную, а можно аналогично закэшировать модель в findModel. Таким образом лишний запрос никак не может сказаться на правильности использования одного или второго способа.
метод то используется тот же. Только вызывается он 2 раза =) И сейчас мы пытаемся решить как сделать что бы этот метод не делал 2 запроса если мы его вызовем 2 раза. И естественно это можно сделать. Но этот вопрос мы уже обсуждали.
zelenin писал(а): я ждал когда поднимется тема ненужности исключения, поэтому не указал вам ранее, когда может понадобиться несколько раз воспользоваться findModel(), т.к. исключение нужно выбросить только если запрашиваем доступ к странице с отсутствующей сущностью. В остальных случаях, как правило нужно вернуть null.
Полностью согласен.
Ответить