Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel - Where to store statuses (flags)? Model, Class or config folder?

I need to extensively use statuses in mt project. I need them for my users (active, suspended, etc), an entity (active, pending_activation, inactive) and for my subscriptions(active, on_grace_period, not_subscribed, never_subscribed).

So far I thought that the best way is to store them in the DB but i have a feeling it's much easier to have them in the other 3 options.

I also thought that i can store them in my Eloquent Model as constants. For example my subscription model would look like this:

// SubscriptionModel
const SUBSCRIBED_ACTIVE = 1;
const SUBSCRIBED_ON_GRACE_PERIOD = 2;
const NOT_SUBSCRIBED = 3;
const NEVER_SUBSCRIBED = 4;

and retrieving them, for example in a blade view:

// 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

How about doing the same but using the config folder and adding a file called status.php. Accessing it in the view would be like:

@if($user->subscription->status == Config::get('status.subscription.SUBSCRIBED_ACTIVE'))
<div>You are subscribed. Thank you</div>
@elseif(...)
// etc

Is there a better way?

Also, how about the other part of the equation, meaning the status stored in the DB. Should I only have a status column for the subscription table and store what the app dictates or even bettter create a separate table subscription_statuses and have a foreign_key subscription_status_id in the subscriptions table?

like image 943
Cristian Avatar asked Oct 03 '15 01:10

Cristian


3 Answers

I tend to create a specific model for statuses, that acts as an enum. So if I have an Event model, I may have a corresponding EventStatus model that looks like this:

class EventStatus
{
    public const CANCELLED = 'EventCancelled';
    public const POSTPONED = 'EventPostponed';
    public const RESCHEDULED = 'EventRescheduled';
    public const SCHEDULED = 'EventScheduled';
}

I can then do checks like this:

$event->status === EventStatus::CANCELLED;

And I’ll usually add convenience methods to my models too:

class Event extends Model
{
    public function isCancelled(): bool
    {
        return $this->status === EventStatus::CANCELLED;
    }
}

For the “human-friendly” strings, I’ll then have a language file that has the text strings:

<?php // resources/lang/en/event_status.php

return [
    EventStatus::CANCELLED => 'Cancelled',
    EventStatus::POSTPONED => 'Postponed',
    EventStatus::RESCHEDULED => 'Rescheduled',
    EventStatus::SCHEDULED => 'Scheduled',
];
like image 168
Martin Bean Avatar answered Nov 09 '22 17:11

Martin Bean


In my applications I do similar to @Martin Bean except I don't create separate classes for status, I store that inside the existent class/Model.

I'm going to call user, subscription and entity a entity.

  • Entity have a status that exists in it's Model and table in the database.
  • Each Model have constants of possible values of status like ACTIVE, INACTIVE, PENDING, etc, and those may vary for each Model.
  • Create methods for dealing with it like getStatusLabel(), listStatus(), isActive(), isX(), etc.
  • Those isActive/X() are only created if really necessary, maybe a Model have 4 status but you only do comparisons against one specific, so I'd create only one isX() for that status.

Example

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;
    }
}
like image 13
Edson Horacio Junior Avatar answered Nov 09 '22 15:11

Edson Horacio Junior


I do not agree with the other answers. Your status information should be stored in the database. A well designed database should be clear and usable without the application. What happens if you decide to use this database to power something like a mobile application as well? You will be taking some of the information away from the database and storing it only in Laravel, meaning you would have to duplicate that list of statuses in your mobile application too, and maintain it across the two.

This kind of information should be stored in the database.

Option 1

If your users can only ever have one status, then you should use an enum field with the values subscribed, subscribed-grace, not-subscribed, never-subscribed

This is just as simple in your views:

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

Option 2

If however, you might have multiple statuses, then you should almost certainly have a separate field for each status, and use a TINYINT to store a 1 or 0.

Separate status table?

I cannot see a good reason to use a separate status table unless you anticipate you might add many more statuses, and even if you are adding more, you can just add new values to the enum or add a new field depending on which option would suit.

A status table would be ideal if you plan to use the statuses for many other tables in the database besides users.

The only other reason for a seperate status table would be if you decided to change the meaning of a particular status. This would mean you could rename the status in the status table, but the users would still be linked to it via it's primary key. Changing the meaning of a status with the previous two methods would involve changes to the structure.

It really comes down to how you anticipate you will use them, but there is no reason not to keep them in the database.

like image 12
AJReading Avatar answered Nov 09 '22 16:11

AJReading