Конечно, ответ во многом зависит от ваших требований, но я постараюсь ответить на него как можно более глобально.
Вариант 1: реляционный путь
С чисто реляционной точки зрения вы хотите, чтобы ваша база данных была нормализована, что привело бы к вашему первому варианту: таблице ролей с отношением m: n к вашей пользовательской таблице. Это имеет некоторые преимущества:
- Что ж, так можно ожидать, что ваша база данных будет работать, поэтому никакой функциональности, скрытой в ваших сущностях.
- Нет способа испортить ситуацию (например, если у вас есть поле varchar и вы ожидаете, что оно будет иметь какой-то формат, такой как разделение комы)
- Только один способ сделать что-то
Относительно вашего беспокойства о том, что роли никогда не меняются: Хранение данных реляционным не о том, как часто они меняются. И всегда нужно помнить, что требования меняются. Чем больше вы напутаете во имя оптимизации, тем больше вы будете бороться позже, когда возникнет необходимость в большем количестве ролей, которые меняются чаще.
Конечно, у вас могут быть проблемы с производительностью, особенно если вы сталкиваетесь с какой-то страстной проблемой загрузки или если вы не кэшируете вещи и должны перезагружать роли при каждой загрузке страницы. Но, опять же, реляционные базы данных предназначены для поддержки таких вещей, поэтому здесь должны быть способы оптимизации запросов.
Вариант 2: Взлом
Ваш второй вариант, просто хранение всех ролей в varchar, был бы намного лучше с точки зрения производительности. Только одно текстовое поле для загрузки, некоторая обработка PHP, и все готово. С другой стороны, вы можете столкнуться с несколькими проблемами:
- У вас нет контроля над полем varchar, поэтому один сценарий сбоя может поставить под угрозу все ваше приложение (Это действительно плохо, но в зависимости от вашего проекта, если вы являетесь единственным разработчиком и знаете, что делаете, он может пойти хорошо)
- Обновление одного набора данных намного сложнее, так как вам нужно извлечь все роли, обновить соответствующие и сохранить обратно
- Запрашивать всех пользователей с определенной ролью намного сложнее
- Удалить роль намного сложнее
Вариант 3: прагматичное решение
Третий вариант с 5 логическими значениями для каждой роли находится посередине: нет никакого способа испортить это, и производительность не должна быть проблемой. Обновление легко, а также удаление роли или добавление новой. Понятно, что делают поля, так что с этой стороны тоже никакого вреда. Это делает вашу сущность и базу данных более уродливыми, и у вас будут имена ролей в вашей пользовательской модели, а также для сопоставления полей true / false с правильными именами ролей, что может немного сбивать с толку.
Результат
Это все в виду, я бы выбрал вариант 1. Можно предположить, что производительность - это проблема, но если я не докажу это, я не думаю о таких вещах. В конце концов, что вы делаете, когда у вас действительно есть проблемы с производительностью? Вы можете добавить дополнительное оборудование, оптимизировать ваши dbms, оптимизировать запросы или, возможно, использовать dbms с большей встроенной производительностью (Hello Oracle!).
И вы всегда можете использовать опцию 3 позже, если докажете, что ваше приложение работает медленно из-за таблицы ролей. Вам просто нужно изменить свою пользовательскую сущность и иметь один запрос, который извлекает роли и устанавливает правильные комбинации истина / ложь для каждого пользователя. Если программное обеспечение чистое, это проблема часов, поэтому нет необходимости делать это сейчас, полагая, что производительность может быть плохой.