Je suis nouveau sur Laravel et j'essaie d'obtenir l'une des valeurs d'une collection par un identifiant récupéré d'une autre collection.
Ma fonction renvoie 2 collections:
public function up()
{
Schema::create('blog_posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->longText('content');
$table->mediumText('slug');
$table->bigInteger('author_id')->unsigned();
$table->bigInteger('category_id')->unsigned();
$table->timestamps();
$table->foreign('author_id')->references('id')->on('blog_authors');
$table->foreign('category_id')->references('id')->on('blog_categories');
});
}
Dans une boucle foreach, j'obtiens des valeurs de collections:
@foreach($posts as $post)
@if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $categories->get($post->category_id) }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
@endif
@endforeach
J'obtiens partiellement le résultat comme vous pouvez le voir dans l'image ci-dessous, mais je ne veux obtenir que le nom.
Voici le code que j'essaye de comprendre
{{$ categories-> get ($ post-> category_id)}}
S'il y a une meilleure ou une bonne façon de le faire, faites-le moi savoir.
Migration des articles de blog:
public function index()
{
$category = BlogCategory::all(['id', 'name']);
$post = BlogPost::orderBy('id', 'desc')->take(14)->get();
return view('blog.index', ['posts' => $post], ['categories' => $category]);
}
4 Réponses :
cette ligne $ categories-> get ($ post-> category_id) renvoie pour vous un tableau de category , donc la solution pour vous ici est comme ci-dessous:
{{ $categories->get($post->category_id)['name'] }}
Cela donne une erreur: Essayer d'obtenir la propriété 'nom' d'un non-objet
Tentative d'obtention du nom de la propriété d'un non-objet
@AlanGodoidaSilveira en fait, car la valeur renvoyée par la méthode get est un simple tableau, vérifiez maintenant
qu'entendez-vous par ordre, s'il vous plaît? combien de noms par ligne avez-vous?
Cela pourrait être optimisé, tout d'abord, vous devez établir une relation un à plusieurs des catégories aux articles
d'abord : assurez-vous que vous avez dans les messages les migrations category_id colonne
Deuxième : Ouvrez le modèle de catégorie et écrivez cette méthode, cela vous permettra de récupérer les articles qui appartiennent à la catégorie
public function index()
{
$post = BlogPost::orderBy('id', 'desc')->take(14)
->with('category')->get();
return view('blog.index', ['posts' => $post]);
}
Troisième : ouvrez le modèle de boutique et écrivez cette méthode, cela vous permettra de récupérer la catégorie qui appartient à l'article
@foreach($posts as $post)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->category->title }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
@endforeach
Enfin strong>: vous modifierez votre vue comme celle-ci
public function catgeory(){
return $this->belongsTo(\App\Category::class);
}
et bien sûr, vous n'appelerez plus les catégories dans votre contrôleur
public function posts(){
return $this->hasMany(\App\Post::class);
}
Vous avez oublié de charger des catégories avec BlogPost, votre contrôleur / code de vue enverra 15 requêtes au lieu de seulement deux.
Gentil je l'oublie je vais le réparer maintenant merci de m'avoir remarqué
Appel à une relation non définie [catégories] sur le modèle [App \ BlogPost]
désolé, j'écris des catégories au lieu de la catégorie dans le contrôleur, ce sera comme ceci $ post = BlogPost :: orderBy ('id', 'desc') -> take (14) -> with ('category') -> get ();
Oui, cela a fonctionné. Mais j'ai essayé une autre bonne réponse avant la vôtre.
@AlanGodoidaSilveira merci :) mais je mentionnerais quelque chose la réponse avant de faire (n + 2) requête SQL parce que chaque fois que vous dites $ post-> category-> title cela fait une nouvelle requête mais dans mon cas , il le composera dans la première requête du contrôleur en utilisant la méthode with () cette technique appelée chargement hâtif
Sûr. La réponse acceptée utilise également le chargement hâtif.
Il vaut peut-être mieux utiliser une relation pour conduire cette situation. Vous pouvez charger dans le contrôleur les données de cette manière.
Dans le post modèle:
@foreach($posts as $post)
@if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->categories->name }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
@endif
@endforeach
Peut-être est hasOne -> la relation si vous n'avez pas de table pivot ...
Dans le contrôleur:
public function index()
{
$data['posts'] = BlogPost::orderBy('id', 'desc')->take(14)->with('categories')->get();
return view('blog.index', $data);
}
Dans la vue:
function categories(){
return $this->belongsToMany('App\BlogCategory')->select(array('id', 'name');
}
Avec appartientToMany: Table de base ou vue non trouvée: 1146 La table 'eaglehorn.blog_category_blog_post' n'existe pas (SQL: sélectionnez id , nom , blog_category_blog_post`
Avec hasOne: Colonne introuvable: 1054 Colonne inconnue 'blog_categories.blog_post_id'
Vous devez ajouter une colonne reliant les deux tables. Peut-être que si le champ associé est category_id: return $ this-> hasOne ('App \ BlogCategory', 'category_id') -> select (arra y ('id', 'name');
Informations de charge de relation liées entre les tables. Vérifiez les informations sur: si la relation est un à un: laravel.com / docs / master / eloquent-relations # one-to-one si vous avez des catégories pour chaque message: une à plusieurs laravel.com/docs/master/eloquent-relationships#one-to-many
Vous devez mettre en place les relations entre les modèles BlogPost et BlogCategory , vu que vous avez déjà un champ category_id dans BlogPost modèle, c'est-à-dire:
dans BlogPost Modèle:
@foreach($posts as $post)
@if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->category->name }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
@endif
@endforeach
dans BlogCategory Modèle: p>
public function index()
{
$posts = BlogPost::with('category')->orderBy('id', 'desc')->take(14)->get();
return view('blog.index', compact('posts'));
}
Ensuite, vous pouvez charger avec impatience catégories avec les $ posts dans votre contrôleur avec seulement deux requêtes:
public function posts(){
return $this->hasMany(\App\BlogPost::class);
}
Puis dans votre vue vous pouvez accéder directement à chaque objet $ post-> category car impatient chargé dans le contrôleur:
public function category(){
return $this->belongsTo(\App\BlogCategory::class);
}
"Variable non définie: catégories"
Je n'ai pas de variable $ categories dans mon code que vous auriez dû publier dans la mauvaise réponse, veuillez essayer mon code.
Sûr. Il était nécessaire de redémarrer le serveur. Cela a fonctionné au besoin.
utiliser le chargement hâtif au lieu du chargement paresseux, cela fera (n + 2) opération SQL
Je ne pense pas @Joseph, le code contrôleur / vue que j'ai posté n'exécute que deux requêtes sur le modèle BlogPost et BlogCategory, essayez-le par vous-même.
faites dd () dans votre collection de messages et vérifiez s'il contient un objet de catégorie, vous ne le trouverez pas.
le contrôleur est impatient de charger: BlogPost :: avec ('category') qui sont deux requêtes, veuillez lire ici: laravel.com/docs/5.8/eloquent-relationships#eager-loading