Bonjour,

J'aimerais ramener tous les jeux avec leur console respective
Voici la requête sql que j'ai trouvée et qui fonctionne très bien dans ma base de données:

SELECT games.name, consoles.name
FROM games
LEFT JOIN consoles
ON games.console_id = consoles.id

Voici ce que je fais avec Laravel dans mon Controller:

$games = DB::table('games')
    ->leftjoin('consoles', 'consoles.id', '=', 'games.console_id')
    ->select('games.name', 'consoles.name')
    ->get();

Dans mon Conroller quand je tente:

$games = Game::all();
dd($games->name);

j'ai l'erreur suivante:

Exception thrown with message "Property [name] does not exist on this collection instance."

La relation ne fonctionne donc pas, du coup j'utilise pas les relations, mais une simple requête sql, car je ne trouve pas la bonne approche(voir plus haut) :( j'ai pourtant fait dans mes modèles les relations suivantes:

Game:
class Game extends Model
{
    public function games()
    {
       return $this->belongsToMany(Game::class);
    }
}

Console:
class Console extends Model
{
    public function consoles()
    {
        return $this->hasMany(Console::class);
    }
}

Mais je n'obtiens pas ce que je souhaite:

Avec un DD(); voici ce que j'obtiens:

Collection {#517 ▼
  #items: array:47 [▼
    0 => {#469 ▼
      +"name": "3DS"
    }
    1 => {#470 ▼
      +"name": "3DS"
    }
    2 => {#471 ▼
      +"name": "DS"
    }

donc juste le nom de chaque console, mais sans leur jeu associé.

Merci pour votre aide, j'espère avoir été clair, j'ai la possibilité de rajouter du code pour mieux me faire comprendre, mais il me semble que tout y est ;)

28 réponses


adrienpsn
Réponse acceptée

Le problème vient de la relation ! Une relation hasMany c'est d'un côté hasMany() et de l'autre belongsTo()

Voir ici pour plus d'informations : https://goo.gl/8G9BPx

StanislasP
Réponse acceptée

Ok. Comme la indiquer@adrienpsn tu te trompe dans les relations ainsique l'optimisationde ta bdd.

Modifie ta migration comme cela, cela vas permettre de créer des relation directement dans ta bdd et ainsi l'optimiser

class CreateGamesTable extends Migration
{
    public function up()
    {
        Schema::create('games', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('console_id')->unsigned();
            $table->string('name');
            $table->timestamps();

            $table->foreign('console_id')
                ->references('id')->on('consoles')
                ->onDelete('cascade');
        });
    }
}

Ensuite, modifie t'est models ainsi :

class Console extends Model
{
    public function games()
    {
       return $this->hasMany(Game::class);
    }
}

class Game extends Model
{
    public function console()
    {
        return $this->belongsTo(Console::class);
    }
}

Cela devrait fonctionner bien mieux

Hello,
comme tu fais un Game::all(); pour pouvoir récupèré le name il te faut un foreach

Pikmin
Auteur

Bien sûr, je n'ai juste pas tout détaillé voyons...
Le souci ne provient absolument pas de ça, j'ai peut-être trop détaillé. Je ne savais pas comment faire ;)
Lis bien tout mon post ….
Et sache qu'un foreach manquant ne générerais pas d'erreur... De plus pour l'affichage j'utilise "DD();" donc...
J'aurais juste un tableau rempli de champs inutile.

Mon souci, est bien les relations, pour pouvoir récupéré ce que j'ai expliqué plus haut ! à savoir le nom des jeux avec leur console associé ;)

Pourquoi ne pas faire un Game::with('console')->get(); ?

Pikmin
Auteur

je viens de tester ta proposition et j'obtiens une belle erreur :
"Call to undefined relationship [console] on model [App\Game]."

Donc j'insiste.... Mais c'est un souci de relation...
j'aimerais comprendre comment faire une belle requête fonctionnelle.

Ah oui j'ais oublié ils faudrait que la relation console soit existante sinon rien ne fonctionnera

Pikmin
Auteur

elles y sont !

dans le with tu a oublié un "s" comme ta relation a un "s" a console

Pikmin
Auteur

non tkt je l'ai bien mit dans mon code ;) et ça change rien, t'en que j'aurais pas une relation correcte rien ne fonctionnera(prends le temps de lire mon post , tout y est en détail, merci) .... bref, je vais attendre d'autre propositions, et continuer de mon coté.
merci pour ton aide,

J'ai tout lu et c'est comme ça que je procède et cela fonctonne bien pour lié mes catégories à mes articles
Exemple moi je procède comme ça dans mon controller

Pikmin
Auteur

tu as quoi dans tes modèles/controllers du coup ? car si ça fonctionne chez toi, ça devrais chez moi ! sinon c'est qu'on à pas du tout les mêmes choses logique. de plus il me semble que je devrais pouvoir faire un truc du genre :

$games->consoles->name // consoles étant une méthode dans le controller.. Console ;)

dans mon controller je fais ça

$cat = Category::where('name', $category_name)->first();
$blog = Blog::with('category', 'user', 'comments')->where('category_id', $cat->id)->paginate(5);
 return view('blog.index', ['blog' => $blog]);

ensuite dans mon model Blog

public function category()
{
    return $this->belongsTo(Category::class);
}
Pikmin
Auteur

je suis avec laravel 5.6 et toi ?
j'avais oublié ce détail !

la dernière version de Laravel

Pikmin
Auteur

De toute façon peut importer la version... ce que tu fais, c'est des clauses "WHERE" du coup rien avoir avec ce que je cherche.
Et visiblement tu n'utiliserais aucune relations, puisque tu fais des requête custom(WHERE). si tu commentes dans tes modèles tes relations, je suis sur que rien ne changerais :) Mais je peut me trompé !

Je veux faire une jointure entrent 2 tables, sans clause particulière (ce référé à ma requête SQL fonctionnel).

Je fais un nouveau project je test et je revien te dire si cela à fonctionné

Pikmin
Auteur

si tu as le temps et le courage ! sinon ne t'emmerde pas pour moi ! bien sur c'est très sympa de ta part ! ! !
je continue de mon coté... meric à toi !
le but est de n'avoir aucune table pivot, et surtout aucune utilisation de l'objet DB, juste via Eloquent t les relationship...
Les vrais relations doivent donnée quelque chose comme ça :
games->consoles->name (avec le code approprié bien sur ;) )

Bonjour.

t'en que j'aurais pas une relation correcte rien ne fonctionnera

J'utilise rarement Laravel, mais je dirais que ton problème de relations est dû à une inversion entre les modèles, tu devrais donc plutôt avoir quelque chose comme :

class Game extends Model
{
    public function console()
    {
        return $this->hasMany(Console::class);
    }
}
class Console extends Model
{
    public function games()
    {
       return $this->belongsToMany(Game::class);
    }
}

j'ai largement le temps mon projet est dèjà terminée

Pikmin
Auteur

@Lartak
si j'inverse comme tu me le propose, laravel me génère une requête SQL "consoles.game_id", or ce champ n'existe pas (games.consoles_id) dans ma base, ce référé à mon post ;)
J'imagine donc que mes méthodes sont dans le bon sens ...

si j'inverse comme tu me le propose, laravel me génère une requête SQL "consoles.game_id", or ce champ n'existe pas (games.consoles_id) dans ma base

Dans ce cas là, c'est que tu t'es trompé dans le type de relation, ce serait donc :

class Game extends Model
{
    public function console()
    {
        return $this->belongsToMany(Console::class);
    }
}
class Console extends Model
{
    public function games()
    {
       return $this->hasMany(Game::class);
    }
}
Pikmin
Auteur

je vous met mes migrations dé fois que j'ai également merder:

class CreateGamesTable extends Migration
{
    public function up()
    {
        Schema::create('games', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->int('console_id');
            $table->timestamps();
        });
    }

class CreateConsolesTable extends Migration
{
    public function up()
    {
        Schema::create('consoles', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });
    }
Pikmin
Auteur

bon je n'y arrive vraiment pas :(
je ne sais pas comment get mes jeux avec leur relations

j'ai refais mes relation sur les conseils de Lartak:

class Console extends Model
{
    public function games()
    {
       return $this->hasMany(Game::class);
    }
}

class Game extends Model
{
    public function console()
    {
        return $this->belongsToMany(Console::class);
    }
}

Bonjour,
Simple question pour le moment afin de t'aider au mieux :)

Dans ton prjet, tu a une liste des jeux et une liste des colonnes.

Tu veux qu'un jeux n'est qu'une seul console ou qu'il puisse en avoir plusieurs ?

Exemple :
game.name : Eve-Online,
game.consoles: [
'PC'
]

game.name : Warframe,
game.consoles: [
'PC',
'X-box',
'PS1',
]

Pikmin
Auteur

Bonjour,

Alors je vais résumer :
Voici mes principales tables :
games(id, name, console_id)
consoles(id, name)

La façon dont j'ai construit ma base de données suppose qu'un jeu n'à qu'une seule console, dans le sens ou un jeu à un ID unique.
un games.id n'à qu'un et un seul games.console_id

Je souhaiterais ramener tous mes jeux avec leur console respectivent.

exemple:
Fallout 4 : PS4

Edit:

@adrienpsn
Je sais bien que c'est mon souci ;) mais du coup pourrais tu m'en dire plus ?
Quel relation dois je utilisé ?

Pikmin
Auteur

Bon je m'y suis remit et j'ai réussis grâce à toi adrienpsn pour ton aide !
j'ai relus la doc...
Maintenant j'aurais aimer que cette dernnière soit plus clair sur les relations que l'ont faire et pas faire !

Pikmin
Auteur

@StanislasP

J'avais de bon résultat en ayant changé mes Modèles comme suit :

class Game extends Model
{
    public function console()
    {
        return $this->belongsTo(Console::class);
    }
}

class Console extends Model
{
    public function games()
    {
       return $this->hasMany(Game::class);
    }
}

Ce que je n'avais pas compris, c'est que certaines associations ne fonctionnent pas et génèrent même des erreurs, je ne trouve pas cela encore très clair dans la doc !

Maintenant je viens de modifier ma migration comme tu me l'as conseillé.
J'ai les mêmes résultats, mais j'imagine que sur de plus grosses bases de données l'optimisation doit être visible.

Merci beaucoup à vous 2 !!