Мне нужно широко использовать статусы в проекте MT. Они нужны мне для моего users
(active
, suspended
и т. д.), субъект (active
, pending_activation
, inactive
) и для моих подписок (active
, on_grace_period
, not_subscribed
, never_subscribed
).
До сих пор я думал, что лучший способ — хранить их в БД, но у меня есть ощущение, что гораздо проще иметь их в трех других вариантах.
Я также думал, что я могу хранить их в моем Eloquent
Модель как константа. Например, моя модель подписки будет выглядеть так:
// SubscriptionModel
const SUBSCRIBED_ACTIVE = 1;
const SUBSCRIBED_ON_GRACE_PERIOD = 2;
const NOT_SUBSCRIBED = 3;
const NEVER_SUBSCRIBED = 4;
и извлекать их, например, в виде лезвия:
// subscription/index.blade.php
@if($user->subscription->status == /App/SubscriptionModel::SUBSCRIBED_ACTIVE)
<div>You are subscribed. Thank you</div>
@elseif($user->subscription->status == /App/SubscriptionModel::NEVER_SUBSCRIBED)
<div>You need to create a subscription before being granted full access!</div>
@elseif(...)
// and so on
Как насчет того же, но используя папку config и добавив файл с именем status.php
, Доступ к нему в представлении будет выглядеть так:
@if($user->subscription->status == Config::get('status.subscription.SUBSCRIBED_ACTIVE'))
<div>You are subscribed. Thank you</div>
@elseif(...)
// etc
Есть ли способ лучше?
Кроме того, как насчет другой части уравнения, что означает статус, хранящийся в DB
, Должен ли я иметь только status
столбец для таблицы подписки и хранить то, что диктует приложение, или даже лучше создать отдельную таблицу subscription_statuses
и есть foreign_key
subscription_status_id
в subscriptions
Таблица?
Я склонен создавать конкретную модель для статусов, которая действует как перечисление. Так что, если у меня есть Event
модель, у меня может быть соответствующая EventStatus
модель, которая выглядит так:
class EventStatus
{
const CANCELLED = 'EventCancelled';
const POSTPONED = 'EventPostponed';
const RESCHEDULED = 'EventRescheduled';
const SCHEDULED = 'EventScheduled';
}
Затем я могу сделать такие проверки:
$event->status == EventStatus::CANCELLED;
И я обычно добавляю удобные методы в свои модели:
class Event extends Model
{
public function isCancelled()
{
return $this->status == EventStatus::CANCELLED;
}
}
Для «удобных для человека» строк у меня будет языковой файл с текстовыми строками:
<?php // resources/lang/en/event_status.php
return [
EventStatus::CANCELLED => 'Cancelled',
EventStatus::POSTPONED => 'Postponed',
EventStatus::RESCHEDULED => 'Rescheduled',
EventStatus::SCHEDULED => 'Scheduled',
];
Я не согласен с другими ответами. Информация о вашем статусе должна храниться в базе данных. Хорошо спроектированная база данных должна быть понятной и удобной для использования без приложения. Что произойдет, если вы решите использовать эту базу данных для питания чего-то вроде мобильного приложения? Вы будете забирать некоторую информацию из базы данных и хранить ее только в Laravel, а это значит, что вам придется дублировать этот список статусов и в своем мобильном приложении и поддерживать его в обоих.
Такая информация должна храниться в базе данных.
Опция 1
Если ваши пользователи могут иметь только один статус, вам следует использовать enum
поле со значениями subscribed
, subscribed-grace
, not-subscribed
, never-subscribed
Это так же просто в ваших взглядах:
@if($user->subscription->status == 'subscribed'
Вариант 2
Однако, если у вас может быть несколько статусов, то вы почти наверняка должны иметь отдельное поле для каждого статуса и использовать TINYINT
хранить 1
или же 0
,
Отдельная таблица статусов?
Я не вижу веской причины использовать отдельную таблицу состояний, если вы не предполагаете, что можете добавить гораздо больше статусов, и даже если вы добавляете больше, вы можете просто добавить новые значения в enum
или добавьте новое поле в зависимости от того, какой вариант подойдет.
Таблица состояний будет идеальной, если вы планируете использовать статусы для многих других таблиц в базе данных, кроме пользователей.
Единственная другая причина для отдельной таблицы состояния может быть, если вы решили изменить значение определенного статуса. Это означает, что вы можете переименовать статус в таблице состояния, но пользователи все равно будут связаны с ним через его первичный ключ. Изменение значения статуса с помощью двух предыдущих методов повлечет за собой изменения в структуре.
Это действительно сводится к тому, как вы ожидаете, что будете их использовать, но нет никаких причин не хранить их в базе данных.
В моих приложениях я делаю то же самое, что и @Martin Bean, за исключением того, что я не создаю отдельные классы для статуса, я храню их в существующем классе / модели.
Я собираюсь позвонить user
, subscription
а также entity
юридическое лицо.
status
который существует в его модели и таблицы в базе данных.status
лайк ACTIVE
, INACTIVE
, PENDING
и т. д., и они могут различаться для каждой модели.getStatusLabel()
, listStatus()
, isActive()
, isX()
, так далее.isActive/X()
создаются только в том случае, если это действительно необходимо, может быть, модель имеет 4 статуса, но вы сравниваете только один конкретный объект, поэтому я бы создал только один isX()
для этого статуса.class User
{
const STATUS_ACTIVE = 1;
const STATUS_SUSPENDED = 2;
const STATUS_INACTIVE = 3;
/**
* Return list of status codes and labels
* @return array
*/
public static function listStatus()
{
return [
self::STATUS_ACTIVE => 'Active',
self::STATUS_SUSPENDED => 'Suspended',
self::STATUS_INACTIVE => 'Inactive'
]
}
/**
* Returns label of actual status
* @param string
*/
public function statusLabel()
{
$list = self::listStatus();
// little validation here just in case someone mess things
// up and there's a ghost status saved in DB
return isset($list[$this->status])
? $list[$this->status]
: $this->status;
}
/**
* Some actions will happen only if it's active, so I have
* this method for making things easier.
* Other status doesn't have a specific method because
* I usually don't compare agains them
* @return Boolean
*/
public function isActive()
{
return $this->status == self::STATUS_ACTIVE;
}
}
У каждого метода есть свои преимущества и недостатки. Хорошо быть в курсе каждого.
Таблица — Плюсы и минусы (метод AJReading):
Использование константПлюсы / минусы (метод Мартина Бина):
Я использую метод констант, но иногда я думаю, что мой код может быть чище и проще, если бы я использовал таблицы. Это сложный вызов. Я хотел бы, чтобы было хорошо документированное решение для константного метода, по крайней мере, для создания согласованности, но я еще не видел его. В любом случае я не думаю, что есть правильный или неправильный ответ. Выбери один и иди с ним!
Для решений такого рода, спросите себя это:
«Будет ли когда-нибудь экземпляр моего приложения, где он будет делать
смысл для этих констант иметь разные значения?
например тестовая среда, какой-то клон, еще не определенная, но возможная будущая версия …
Если ответ на этот вопрос «да», то, вероятно, он должен идти в конфигурации приложения.
Если маловероятно (или ненормально) изменить значения, они принадлежат и должны быть включены в модель.
Я полагаю, что в этом случае не было бы разумной причины иметь версию приложения с другими значениями, поэтому я бы включил ее в модель.