Convert laravel morph collection to model collection? - laravel

I have 3 models:
Post, Like, Trending
The like and trending models are polymorphs, both are:
public function likeable()
{
return $this->morphTo();
}
public function trendingable()
{
return $this->morphTo();
}
When I populate the trendings table based on the likes the only way to access the "posts" from a trending collection is to make a foreach loop like this:
$chart = Trending::all();
foreach($chart as $chartItem)
{
$chartItem->trendingable->title
}
How can I convert the $chart collection into posts collection without the foreach loop? I am using Laravel 5.8

you should always define the opposite of the relation:
public Post extends Model
{
public function trendings()
{
return $this->morphMany('App\Trending', 'trendingable');
}
}
now if you want to get all posts that have trendings with their trendings:
$postWithTrending=Post::with('trendings')->whereHas('trendings')->get();
if you had to get them by Trending model:
$chart = Trending::where('trendingable_model','=',Post::class)->with
('trendingable')->get()->pluck('trendingable');
but that won't get a list of posts model but array represent posts as key value pairs

Related

Laravel Count Multiple Tables In Eloquent

I am trying to count related tables via model but can't successful.
I have a categories, questions and answers table.
I can count questions related to a category but can't count answers from related categories. U can think its a forum system.
Category Model
public function questions(){
return $this->hasMany('App\Question','category_id','id');
}
Question Model
public function answer()
{
return $this->hasMany('App\Answer');
}
public function category()
{
return $this->belongsTo('App\Category','category_id','id');
}
Answer model
public function question()
{
return $this->belongsTo('App\Question','question_id','id');
}
I can count questions for a related category view Category model like below
public function questioncount(){
return $this->questions()->where('status',1)->count();
}
Tried below for counting answers but no luck;
public function answercount()
{
return $this->questions()
->leftJoin('answers','answers.question_id','=','questions.id')
->count();
}
You might try Has Many Through relationship.
So let's define a Has Many Through relationship in Category model:
class Category
{
public function answers()
{
return $this->hasManyThrough(Answer::class, Question::class);
}
}
Then of course you can get the answers count like this:
$question->answers()->count();
If you want to count the number of results from a relationship without actually loading them you may use the withCount method, which will place a {relation}_count column on your resulting models. For example:
$answers = App\Question::withCount('answers')->get();

Laravel | Using Eloquent hasManyThrough

I have a table called invoiceDetails that has item_id as foreign key from another table called items which has category_id as foreign key from table called categories.
I want to do that following using eloquent:
$result = InvoiceDetail::groupBy('item_id')
->selectRaw('sum(qty) as qty, item_id')->with('item', 'category')->get();
but I am getting error:
Call to undefined relationship [category] on model [App\InvoiceDetail].
Here's my relation inside Category model:
public function invoiceDetail() {
return $this->hasManyThrough('App\InvoiceDetail', 'App\Item', 'category_id', 'item_id');
}
Any suggestions?
Not sure you would even need a hasManyThrough relation here, unless you want to fetch all InvoiceDatail objects belonging to all items which in turn belong to the Category. That part is not clear from your question.
But in your example you are fetching items with their category from distinct item_id.
The reason this is not working is because you are trying to fetch the category relation from the InvoiceDetail object, which does not exist.
->with('item', 'category')
You want to load the Category based on the item relation, not based on the InvoiceDetail, try the dot notation (given that you did define the other relations)
->with('item.category')
Relations should be like this:
class InvoiceDetail extends Model
{
public function item()
{
return $this->belongsTo(\App\Item::class);
}
}
class Item extends Model
{
public function invoiceDetails()
{
return $this->hasMany(\App\InvoiceDetail::class);
}
public function category()
{
return $this->belongsTo(\App\Category::class);
}
}
class Category extends Model
{
public function items()
{
return $this->hasMany(\App\Item::class);
}
public function invoiceDetails()
{
return $this->hasManyThrough(\App\InvoiceDetail::class, \App\Item::class, 'category_id', 'item_id');
}
}
You would want to use the hasManyThrough if, for example, you have a Category and you want to load all the InvoiceDetails directly.
dd($category->invoiceDetails);

Laravel query multiple tables using eloquent

hi sorry bit of a newbie here but I am have three tables users, profiles, friends. they all have the user_id fields within them and I want fetch all of the fields in one statement using Eloquent and not DB::statement and doing the table joins.
How can I achieve this?
Try this
use the User class and the with method that laravel has to query model relationships
$user = User::with(['profile', 'friend'])->get();
Ensure your models has the correct relationships as follows:
app/models/User.php
public function friend () {
return $this->hasMany('Friend');
}
public function profile () {
return $this->hasOne('Profile');
}
app/models/Profile.php
public function user() {
return $this->belongsTo('User');
}
app/models/Friend.php
public function user() {
return $this->belongsTo('User');
}
use some thing like this:
You should define relations in your models with hasOne, hasMany.
class Review extends Eloquent {
public function relatedGallery()
{
$this->hasOne('Gallery', 'foreign_id', 'local_id');
}
}
class Gallery extends Eloquent {
public function relatedReviews()
{
$this->hasMany('Review', 'foreign_id', 'local_id');
}
}
$gallery = Gallery::with('relatedReviews')->find($id);
Will bring the object Gallery with
$gallery->id
gallery->name
...
$gallery->relatedReviews // array containing the related Review Objects

Returning counts of a relationship model in Laravel

I have a model for user and annotations along with a pivot table user_like for storing annotations liked by user. The annotation table is also associated with another model (ranges) through hasMany relationship. I am trying to return all annotations along with its user, ranges and total number of likes.
The code below works for user, ranges and even likes. But, I am only interested in returning the count of likes and not the actual values (i.e. list of users liking the annotation). Is there a way to include just the counts for one of the models from the relations?
Eloquent query:
$annotations = Annotation::with('ranges')
->with('likes')
->with('author')
->where('document_id', $docid)->get()->toArray();
The model:
class Annotation extends Eloquent {
public function ranges()
{
return $this->hasMany('Range');
}
public function author()
{
return $this->belongsTo('User', 'user_id');
}
public function likes()
{
return $this->belongsToMany('User', 'annotation_like');
}
public function countOfLikes()
{
return $this->likes()->count();
}
}
If you want to retrieve count for multiple annotations using eager loading then you need the following 'helper' relation setup:
public function countLikesRelation()
{
return $this->belongsTo('User','annonation_like')->selectRaw('annotation_like, count(*) as count')->groupBy('annotation_like');
}
// then you can access it as such:
$annotations= Annotation::with('countLikesRelation')->get();
$annotations->first()->countLikesRelation->count;
// to make it easier, we create an accessor to the count attribute
public function getLikesCountAttribute()
{
return $this->countLikesRelation->count;
}
//And then, simply use
$annotations->first()->sectionsCount;

Many to Many with eager loading in Laravel 4

I have this model:
class Ownership extends Eloquent {
protected $table = 'game_user';
public function games() {
return $this->belongsToMany('Game');
}
public function type() {
return $this->belongsToMany('owntype');
}
}
Models for Game and Owntype are simple ...extends Eloquent. This is how I pull the data:
$games = Ownership::with('games','type')->where('user_id','=','1')->get();
Theoretically, it works. Practically, not, because it returns empty games and owntype collections. Here's what it returns: http://paste.laravel.com/s94
How can I get games and users table contents? I don't want to Game::find in foreach, because it would produce a lot of queries.
You need to pass an array inside with().
I.e.
$games = Ownership::with(array('games','type'))->where('user_id','=','1')->get();

Resources