web-dev-qa-db-fra.com

Laravel - Où stocker les statuts (drapeaux)? Modèle, classe ou dossier de configuration?

J'ai besoin d'utiliser énormément les statuts dans le projet mt. J'en ai besoin pour ma users (active, suspended, etc.), une entité (active, pending_activation, inactive) et pour mes abonnements (active, on_grace_period, not_subscribed, never_subscribed).

Jusqu'à présent, je pensais que le meilleur moyen était de les stocker dans la base de données, mais j'ai l'impression qu'il est beaucoup plus facile de les avoir dans les 3 autres options.

J'ai également pensé que je pouvais les stocker dans mon modèle Eloquent sous forme de constantes. Par exemple, mon modèle d'abonnement ressemblerait à ceci:

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

et les récupérer, par exemple dans une vue de lame:

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

Pourquoi ne pas en faire autant, mais en utilisant le dossier config et en ajoutant un fichier appelé status.php. Accéder à la vue serait comme:

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

Y a-t-il un meilleur moyen?

Aussi, que diriez-vous de l’autre partie de l’équation, c’est-à-dire le statut stocké dans la variable DB. Devrais-je avoir seulement une colonne status pour la table d'abonnement et stocker ce que l'application dicte ou même mieux créer une table séparée subscription_statuses et avoir un foreign_keysubscription_status_id dans la table subscriptions?

15
Cristian

J'ai tendance à créer un modèle spécifique pour les statuts, qui agit comme une énumération. Donc, si j’ai un modèle Event, il est possible qu’un modèle EventStatus correspondant ressemble à ceci:

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

Je peux alors faire des contrôles comme ceci:

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

Et d’habitude, j’ajouterai également des méthodes pratiques à mes modèles:

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

Pour les chaînes «conviviales pour l’homme», j’aurai alors un fichier de langue contenant les chaînes de texte:

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

return [
    EventStatus::CANCELLED => 'Cancelled',
    EventStatus::POSTPONED => 'Postponed',
    EventStatus::RESCHEDULED => 'Rescheduled',
    EventStatus::SCHEDULED => 'Scheduled',
];
15
Martin Bean

Je ne suis pas d'accord avec les autres réponses. Vos informations de statut doivent être stockées dans la base de données. Une base de données bien conçue doit être claire et utilisable sans l'application. Que se passe-t-il si vous décidez d'utiliser cette base de données pour alimenter également quelque chose comme une application mobile? Vous allez retirer certaines informations de la base de données et les stocker uniquement dans Laravel, ce qui signifie que vous devez également dupliquer cette liste de statuts dans votre application mobile et la conserver dans les deux cas.

Ce type d'information devrait être stocké dans la base de données. 

Option 1

Si vos utilisateurs ne peuvent avoir qu'un seul statut, vous devez utiliser un champ enum avec les valeurs subscribed, subscribed-grace, not-subscribed, never-subscribed.

C’est aussi simple dans vos vues:

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

Option 2

Si, toutefois, vous pouvez avoir plusieurs statuts, alors vous devriez presque certainement avoir un champ séparé pour chaque statut et utiliser un TINYINT pour stocker un 1 ou un 0.

Tableau d'état séparé?

Je ne vois pas de bonne raison d'utiliser une table d'état distincte à moins que vous ne prévoyiez ajouter beaucoup plus d'états. Même si vous en ajoutez d'autres, vous pouvez simplement ajouter de nouvelles valeurs à la variable enum ou ajouter un nouveau champ, selon l'option qui conviendrait. .

Une table de statut serait idéale si vous envisagez d'utiliser les statuts pour de nombreuses autres tables de la base de données autres que les utilisateurs.

Si vous décidiez de modifier la signification d'un statut particulier, la seule autre raison justifiant la création d'une table d'état distincte serait. Cela signifierait que vous pourriez renommer le statut dans la table de statut, mais que les utilisateurs y seraient toujours liés via sa clé primaire. Changer la signification d'un statut avec les deux méthodes précédentes impliquerait des changements dans la structure.

Cela dépend vraiment de la manière dont vous prévoyez de les utiliser, mais il n’ya aucune raison de ne pas les conserver dans la base de données.

6
AJReading

Dans mes applications, je fais similaire à @Martin Bean sauf que je ne crée pas de classes séparées pour status, je les stocke dans la classe/modèle existant.

Je vais appeler user, subscription et entity une entité

  • Entity a une status qui existe dans son modèle et une table dans la base de données.
  • Chaque modèle a des constantes de valeurs possibles de status comme ACTIVE, INACTIVE, PENDING, etc., et celles-ci peuvent varier pour chaque modèle.
  • Créez des méthodes pour le gérer, telles que getStatusLabel(), listStatus(), isActive(), isX(), etc.
  • Ces isActive/X() ne sont créés que si cela est vraiment nécessaire. Par exemple, un modèle a un statut 4, mais vous ne faites que des comparaisons avec un spécifique. Par conséquent, je ne créerais qu'un isX() pour ce statut.

Exemple

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;
    }
}
3
Edson Horacio Junior

Chaque méthode présente des avantages et des inconvénients. C'est bien d'être au courant de chacun.

Tableau - Avantages et inconvénients (méthode d'AJReading):

  • Ajouter et maintenir une table semble ennuyeux
  • Avoir juste une autre table et un autre modèle peut rendre notre code plus encombré (ne pas dire que c'est une bonne raison de ne pas utiliser simplement en disant que c'est un peu vrai)
  • Cela devient gênant lorsque la logique de l'application dépend de quelque chose dans la base de données (les éléments de la base de données ont l'impression qu'ils devraient être variables, lorsque nous basons la logique de l'application sur eux, ils sont nécessaires)
  • Nous avons maintenant des migrations, mais avant elles, elles constituaient le fléau de l’existence des développeurs (ils faisaient de la commutation entre serveurs une tâche pénible car il fallait se souvenir d’ajouter de nouveaux statuts, sans quoi votre application planterait) ... vous auriez dû faire cela avec tout changement de base de données mais ce sont quand même ceux que je devrais faire le plus souvent
  • Bon pour l'intégrité des données

Utilisation de constantes : Avantages/inconvénients (méthode de Martin Bean):

  • Evite les inconvénients ci-dessus
  • Celles-ci sont faciles à référencer dans votre code et sur la logique de base
  • Vous n'avez même pas besoin de créer un nouveau modèle ou une table (il le fait dans son exemple, mais vous pouvez également les insérer dans le modèle Events)
  • Ils sont parfaits pour les valeurs qui ne seront utilisées que dans les coulisses
  • Ils réduisent le nombre de requêtes
  • Ils ne se sentent pas comme autant de travail. Ils semblent plus faciles à refactoriser.
  • Contre: ils deviennent un peu gênants lorsque vous commencez à les étiqueter, à les récupérer tous, à obtenir des descriptions, etc. La solution de traduction est bonne, mais si vous n'utilisez pas de traduction dans votre application, c'est également un peu gênant.
  • En fin de compte, ils interrompent le flux ORM que vous avez. Si tous vos autres modèles étendent Eloquent, cela brise un peu le moule. 
  • Il n'y a pas vraiment d'accord sur la meilleure façon de le faire. Beaucoup de gens utilisent une méthode différente à chaque fois.
  • Comme AJReading l'a dit, si vous devez utiliser la base de données seule pour un autre aspect du projet, cela ne fonctionnera pas.

J'utilise la méthode constante mais parfois je pensais que mon code serait plus propre et plus simple si j'avais utilisé des tableaux. C'est un appel difficile. J'aimerais qu'il y ait une solution bien documentée pour que la méthode constante crée au moins de la cohérence, mais je n'en ai pas encore vu. De toute façon, je ne pense pas qu'il y ait une bonne ou une mauvaise réponse. Choisissez-en un et allez-y!

1
Sabrina Leggett

Pour des décisions de cette nature, demandez-vous ceci: 

"Y aura-t-il un cas dans mon application où il serait logique Que ces constantes aient des valeurs différentes?"

par exemple. un environnement de test, une sorte de clone, des versions non encore définies mais des versions futures possibles ...

Si la réponse à cette question est "oui", alors il devrait probablement aller dans la configuration d'application. 

S'il est peu probable (ou stupide) que les valeurs changent, elles appartiennent et doivent être intégrées au modèle.

Je suggère que dans ce cas, il n’y aurait aucune raison valable d’avoir une version de l’application avec des valeurs différentes, je la mettrais donc dans le modèle.

0
DanSingerman