Фреймворк Symfony;идиоматический способ хранения роли пользователя - PullRequest
8 голосов
/ 06 марта 2012

В моем приложении Symfony 2 я хочу использовать стандартную систему авторизации пользователей и ролей (http://symfony.com/doc/2.0/book/security.html)

Мой пользователь - это сущность, хранящаяся в базе данных с доктриной (реализация интерфейса пользователя). У меня будет 5 предопределенных ролейв моей системе каждый пользователь может иметь несколько из этих ролей.

Какой самый идиоматичный способ реализации этого? Я думаю о следующих трех решениях.

  1. Создайте отдельную сущность Роль и создайте отношение «многие ко многим» с сущностью пользователя

    • Плюс: Легко получить всех пользователей с определенной ролью
    • Con: Требуется много ресурсов?(Всегда требуется двойное объединение, чтобы получить все роли для пользователя)
    • Con: не idomatic? Количество ролей (и их имен) никогда не меняется, поэтому имеет смысл хранить их в базе данных какотдельный объект?
  2. Есть поле внутри пользователя, представляющее собой отсортированный запятый список ролей, а getRoles () реализован как explode(',',this.all_roles)

    • Плюс: не дорого в вычислительном отношении
    • Con: Трудно получить всех пользователей с определенной ролью
    • Con: Подобные поля базы данных заставляют котят плакать (нормализация и прочее)
  3. Имеют 5 двоичных полей в пользовательском объекте для каждой роли

    • Plus: не дорого в вычислительном отношении
    • Plus: легко получить все пользователи сконкретная роль
    • Con: Это все еще нехорошо

Какой самый идиоматичный способ реализации этой системы?

1 Ответ

12 голосов
/ 11 марта 2012

Конечно, ответ во многом зависит от ваших требований, но я постараюсь ответить на него как можно более глобально.

Вариант 1: реляционный путь

С чисто реляционной точки зрения вы хотите, чтобы ваша база данных была нормализована, что привело бы к вашему первому варианту: таблице ролей с отношением m: n к вашей пользовательской таблице. Это имеет некоторые преимущества:

  • Что ж, так можно ожидать, что ваша база данных будет работать, поэтому никакой функциональности, скрытой в ваших сущностях.
  • Нет способа испортить ситуацию (например, если у вас есть поле varchar и вы ожидаете, что оно будет иметь какой-то формат, такой как разделение комы)
  • Только один способ сделать что-то

Относительно вашего беспокойства о том, что роли никогда не меняются: Хранение данных реляционным не о том, как часто они меняются. И всегда нужно помнить, что требования меняются. Чем больше вы напутаете во имя оптимизации, тем больше вы будете бороться позже, когда возникнет необходимость в большем количестве ролей, которые меняются чаще.

Конечно, у вас могут быть проблемы с производительностью, особенно если вы сталкиваетесь с какой-то страстной проблемой загрузки или если вы не кэшируете вещи и должны перезагружать роли при каждой загрузке страницы. Но, опять же, реляционные базы данных предназначены для поддержки таких вещей, поэтому здесь должны быть способы оптимизации запросов.

Вариант 2: Взлом

Ваш второй вариант, просто хранение всех ролей в varchar, был бы намного лучше с точки зрения производительности. Только одно текстовое поле для загрузки, некоторая обработка PHP, и все готово. С другой стороны, вы можете столкнуться с несколькими проблемами:

  • У вас нет контроля над полем varchar, поэтому один сценарий сбоя может поставить под угрозу все ваше приложение (Это действительно плохо, но в зависимости от вашего проекта, если вы являетесь единственным разработчиком и знаете, что делаете, он может пойти хорошо)
  • Обновление одного набора данных намного сложнее, так как вам нужно извлечь все роли, обновить соответствующие и сохранить обратно
  • Запрашивать всех пользователей с определенной ролью намного сложнее
  • Удалить роль намного сложнее

Вариант 3: прагматичное решение

Третий вариант с 5 логическими значениями для каждой роли находится посередине: нет никакого способа испортить это, и производительность не должна быть проблемой. Обновление легко, а также удаление роли или добавление новой. Понятно, что делают поля, так что с этой стороны тоже никакого вреда. Это делает вашу сущность и базу данных более уродливыми, и у вас будут имена ролей в вашей пользовательской модели, а также для сопоставления полей true / false с правильными именами ролей, что может немного сбивать с толку.

Результат

Это все в виду, я бы выбрал вариант 1. Можно предположить, что производительность - это проблема, но если я не докажу это, я не думаю о таких вещах. В конце концов, что вы делаете, когда у вас действительно есть проблемы с производительностью? Вы можете добавить дополнительное оборудование, оптимизировать ваши dbms, оптимизировать запросы или, возможно, использовать dbms с большей встроенной производительностью (Hello Oracle!).

И вы всегда можете использовать опцию 3 позже, если докажете, что ваше приложение работает медленно из-за таблицы ролей. Вам просто нужно изменить свою пользовательскую сущность и иметь один запрос, который извлекает роли и устанавливает правильные комбинации истина / ложь для каждого пользователя. Если программное обеспечение чистое, это проблема часов, поэтому нет необходимости делать это сейчас, полагая, что производительность может быть плохой.

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