Laravel Count Multiple Tables In Eloquent - laravel

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();

Related

access relation inside hasMany relation

I have a model request.php has this relation :
public function requestItems(): HasMany
{
return $this->hasMany(RequestItemd::class, 'request_id', 'id');
}
inside this relation there is another relation
public function item()
{
return $this->belongsTo(Item::class, 'item_id', 'id');
}
how to reach to belongsTo relation and retrieve data through the original hasMany relation?
You will need to loop over your items or get the individual item, something like this:
$requestItemsQuery->each(function($reqestItmId) {
$item = $reqestItmId->item;
});
there are a few other ways of doing this though, so if you share how you are planning to use the reference i might be able to give a better answer

Convert laravel morph collection to model collection?

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

Laravel Eloquent 'withCount' function on multiple joined tables

I have multiple hasMany relations where I want the row count only for the last table.
Users can register for workshops at a specific date and time, so the relations look like 'Workshop' -> hasMany 'Date' -> hasMany 'TimeSlot' -> hasMany 'Registration'.
//Workshop Model
public function workshop_dates(){
return $this->hasMany(WorkshopDate::class);
}
//Date Model
public function workshops(){
return $this->belongsTo(Workshop::class);
}
public function workshop_times(){
return $this->hasMany(WorkshopTime::class);
}
//Time Model
public function workshop_dates(){
return $this->belongsTo(WorkshopDate::class);
}
public function registrations(){
return $this->hasMany(Registration::class);
}
//Registration Model
public function workshop_times(){
return $this->belongsTo(WorkshopTime::class, 'workshop_time_id','id');
}
In my controller I fetch all workshops with all related dates and timelots, but I don't want the user to download all the registration data. I only want them to download the number of registrations for each timeslot.
I tried with the 'withCount' function:
return Workshop::with('workshop_dates.workshop_times.registrations')->withCount('registrations')
But this gave me the error 'Call to undefined method App\Workshop::registrations()'
So I created this method in Workshop.php, with the extended version of hasManyThrough:
public function registrations(){
return $this->hasManyDeep(Registration::class, [WorkshopDate::class,WorkshopTime::class]);
}
However, now I get the total number of registrations per workshop in stead of per timeslot.
I'm a laravel beginner and searching for a solution for many hours. All help is appreciated!
You can add the withCount() on relationship with a closure like this:
Workshop::with(['workshop_dates.workshop_times' => function($q) {
$q->withCount('registrations');
}, 'workshop_dates.workshop_times.registrations'])
->get()
Otherwise, something like this approach https://stackoverflow.com/a/41166325/4705339

BelongsToMany with one or vice versa relationship

I'm using Laravel and Eloquent.
I have a courses table and a Pivot table that holds the related courses.
My pivot table named relatedCourses has 2 columns, course1 & course2.
In the above example, Course ID 5 is related with Course ID 7.
$data["course"] = course::where("isActive",1)->with('related')->find(5);
This works and brings ID 7 as related.
If i try
$data["course"] = course::where("isActive",1)->with('related')->find(7) it should bring ID 5 as related, this is what i'm trying to achieve.
My code is like this in the model :
class course extends Model
{
public function category()
{
return $this->hasOne('App\courseCategory',"categoryId");
}
public function related()
{
return $this->belongsToMany('App\Models\course', 'relatedCourses', 'course1', 'course2');
}
}
You can define two relationships for this query.
class course extends Model
{
public function category()
{
return $this->hasOne('App\courseCategory',"categoryId");
}
public function relatedCourses()
{
return $this->belongsToMany('App\Models\Course', 'relatedCourses', 'course1', 'course2');
}
public function originalCourses()
{
return $this->belongsToMany('App\Models\Course', 'relatedCourses', 'course2', 'course1');
}
}
Then you can query your relations,
$data["course"] = course::where("isActive",1)->with('relatedCourses')->find(5);
and
$data["course"] = course::where("isActive",1)->with('originalCourses')->find(7);
To merge both relations you can do like this
$course = course::where("isActive",1)->with('originalCourses', 'relatedCourses')->get();
Hope this will help you.

I can't make some Eloquent relations to work

Let me first explain the relations of my table, and then I will explain what I cannot do.
So, I have an entity called "Company" it has many "Incomes" which has many "IncomeUnitSale" which has one "IncomeUnitSaleUnitPrice"
Company 1->* Income 1->* IncomeUnitSale 1->1 IncomeUnitSaleUnitPrice
Models:
Company Model
public function Income(){
return $this->hasMany('App\Income');
}
Income Model (table has "company_id")
public function Company(){
return $this->belongsTo('App\Company');
}
public function IncomeUnitSale(){
return $this->hasMany('App\IncomeUnitSale');
}
IncomeUnitSale Model (table has "income_id")
public function Income(){
return $this->belongsTo('App\Income');
}
public function IncomeUnitSaleUnitPrice(){
return $this->hasOne('App\IncomeUnitSaleUnitPrice');
}
IncomeUnitSaleUnitPrice (table has "income_unit_sale_id")
public function IncomeUnitSale(){
return $this->belongsTo('App\IncomeUnitSale');
}
What I am trying to do is the following:
$company = Company::where("id","=",1)->first();
$company->Income->IncomeUnitSale->IncomeUnitSaleUnitPrice
But It says its null, it works till $company->Income->IncomeUnitSale but after that doest't show any relation.
Can somebody please tell me what I am doing wrong?
Thank you!
hasMany relationships will always return an Eloquent Collection object. If there are no related records, it will just be an empty Collection. hasOne and belongsTo relationships will always return either the related Model, or null if there is no related model.
Because some of your relationships are hasMany, you have to iterate the returned Collection to be able to go further. So, instead of $company->Income->IncomeUnitSale->IncomeUnitSaleUnitPrice, you have to:
foreach($company->Income as $income) {
foreach($income->IncomeUnitSale as $sale) {
echo $sale->IncomeUnitSaleUnitPrice->price;
}
}

Resources