Bonjour,

Je rencontre actuellement plusieurs problemes avec la creation de liaisons.
J'ai une table Article à qui on peut associer un seul et unique Questionnaire.
Ce Questionnaire est associé à une ou plusieurs Questions.
Chaque Question est associé à une Questionvaleur.

Article (1,1) => (0,n) Questionnaire (1,n) => (1,1) Questions (1,1) => (1,1) Questionvaleur

Je rencontre principalement deux soucis.

Récurération de la requette

J'avais essayé de faire mes liaisons dans mes models mais je n'arrivais pas à enchainer les method :

$article->questionnaire->question-questionvaleur;

De Article à Questionnaire la liaison etait parfaite, le Questionnaire etait bien retourné dans la requette.
Mais la liaison de Questionnaire à Question ne marche pas, les deux table ne se relient pas à la clef etrangere.

Pour palier à ça j'ai fait ma requete dans le controller comme ceci :

$article = $this->article->join('questionnaire', 'questionnaire.id', '=', 'posts.questionnaire_id')->where('posts.slug', $slug)->firstorfail();
$questions = $this->question->where('questionnaire_id', $article->questionnaire_id)->get();

foreach ($questions as $key => $question){
       $questionValue = $this->questionValue->where('question_id', $question->id)->get();
       $questions[$key]->values = $questionValue;
}

Récuperation des données dans le formulaire d'édition

Actuellement je n'ai aucun soucis pour remplir les champs Article et Questionnaire.
Par contre en se qui concerne les question à associer à chaque Questionnaire ainsi que les Valeur de chaque question c'est plus compliqué.

Avez vous une solution pour remplir tout les champs du form bien que les valeurs viennes de tables differentes.
J'utilise un seul et unique Form pour l'édition et la Création.

Merci pour votre aide.

3 réponses


Azorgh
Réponse acceptée

Salut !

Alors tu as deux solutions pour gérer tes relations. Comme tu l'a fait, avec des join a la main, ou avec les relations que Eloquent te fournit.
L'avantage des relations directement dans les Model, ca permet d'intégrer ces relations dans les requêtes sans te soucier des clés étrangères et autre contraintes.

Je serais partis sur quelque chose dans ce style là :

class Article extends Model{
    public function questionnaire{
        return $this->hasOne(Questionnaire::class);
    }
}

class Questionnaire extends Model{
    public function article(){
        return $this->belongsTo(Article::class);
    }

    public function questions(){
        return $this->hasMany(Question::class);
    }
}

class Question extends Model{
    public function questionnaire(){
        return $this->belongsTo(Questionnaire::class);
    }

    public function valeur(){
        return $this->hasOne(QuestionValeur::class);
    }
}

class QuestionValeur extends Model{
    public function question(){
        return $this->belongsTo(Question::class);
    }
}

Une fois tes relations définis (je me suis peut être trompé mais tu vois l'idée, plus d'info ici : https://laravel.com/docs/master/eloquent-relationships) tu peux faire une requête comme ça :

    $article = Article::whereSlug($slug)->with(['questionnaire.questions.valeur'])->first();

Ainsi, $article contiendra une propriété 'relations', nommé 'questionnaire', qui sera un objet de classe Questionnaire, et ainsi de suite donc :

$article->name; //= Name de l'article
$article->questionnaire; // = Objet Questionnaire
$article->questionnaire->name; // = Name du questionnaire associé à l'article

foreach($article->questionnaire->questions as $question){
    $question->name; // = Nom de la question
    $question->valeur; // = Objet QuestionValeur
    $question->valeur->value; // = Value de l'objet QuestionValeur
}

J'espère avoir pu t'aider, hésites pas si tu as des questions ou si je suis complètement à côté de la plaque.

Pyxel
Auteur

Merci Azorgh pour ta réponse compléte !
Je vais essayer d'appliquer ça au projet.

J'ai juste une petite question, dans les model, comment eloquent va savoir quels champs sont lié entre eux pour faire les liaison ? :/

        Schema::create('posts', function(Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
            $table->string('image', 255);
            $table->string('title', 255);
            $table->string('slug', 255)->unique();
            $table->text('summary');
            $table->text('content');
            $table->bigInteger('questionnaire_id');
        });

        Schema::create('questionnaires', function(Blueprint $table) {
            $table->increments('id');
            $table->string('titre', 255);
            $table->string('logo', 255);
        });

        Schema::create('questions', function(Blueprint $table) {
            $table->increments('id');
            $table->integer('questionnaire_id')->unsigned()->index();
            $table->string('name', 255);
            $table->string('icon', 255);
        });

        Schema::create('questions_values', function(Blueprint $table) {
            $table->increments('id');
            $table->integer('question_id')->unsigned()->index();
            $table->string('value', 255);
        });

Je ferais un retour du resultat !

Merci encore.

Alors par défaut, Eloquent prend model_id.
Donc si tu as une méthode :

public function questionnaire(){
    return $this->belongsTo(Questionnaire::class);
    //Il va chercher questionnaire_id dans la table.
    //regarde dans la doc, tu peux préciser manuellement quelle colonne prendre si besoin en second paramètre (pour un BelongsTo)
    //Pour un HasMany, il s'agit du second et tu 3eme paramètre, je te laisse voir ça sur la doc.
}