web-dev-qa-db-fra.com

Comment filtrer un tableau croisé dynamique à l'aide d'Eloquent?

J'utilise un tableau croisé dynamique sur le projet avec lequel je travaille pour obtenir les travaux des utilisateurs.

Par exemple: User::find(1)->works me donne les travaux de l'utilisateur avec l'ID de 1.

Le fait est que je veux filtrer ces résultats avec des données Pivot supplémentaires.

Quelque chose comme:

User::find(1)->works->pivot->where('active',1)->get();

Dans lequel l'actif est la colonne que j'ai définie dans mon tableau croisé dynamique user_works.

Ceci est ma partie connexe de mon modèle User.php:

<?php

class User extends Cartalyst\Sentry\Users\Eloquent\User {

    public function works() {
        return $this->belongsToMany('Work','user_works')->withPivot('active')->withTimestamps();
    }

}

Ceci est ma partie connexe de mon modèle Work.php:

<?php

class Work extends Eloquent {

    public function users() {
        return $this->belongsToMany('User','user_works')->withPivot('active')->withTimestamps();
    }
}

Voici mon schéma de tableau croisé dynamique:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class CreateUserWorksTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('user_works', function(Blueprint $table) {
            $table->increments('id');

            $table->integer('user_id')->unsigned()->default(0);
            $table->integer('work_id')->unsigned()->default(0);

            $table->enum('active',array('0','1'))->default(1);

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

            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('user_works');
    }

}

Existe-t-il un moyen d'obtenir les données sans créer un nouveau modèle pour le tableau croisé dynamique?

Merci d'avance,

Edit: Je peux filtrer de cette façon:

return User::find(1)->works()->where('user_works.active','=','1')->get();

J'ai dû taper le nom de la table brut. Mais existe-t-il une meilleure façon de gagner cela sans l'utiliser?

27
Arda

Laravel 4.1 apporte natif wherePivot et orWherePivotméthodes , ce qui est directement une solution à mon problème.

40
Arda

Chaque fois que vous appelez withPivot('foo'), Laravel vous faites:

SELECT ... `table`.`foo` AS `pivot_foo` FROM `table` ...

Réponse fixe:

MySQL en particulier permet l'utilisation d'alias de colonnes sur HAVING, GROUP BY et ORDER BY clauses, mais pas sur WHERE clauses.

HAVING et WHERE sont utilisés pour filtrer les requêtes, mais ils se comportent légèrement différemment: HAVING est appliqué après GROUP BY et WHERE est avant.

En règle générale, vous ne devez pas utiliser d'alias de colonne (pivot_foo dans ce cas) pour le regroupement, le filtrage ou quelque chose du genre, car il peut ne pas fonctionner avec d'autres bases de données SQL.

Bien que non recommandé, il est possible d'utiliser:

return User::find(1)->works()->having('pivot_active','=','1')->get();
3
vFragosop

J'essaie de configurer toutes les relations dans les deux sens car cela permet d'utiliser des propriétés dynamiques, par exemple $user->works().

class Collection extends Eloquent {
    public function contents()
    {
        return $this->belongsToMany('Content', 'collection_content', 'collection_id', 'content_id')->withPivot('collection_id', 'group_id', 'field_identifier');
    }
}

class Content extends Eloquent {
    public function collections()
    {
        return $this->belongsToMany('Collection', 'collection_content', 'collection_id', 'content_id')->withPivot('collection_id', 'group_id', 'field_identifier');
    }
}

class CollectionContent extends Eloquent {
    public function content()
    {
        return $this->belongsTo('Content');
    }

    public function collection()
    {
        return $this->belongsTo('Collection');
    }
}

Ensuite, interrogez:

$works = User::find(1)->works()->where('active', 1)->get();

La documentation d'Eloquent est horrible en ce qui concerne l'utilisation des tableaux croisés dynamiques. Ceci est un excellent tutoriel: http://www.developed.be/2013/08/30/laravel-4-pivot-table-example-attach-and-detach/

2
omar j