web-dev-qa-db-fra.com

Migration Foreign Key Vs Eloquent Relationships in Laravel

Dans Laravel 5.1 je peux voir que les relations de colonne de table peuvent être configurées de 2 manières:

1) Définition de clés étrangères dans la table de migration.

2) Définition des relations éloquentes dans les modèles.

J'ai lu les documentations et je suis toujours confus sur les points suivants:

  1. Dois-je utiliser les deux ou seulement 1 est nécessaire?

  2. Est-ce mal d'utiliser les deux en même temps? Ou est-ce que cela le rend redondant ou provoque des conflits?

  3. Quel est l'avantage d'utiliser les relations Eloquent sans mentionner la colonne Clés étrangères dans la migration?

  4. Quelle est la différence?

Ce sont les codes que j'ai maintenant. Je ne sais toujours pas si je dois supprimer les clés étrangères que j'ai configurées dans mon fichier de migration.

Migration:

  public function up()
    {   

       Schema::create('apps', function (Blueprint $table) {
          $table->increments('id');
          $table->string('app_name');
          $table->string('app_alias');
          $table->timestamps();
          $table->engine = 'InnoDB';
       });

      // This is the second Migration table
      Schema::create('app_roles', function (Blueprint $table) {
          $table->increments('id');
          $table->integer('app_id')->unsigned()->index();
          $table->integer('user_id')->unsigned()->index();
          $table->integer('role_id')->unsigned()->index();
          $table->engine = 'InnoDB';

          $table->unique(array('app_id', 'user_id'));

          $table->foreign('app_id')
                ->references('id')
                ->on('apps')
                ->onDelete('cascade');

          $table->foreign('user_id')
                ->references('id')
                ->on('users')
                ->onDelete('cascade');

          $table->foreign('role_id')
                ->references('id')
                ->on('roles')
                ->onDelete('cascade');
        });     
    }

Modèle avec relations éloquentes:

// App Model
class App extends Model
{

     public function appRoles() {
         return $this->hasMany('App\Models\AppRole');
     }
}

// AppRole Model
class AppRole extends Model
{
   public function app() {
       return $this->belongsTo('App\Models\App');
   }

   public function user() {
       return $this->belongsTo('App\User');
   }

   public function role() {
       return $this->belongsTo('App\Models\Role');
   }
}

// User Model
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
    .....
    public function appRole() {
         return $this->belongsToMany('App\Models\AppRole');
     }
}

// Role Model
class Role extends EntrustRole
{
     public function appRole() {
         return $this->hasMany('App\Models\AppRole');
     }
}

Quelqu'un peut-il m'aider à comprendre cela s'il vous plaît?

28
Neel

Les deux vont de pair. L'un est incomplet sans l'autre. Si vous voulez que vos relations fonctionnent correctement, vous devez définir ces deux choses.

Si vous venez de définir la clé étrangère dans un fichier de migration, la relation fonctionnerait juste au cas où vous écririez une requête brute. Cela ne fonctionnera pas sur vos modèles car vous n'avez rien écrit sur les relations dans vos modèles.

Ainsi, dès que vous écrivez hasMany dans l'un de vos modèles et la fonction correspondante dans l'autre modèle, ce n'est qu'alors que vos modèles se connaissent les uns les autres, et que vous pouvez alors interroger avec succès les choses via votre modèle ainsi que dans votre base de données.

Notez également que si vous avez correctement défini des relations via hasMany et belongsTo dans vos modèles, mais que vous n'avez pas fourni de clé étrangère dans la table du modèle qui belongsTo autre table, vos relations ne fonctionneront pas.

Bref, les deux sont également obligatoires.

29
Arslan Ali

Eloquent suppose la clé étrangère de la relation en fonction du nom du modèle. Dans ce cas, le modèle App est automatiquement supposé avoir un app_id clé étrangère, donc dans vos migrations vous n'avez pas besoin de spécifier:

$table->foreign('app_id')
->references('id')
->on('apps')
->onDelete('cascade');

Documentation

4
apex39