【问题标题】:Laravel - Where to store statuses (flags)? Model, Class or config folder?Laravel - 在哪里存储状态(标志)?模型、类或配置文件夹?
【发布时间】:2023-03-27 14:50:01
【问题描述】:

我需要在 mt 项目中广泛使用状态。我的usersactivesuspended 等)、一个实体(activepending_activationinactive)和我的订阅(activeon_grace_period、@987654329)需要它们@, never_subscribed)。

到目前为止,我认为最好的方法是将它们存储在数据库中,但我觉得将它们存储在其他 3 个选项中要容易得多。

我还认为我可以将它们作为常量存储在我的 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 并在 subscriptions 表中创建一个 foreign_key subscription_status_id

【问题讨论】:

  • 这些当然应该存储在数据库中,看下面我的回答
  • 即使存储在数据库中也需要Model::select('myvar')-&gt;where('myvar','=' myvar)-&gt;get();。 @Cristian,检查我的 awnser,您可以在 .env os 中使用全局变量为此创建一个文件。这取决于你是否需要更多的变量,如果你只需要 4 个变量,你不应该只为它们创建一个文件,它并不优雅。我在我的答案中标记了一条评论,因为用户投票反对,原因是probavly* you must create and config file not .env。人们对您投反对票并且没有解决方案或解释为什么您的答案不是更好,这很糟糕。
  • 如果需要方便按状态选择用户,您可以编写范围。存储在 env 文件中是最糟糕的地方。您有不同环境的 env 文件,并且必须跨 env 文件维护这些列表。它们应该存储在一个中心位置,即数据库中。如果没有它,您将如何仅通过查看数据库来确定状态?你的回答被否决了,因为这是个糟糕的建议。

标签: php mysql laravel eloquent status


【解决方案1】:

我倾向于为状态创建一个特定的模型,它充当一个枚举。所以如果我有一个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',
];

【讨论】:

  • 您的回答最符合我的需要。我还有一个问题。目前我的大部分状态都作为不同的表存储在数据库中。像:event_statuses。当我想检索一个时,我会(有一个模型)EventStatus::findFirstBySlug('cancelled')。但是为了比较(使用关系)我只是做if( $event-&gt;event_status-&gt;slug == 'cancelled' ) ... 。对于我的问题。哪个选项更易于使用? EventStatus 的 DB 模型还是您所说的简单模型?我想你的 EventStatus 没有链接到数据库。
  • 简写数组的语法是否正确?数组一般好吗?每行末尾应该是逗号而不是分号?否则这对我来说看起来很棒。
  • @johnsnails 不,它们确实应该是逗号。好地方!
【解决方案2】:

我不同意其他答案。您的状态信息应存储在数据库中。一个设计良好的数据库应该在没有应用程序的情况下清晰可用。如果您决定使用这个数据库来支持移动应用程序之类的东西,会发生什么?您将从数据库中取出一些信息并仅将其存储在 Laravel 中,这意味着您还必须在移动应用程序中复制该状态列表,并在两者之间进行维护。

此类信息应存储在数据库中。

选项 1

如果您的用户只能拥有一种状态,那么您应该使用具有值 subscribedsubscribed-gracenot-subscribednever-subscribedenum 字段

这在你看来很简单:

@if($user->subscription->status == 'subscribed'

选项 2

但是,如果您可能有多个状态,那么您几乎可以肯定每个状态都有一个单独的字段,并使用TINYINT 来存储10

单独的状态表?

我看不出使用单独状态表的充分理由,除非您预计可能会添加更多状态,即使您要添加更多状态,您也可以向 enum 添加新值或添加新字段,具体取决于哪个选项适合。

如果您打算将状态用于数据库中除用户之外的许多其他表,则状态表将是理想的选择。

单独的状态表的唯一其他原因是您决定更改特定状态的含义。这意味着您可以重命名状态表中的状态,但用户仍将通过其主键链接到它。使用前两种方法更改状态的含义会涉及到结构的更改。

这实际上取决于您预期如何使用它们,但没有理由不将它们保存在数据库中。

【讨论】:

  • 我目前将我的状态存储为单独的表(有些是可重复使用的,有些不是)。我对 ENUM 的问题是,一旦设置,当网站投入生产时就更难进行更改 (komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil)。但是,我觉得将它们存储在我的应用程序中(正如@Martin Bean 指出的那样)并将它们链接到语言文件是一种更简洁的方式。我在数据库中的状态有一个 id、slug 和描述。但是,我只接受一种语言的描述。
  • 那么您当前的方法是理想的,没有理由只能使用一种语言。您可以有一个语言和描述表,而不是将描述存储在状态表中。或者,如果您更喜欢文件中的语言,您仍然可以使用该设置进行操作
  • 如果您决定使用此数据库来支持移动应用程序之类的东西会发生什么 - 这就是 API 的原因
【解决方案3】:

在我的应用程序中,我与@Martin Bean 类似,只是我没有为状态创建单独的类,而是将其存储在现有的类/模型中。

我将调用usersubscriptionentity 一个实体

  • 实体有一个status,存在于它的模型和数据库中的表中。
  • 每个模型都有可能取值为status 的常量,例如ACTIVEINACTIVEPENDING 等,每个模型的值可能有所不同。
  • 创建处理它的方法,例如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;
    }
}

【讨论】:

  • 我喜欢它,解决标志问题的最佳解决方案,谢谢
【解决方案4】:

每种方法都有优点和缺点。了解每一个是很好的。

表格 - 优缺点(AJReading 的方法):

  • 添加和维护表看起来很乏味
  • 仅仅拥有另一个表和模型会使我们的代码感觉更加混乱(并不是说这是一个很好的理由不使用只是说它有点真实)
  • 当我们的应用程序逻辑依赖于数据库中的某些内容时(数据库中的内容感觉应该是可变的,而当我们将应用程序逻辑基于它们时,它们是必需的)时会变得很尴尬
  • 现在我们有了迁移,但在迁移之前,这些曾经是开发人员存在的祸根(它们会使服务器之间的切换变得很麻烦,因为您必须记住添加新状态,否则您的应用程序会崩溃)...您会必须对任何数据库更改执行此操作,但这些仍然是我最经常要做的事
  • 有利于数据完整性

使用常量:优点/缺点(Martin Bean 的方法):

  • 避免上述缺点
  • 这些很容易在您的代码和基础逻辑中引用
  • 您甚至不必创建新模型或表(他在他的示例中这样做了,但您也可以将它们放入事件模型中)
  • 它们非常适合仅在幕后使用的值
  • 它们减少了查询量
  • 他们只是觉得工作量不大。它们似乎更容易重构。
  • 缺点:当您对它们进行标记、检索所有它们、获取描述等时,它们会变得有点尴尬。翻译解决方案是一个很好的解决方案,但如果您不在应用程序中使用翻译,那么这会有点尴尬也一样。
  • 最终,他们破坏了您正在进行的 ORM 流程。如果您的所有其他模型都扩展了 Eloquent,那么这会有点打破常规。
  • 对于如何最好地做到这一点没有真正的一致意见。很多人每次都使用不同的方法。
  • 就像 AJReading 所说,如果您需要单独将数据库用于项目的另一个方面,它将无法工作

我使用常量方法,但有时我认为如果我使用表,我的代码可能会更简洁。这是一个艰难的决定。我希望有一个有据可查的解决方案,用于恒定方法至少创建一致性,但我还没有看到一个。无论哪种方式,我认为没有正确或错误的答案。选择一个并使用它!

【讨论】:

    【解决方案5】:

    对于这种性质的决定,问问自己:

    “是否会有我的应用程序的实例 这些常量是否有不同的值?"

    例如一个测试环境,某种克隆,一些尚未定义但可能的未来版本......

    如果该问题的答案是“是”,那么它可能应该进入应用程序配置。

    如果这些值不太可能(或愚蠢)发生变化,则它们属于并且应该进入模型。

    我建议在这种情况下,没有合理的理由拥有具有不同值的应用程序版本,因此我将其放入模型中。

    【讨论】:

    • 好吧。作为状态,它们应该始终是常量,并且永远不会更改为其他内容。唯一可能改变的是添加了一些状态。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多