Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 26.12.2016 18:55:08

Выборка из БД ...

(Laravel 5.3 и базовая auth)
Есть три таблицы: users, roles и permits.
Первая и вторая, вторая и третья связаны отношениями "многие ко многим".
Задача: для юзера, через назначенные ему роли, выбрать права, которыми он обладает (права назначаются роли).
Делаю так:
// получаем id в таблице roles для пользователя
        $roles_id = Auth::user()->roles->pluck('id');
// получаем все права в виде json-массива
        $permits = Role::find($roles_id)->permits()->pluck('slug');
// получаем нужный простой массив прав
        $permits_array = json_decode($permits, true);
Вопрос:
- можно ли реализовать проще?
- что будет, если ролей у юзера будет несколько? (Пока я прописывал только одну)

Не в сети

#2 27.12.2016 06:41:06

Re: Выборка из БД ...

можно проще. на правах нет никаких атрибутов кроме слага соответственно заводить под права таблицу нет смысла.

кроме этого нужно иметь возможность задавать отдельные пермишены на пользователе не через группу – быстро понадобится по-быстрому дать пользователю что-нибудь иметь возможность делать лично а не через права группы.

соответственно users и roles оставить, отношение многие-ко-многим оставить, на пользователе и на роли завести поле permissions тип text, содержание – массив в json-е. в модели объявить в $casts: 'permissions' => 'array'

хранить отдельные пермишены текстовыми строками вида "posts.*", "posts.edit". при загрузке пользователя выбирать его роли, объединять пермишены с array_merge, запоминать в тегированном кэше с ключом "users" (сбрасывать по тэгу при изменениях в пользователях). при проверке доступа искать пермишены в кэше или загружать из базы и проверять для "posts.edit" в массиве наличие записей "posts.edit", "posts.*" или "*". соответственно право "*" означает что пользователь – superadmin и может делать всё

как-то так

Не в сети

#3 27.12.2016 07:18:25

Re: Выборка из БД ...

Я бы роли сделал отдельным полем в users в виде smallint. Иначе на более менее сложном проекте упрешься в кучу ограничений. На очень сложном, я бы и от permit избавился.

А вообще, не лучше использовать готовый популярный пакет, к которому в сети можно найти много готовых рецептов?

Не в сети

#4 27.12.2016 07:38:00

Re: Выборка из БД ...

зачем smallint? можно просто сделать role_id unsigned int и сделать один-ко-многим на таблицу ролей, но заранее решать что уже точно известны все роли и меняться они никогда не будут – это слишком смело smile многие-ко-многим – это тоже один из вариантов, мы же не знаем заранее что там в ТЗ. может там прописано что пользователь может принадлежать нескольким группам одновременно?

на более менее сложном проекте упрешься в кучу ограничений

как раз со smallint и упрёшься. ещё забудешь по ходу дела что отдельные значения означают и накосячишь где-нибудь

о, можно ещё надёжнее – завести на пользователе tinyint is_admin! максимальная надёжность и производительность! )))

Не в сети

#5 27.12.2016 07:38:06

Re: Выборка из БД ...

AlexeyMezenin пишет:

А вообще, не лучше использовать готовый популярный пакет, к которому в сети можно найти много готовых рецептов?

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

Вот тут обсуждалась тема.

Не в сети

#6 27.12.2016 08:07:07

Re: Выборка из БД ...

constb пишет:

многие-ко-многим – это тоже один из вариантов

Ну да, только почему так много заказчиков ищут разработчика, который бы завершил их проект, потому что их разработчик "ушел на другой проект", "не смог продолжить по личным причинам" и т.д.? Посмотришь проект - а там такая архитектура, с которой шаг влево не сделать. Пример - нужно показать выборку комментариев к публикациям пользователей с опредленными permissions по определенным странам. Наворотят вот такое, а потом начинаются вопросы на форумах и SO "а как сделать выборку, если у меня many-to-many, дальше hasMany и там еще many-to-many... еще параллельно по many-to-many страны отфильровать?".

о, можно ещё надёжнее – завести на пользователе tinyint is_admin! максимальная надёжность и производительность! )))

KISS. Для большинства приложений нужно 1-3 роли без разделения полномочий, а в полуторах методах, где это используется, можно сделать локальную проверку или дополнительную роль. Но большинство все равно лепят то, что лепит автор. А вот посмотришь код сложных проектов от серьезных ребят, там как раз используешься тот замечательный надежный isAdmin().

Изменено AlexeyMezenin (27.12.2016 08:26:16)

Не в сети

#7 27.12.2016 08:23:34

Re: Выборка из БД ...

AlexeyMezenin пишет:

Я бы роли сделал отдельным полем в users в виде smallint. Иначе на более менее сложном проекте упрешься в кучу ограничений. На очень сложном, я бы и от permit избавился.

А вообще, не лучше использовать готовый популярный пакет, к которому в сети можно найти много готовых рецептов?

Я забыл написать что не нужно менять структуру таблиц которые создают Laravel и SleepingOwl.
Вот и использую пакет "Совы", но он не имеет проверок, кто может туда переться, а кто нет. Далее прикручу Sentinel вместо Auth.
Мой вопрос связан с middleware для админки ...
Всем спасибо. (Для многих ролей не обойтись видно без foreach с последующим объединением массивов ...)

Изменено Grumm (27.12.2016 08:28:11)

Не в сети

#8 27.12.2016 08:50:48

Re: Выборка из БД ...

Grumm, когда всем этим будешь заниматься, создай много ролей и пермитов для тестирования и смотри на количество запросов, которые создает Laravel. В этом тебе поможет Laravel Debugbar.

Не в сети

#9 27.12.2016 08:59:34

Re: Выборка из БД ...

Grumm пишет:

Вот и использую пакет "Совы", но он не имеет проверок, кто может туда переться, а кто нет.

Разве не имеет? "Сова", вроде, с ролями неплохо работает, или я не так Вас понял?

Не в сети

#10 28.12.2016 17:33:13

Re: Выборка из БД ...

AlexeyMezenin пишет:

Grumm, когда всем этим будешь заниматься, создай много ролей и пермитов для тестирования и смотри на количество запросов, которые создает Laravel. В этом тебе поможет Laravel Debugbar.

Эта панелька внизу уже стала родной на локали! smile)

Не в сети

#11 28.12.2016 17:34:47

Re: Выборка из БД ...

Androbim пишет:
Grumm пишет:

Вот и использую пакет "Совы", но он не имеет проверок, кто может туда переться, а кто нет.

Разве не имеет? "Сова", вроде, с ролями неплохо работает, или я не так Вас понял?

Это админка. Она не имеет системы авторизации. Возможно вы путаете с Sentinel.

Не в сети

#12 28.12.2016 17:41:26

Re: Выборка из БД ...

Может кому надо будет:
// получаем права пользователя в виде массива
        $roles_id = Auth::user()->roles->pluck('id');
        $result = array();
// перебираем полученные id
        foreach ($roles_id as $item)
        {
            $permits = Role::find($item)->permits()->pluck('slug');
            $permits_array = json_decode($permits, true);
// результирующий массив, в котором собраны все права закрепленные за юзером, исключая повторяющиеся.
            $result = array_unique(array_merge($result, $permits_array));
        }
/**
* Таким образом можно проверять юзера на право что либо совершать в админке,
* присваивая ему любое количество ролей, с любым набором прав.
*/

Не в сети

#13 28.12.2016 17:45:05

Re: Выборка из БД ...

Grumm пишет:

Может кому надо будет:

Присвой пользователю 3-4 роли и несколько пермитов и посмотри сколько запросов в БД создаст код.

Не в сети

#14 28.12.2016 17:48:43

Re: Выборка из БД ...

AlexeyMezenin пишет:
Grumm пишет:

Может кому надо будет:

Присвой пользователю 3-4 роли и несколько пермитов и посмотри сколько запросов в БД создаст код.

Сегодня мозги уже кипят. Завтра буду гонять тестами ...

Не в сети

#15 28.12.2016 18:01:34

Re: Выборка из БД ...

Grumm пишет:

Это админка. Она не имеет системы авторизации. Возможно вы путаете с Sentinel.

Я не путаю, системы авторизации не имеет, верно, но с auth и ролями работает легко.

Не в сети

#16 28.12.2016 18:07:29

Re: Выборка из БД ...

Grumm пишет:

Я не путаю, системы авторизации не имеет, верно, но с auth и ролями работает легко.

Аха, работает. Админ, не админ. Это всё.
Скажите как по вашему разрешить к примеру смотреть и банить юзеров, но не удалять их и не править им профиль? И не лезть в другие разделы админки?

Не в сети

#17 28.12.2016 18:18:42

Re: Выборка из БД ...

Ну лично у меня, например, контент-менеджер не имеет доступа к редактированию аккаунтов, но публикует новости. Это на уровне разделов, вроде бы, можно и на уровне методов, но сам пока не проверял. Сейчас работаю над тем, чтобы в самой админке создать раздел, в котором админ сможет работать с ролями, определяя им права в "Сове", а политика будет работать с этой моделью.

Изменено Androbim (28.12.2016 18:24:21)

Не в сети

#18 29.12.2016 17:59:06

Re: Выборка из БД ...

AlexeyMezenin пишет:

Присвой пользователю 3-4 роли и несколько пермитов и посмотри сколько запросов в БД создаст код.

Присвоил. Четыре роли, у каждой по четыре права. Запросов 20, время 90 ms. В том числе запросы самого фреймворка (5 запросов).
В общем: разных админов не будет очень много (да хоть 100) и толпой они не ходят. Если в админку полезут хакеры, отработает трейт по ограничению запросов с одного Ip. Конечно запросов много, но или универсальность, или оптимальность. Почему я и вынес вопрос - "как сделать проще ...".

Изменено Grumm (29.12.2016 18:01:29)

Не в сети

#19 29.12.2016 18:21:05

Re: Выборка из БД ...

AlexeyMezenin пишет:

Запросов 20

Дак приложение будет эти 20 (дальше больше) запросов на каждый запрос запускать. Проверка ведь каждого пользователя будет идти? Если нет, то какой смысл вообще в использовании ролей и пермитов?

К слову, isAdmin(), над которым выше посмеялись, вообще не создаст ни одного лишнего запроса, т.к. будут использоваться данные из запроса в users, который Laravel создает для каждого запроса.

Не в сети

#20 29.12.2016 18:23:58

Re: Выборка из БД ...

AlexeyMezenin пишет:

Проверка ведь каждого пользователя будет идти?

С какой стати пользователем переться в админку? Этот посредник работает только для админки. Проверка админ\не админ меня не устраивает. Для этого вообще ничего не надо сочинять ...

Изменено Grumm (29.12.2016 18:26:12)

Не в сети

#21 29.12.2016 18:30:51

Re: Выборка из БД ...

Grumm пишет:

С какой стати пользователем переться в админку?

Еще раз, тогда какой вообще смысл в пермитах и ролях?

Не в сети

#22 29.12.2016 18:37:01

Re: Выборка из БД ...

Тема закрыта.

Не в сети

#23 29.12.2016 18:39:35

Re: Выборка из БД ...

"Ой, всёёё!!!" smile

Не в сети

#24 29.12.2016 18:43:49

Re: Выборка из БД ...

Grumm, с таким подходом к разработке далеко не уедешь. Создал совершенно ненужную фичу, с двумя many-to-many - 5 таблиц! Создал без использования жадной загрузки, в итоге 20 совершенно ненужных запросов даже на пустом проекте. Почитай про принцип KISS - Keep it simple stupid.

Не в сети

#25 02.01.2017 15:38:48

Re: Выборка из БД ...

Я вот не понял, зачем одному пользователю несколько ролей? Ну это ладно, это разработчику виднее - хотя он сильно осложнил себе жизнь. И не только связью "многие-ко-многим", это-то рутина. А шизофреничностью назначения прав. Менеджеру нельзя, бухгалтеру можно, а если он и менеджер и бухгалтер  - ему можно или нельзя?

Не проще сделать НОРМАЛЬНЫЙ набор ролей? Если ты главбух - ну и заходи как главбух, а не скрещивай менеджера с бухгалтером.

Но что совсем удручает - какие-то джсон-массивы. Одним банальным SQL-запросом эта задача решается. Кинул запрос - и вуяля: получил права, сиди теперь разрешай конфликты между ними smile

Но нет. Теперь так нельзя. Нельзя писать запрос и получать ответ. Надо получать массивы в три этапа...

Пойду стакан накачу...

Не в сети

Подвал раздела