Laravel - 在哪里存储状态(标志)?模型,Class 还是配置文件夹?
Laravel - Where to store statuses (flags)? Model, Class or config folder?
我需要在 mt 项目中广泛使用状态。我的 users
(active
、suspended
等)、一个实体(active
、pending_activation
、inactive
)和我的订阅(active
、on_grace_period
、not_subscribed
、never_subscribed
)。
到目前为止,我认为最好的方法是将它们存储在数据库中,但我感觉将它们放在其他 3 个选项中要容易得多。
我还认为我可以将它们作为常量存储在我的 Eloquent
模型中。例如,我的订阅模型如下所示:
// SubscriptionModel
const SUBSCRIBED_ACTIVE = 1;
const SUBSCRIBED_ON_GRACE_PERIOD = 2;
const NOT_SUBSCRIBED = 3;
const NEVER_SUBSCRIBED = 4;
并检索它们,例如在 blade 视图中:
// 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
如何做同样的事情,但使用配置文件夹并添加一个名为 status.php
的文件。在视图中访问它就像:
@if($user->subscription->status == Config::get('status.subscription.SUBSCRIBED_ACTIVE'))
<div>You are subscribed. Thank you</div>
@elseif(...)
// etc
有没有更好的方法?
此外,等式的另一部分如何,即存储在 DB
中的状态。我是否应该只有一个 status
列用于订阅 table 并存储应用程序指示的内容,或者甚至更好地创建一个单独的 table subscription_statuses
并有一个 foreign_key
subscription_status_id
在 subscriptions
table?
对于这种性质的决定,问问自己:
"Will there ever be an instance of my application where it would make
sense for these constants to have different values?"
例如一个测试环境,某种克隆,一些尚未定义但可能是未来版本...
如果该问题的答案是 "yes",那么它可能应该进入应用程序配置。
如果值不太可能(或愚蠢)发生变化,它们属于并且应该进入模型。
我建议在这种情况下,没有合理的理由让应用程序版本具有不同的值,因此我将其放入模型中。
我不同意其他答案。您的状态信息应该存储在数据库中。设计良好的数据库应该在没有应用程序的情况下清晰易用。如果您决定也使用此数据库来支持移动应用程序之类的东西,会发生什么情况?您将从数据库中取出一些信息并将其仅存储在 Laravel 中,这意味着您也必须在您的移动应用程序中复制该状态列表,并在两者之间维护它。
这种信息应该存储在数据库中。
选项 1
如果您的用户只能有一个状态,那么您应该使用一个 enum
字段,其值为 subscribed
、subscribed-grace
、not-subscribed
、never-subscribed
这在您看来很简单:
@if($user->subscription->status == 'subscribed'
选项 2
但是,如果您可能有多个状态,那么几乎可以肯定每个状态都有一个单独的字段,并使用 TINYINT
来存储 1
或 0
。
独立状态table?
我看不出使用单独状态 table 的充分理由,除非您预计可能会添加更多状态,即使您要添加更多状态,也可以向 [=11 添加新值=] 或根据适合的选项添加新字段。
如果您计划将状态用于数据库中除用户之外的许多其他 table,那么状态 table 将是理想的选择。
单独状态 table 的唯一其他原因是您决定更改特定状态的含义。这意味着您可以重命名状态 table 中的状态,但用户仍会通过它的主键链接到它。使用前两种方法改变状态的含义会涉及到结构的改变。
这实际上取决于您预期如何使用它们,但没有理由不将它们保存在数据库中。
我倾向于为状态创建一个特定的模型,作为一个枚举。因此,如果我有一个 Event
模型,我可能会有一个相应的 EventStatus
模型,如下所示:
class EventStatus
{
public const CANCELLED = 'EventCancelled';
public const POSTPONED = 'EventPostponed';
public const RESCHEDULED = 'EventRescheduled';
public const SCHEDULED = 'EventScheduled';
}
然后我可以像这样检查:
$event->status === EventStatus::CANCELLED;
而且我通常也会为我的模型添加便捷方法:
class Event extends Model
{
public function isCancelled(): bool
{
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',
];
每种方法各有利弊。了解每一个都很好。
Table - 优点和缺点(AJReading 的方法):
- 添加和维护 table SEEMS 很乏味
- 只是有另一个 table 和模型可以让我们的代码感觉更混乱(并不是说这是不使用的一个很好的理由只是说它有点真实)
- 当我们的应用程序逻辑依赖于数据库中的某些东西时会变得很尴尬(数据库中的东西感觉它们应该是可变的,当我们将应用程序逻辑基于它们时它们是必需的)
- 现在我们有迁移,但在它们之前,这些曾经是开发人员存在的祸根(它们会使服务器之间的切换成为一件可怕的苦差事,因为你必须记住添加新状态,否则你的应用程序会崩溃)......您将不得不对任何数据库更改执行此操作,但这些仍然是我最常执行的操作
- 有利于数据完整性
使用常量:Pros/cons(Martin Bean 的方法):
- 避免上述缺点
- 这些很容易在您的代码和基础逻辑中引用
- 您甚至不必创建新模型或 table(他在他的示例中这样做,但您也可以将它们放在事件模型中)
- 它们非常适合仅在幕后使用的值
- 他们减少了查询量
- 他们就是不喜欢那么多工作。它们似乎更容易重构。
- 缺点:当您标记它们、检索所有它们、获取描述等时,它们会变得有点尴尬。翻译解决方案是一个很好的解决方案,但如果您不在您的应用程序中使用翻译,那么这是一个也有点尴尬。
- 最终他们会破坏您正在进行的 ORM 流程。如果您所有其他模型都扩展 Eloquent 那么这会稍微打破常规。
- 对于如何最好地做到这一点还没有达成真正的共识。很多人每次都使用不同的方法。
- 就像 AJReading 所说的,如果您需要单独使用数据库来处理项目的另一个方面,那将行不通
我使用常量方法,但有时我认为如果我使用 tables,我的代码可能会更清晰、更简单。这是一个艰难的决定。我希望常量方法有一个有据可查的解决方案,至少可以创建一致性,但我还没有看到。无论哪种方式,我认为没有正确或错误的答案。挑一个一起去吧!
在我的应用程序中,我与@Martin Bean 类似,除了我不为状态创建单独的 类,我将其存储在现有的 class/Model.
中
我要将 user
、subscription
和 entity
称为 实体。
- 实体 有一个存在于它的模型中的
status
和存在于数据库中的 table。
- 每个模型都有
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;
}
}
我需要在 mt 项目中广泛使用状态。我的 users
(active
、suspended
等)、一个实体(active
、pending_activation
、inactive
)和我的订阅(active
、on_grace_period
、not_subscribed
、never_subscribed
)。
到目前为止,我认为最好的方法是将它们存储在数据库中,但我感觉将它们放在其他 3 个选项中要容易得多。
我还认为我可以将它们作为常量存储在我的 Eloquent
模型中。例如,我的订阅模型如下所示:
// SubscriptionModel
const SUBSCRIBED_ACTIVE = 1;
const SUBSCRIBED_ON_GRACE_PERIOD = 2;
const NOT_SUBSCRIBED = 3;
const NEVER_SUBSCRIBED = 4;
并检索它们,例如在 blade 视图中:
// 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
如何做同样的事情,但使用配置文件夹并添加一个名为 status.php
的文件。在视图中访问它就像:
@if($user->subscription->status == Config::get('status.subscription.SUBSCRIBED_ACTIVE'))
<div>You are subscribed. Thank you</div>
@elseif(...)
// etc
有没有更好的方法?
此外,等式的另一部分如何,即存储在 DB
中的状态。我是否应该只有一个 status
列用于订阅 table 并存储应用程序指示的内容,或者甚至更好地创建一个单独的 table subscription_statuses
并有一个 foreign_key
subscription_status_id
在 subscriptions
table?
对于这种性质的决定,问问自己:
"Will there ever be an instance of my application where it would make sense for these constants to have different values?"
例如一个测试环境,某种克隆,一些尚未定义但可能是未来版本...
如果该问题的答案是 "yes",那么它可能应该进入应用程序配置。
如果值不太可能(或愚蠢)发生变化,它们属于并且应该进入模型。
我建议在这种情况下,没有合理的理由让应用程序版本具有不同的值,因此我将其放入模型中。
我不同意其他答案。您的状态信息应该存储在数据库中。设计良好的数据库应该在没有应用程序的情况下清晰易用。如果您决定也使用此数据库来支持移动应用程序之类的东西,会发生什么情况?您将从数据库中取出一些信息并将其仅存储在 Laravel 中,这意味着您也必须在您的移动应用程序中复制该状态列表,并在两者之间维护它。
这种信息应该存储在数据库中。
选项 1
如果您的用户只能有一个状态,那么您应该使用一个 enum
字段,其值为 subscribed
、subscribed-grace
、not-subscribed
、never-subscribed
这在您看来很简单:
@if($user->subscription->status == 'subscribed'
选项 2
但是,如果您可能有多个状态,那么几乎可以肯定每个状态都有一个单独的字段,并使用 TINYINT
来存储 1
或 0
。
独立状态table?
我看不出使用单独状态 table 的充分理由,除非您预计可能会添加更多状态,即使您要添加更多状态,也可以向 [=11 添加新值=] 或根据适合的选项添加新字段。
如果您计划将状态用于数据库中除用户之外的许多其他 table,那么状态 table 将是理想的选择。
单独状态 table 的唯一其他原因是您决定更改特定状态的含义。这意味着您可以重命名状态 table 中的状态,但用户仍会通过它的主键链接到它。使用前两种方法改变状态的含义会涉及到结构的改变。
这实际上取决于您预期如何使用它们,但没有理由不将它们保存在数据库中。
我倾向于为状态创建一个特定的模型,作为一个枚举。因此,如果我有一个 Event
模型,我可能会有一个相应的 EventStatus
模型,如下所示:
class EventStatus
{
public const CANCELLED = 'EventCancelled';
public const POSTPONED = 'EventPostponed';
public const RESCHEDULED = 'EventRescheduled';
public const SCHEDULED = 'EventScheduled';
}
然后我可以像这样检查:
$event->status === EventStatus::CANCELLED;
而且我通常也会为我的模型添加便捷方法:
class Event extends Model
{
public function isCancelled(): bool
{
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',
];
每种方法各有利弊。了解每一个都很好。
Table - 优点和缺点(AJReading 的方法):
- 添加和维护 table SEEMS 很乏味
- 只是有另一个 table 和模型可以让我们的代码感觉更混乱(并不是说这是不使用的一个很好的理由只是说它有点真实)
- 当我们的应用程序逻辑依赖于数据库中的某些东西时会变得很尴尬(数据库中的东西感觉它们应该是可变的,当我们将应用程序逻辑基于它们时它们是必需的)
- 现在我们有迁移,但在它们之前,这些曾经是开发人员存在的祸根(它们会使服务器之间的切换成为一件可怕的苦差事,因为你必须记住添加新状态,否则你的应用程序会崩溃)......您将不得不对任何数据库更改执行此操作,但这些仍然是我最常执行的操作
- 有利于数据完整性
使用常量:Pros/cons(Martin Bean 的方法):
- 避免上述缺点
- 这些很容易在您的代码和基础逻辑中引用
- 您甚至不必创建新模型或 table(他在他的示例中这样做,但您也可以将它们放在事件模型中)
- 它们非常适合仅在幕后使用的值
- 他们减少了查询量
- 他们就是不喜欢那么多工作。它们似乎更容易重构。
- 缺点:当您标记它们、检索所有它们、获取描述等时,它们会变得有点尴尬。翻译解决方案是一个很好的解决方案,但如果您不在您的应用程序中使用翻译,那么这是一个也有点尴尬。
- 最终他们会破坏您正在进行的 ORM 流程。如果您所有其他模型都扩展 Eloquent 那么这会稍微打破常规。
- 对于如何最好地做到这一点还没有达成真正的共识。很多人每次都使用不同的方法。
- 就像 AJReading 所说的,如果您需要单独使用数据库来处理项目的另一个方面,那将行不通
我使用常量方法,但有时我认为如果我使用 tables,我的代码可能会更清晰、更简单。这是一个艰难的决定。我希望常量方法有一个有据可查的解决方案,至少可以创建一致性,但我还没有看到。无论哪种方式,我认为没有正确或错误的答案。挑一个一起去吧!
在我的应用程序中,我与@Martin Bean 类似,除了我不为状态创建单独的 类,我将其存储在现有的 class/Model.
中我要将 user
、subscription
和 entity
称为 实体。
- 实体 有一个存在于它的模型中的
status
和存在于数据库中的 table。 - 每个模型都有
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;
}
}