How to eager load all parents relations count in Laravel? - php

I'm using Laravel 9. to clarify my question firstly I explain the models and the relations between them:
1- Form model has a one to many relationship with Submission model. (each form could have many submissions).
2- Form model has a one to one relationship with itself. (each form could have a parent and a child).
class Form extends Model
{
public function Submissions()
{
return $this->hasMany(Submission::class);
}
public function parent()
{
return $this->belongsTo(Form::class, 'form_id');
}
public function child()
{
return $this->hasOne(Form::class, 'form_id');
}
}
Now I want to return the form with eager load the count of it's submissions plus it's nested parents submissions.
For instance:
form with id:3 with 4 submissions is a child of form with id:2.
Also, the form with id:2 has 3 submissions and is a child of form with id:1.
And finally, the form with id:1 has 5 submissions.
now I want to return the form with id:3 with count submissions + all nested parents' submissions. something like this:
id => 3,
title => form 3,
submissions_count => 12 //count submissions + parents submissions
Note the number of parents is dynamic and the parents are nested. maybe a form doesn't have any parents, in another hand, it could have a parent, then it's parent has another parent itself and so on till the last one doesn't have any parent and it's form_id is null.
Also, I want to eager load from last child, Not parent.
If you can answer the question, it's not any difference between Laravel code or SQL code. both ar fine.

Related

Eloquent Relationship without Pivot Model

I have 3 tables:
customer: fields: id, name
item: fields: id, name
customer_items: fields: customer_id, item_id, qty
Customer and Item have their separate Models as we would expect.
Question: How would I relate these two(Customer and Item) without having a pivot model.
I want to directly get customer items using $customer->items instead of doing $customer->customerItem->items which I find unnecessary since I don't want to track customerItems & customer by item.
Also, I cannot directly use customer_items table for Item model as I might need to retrieve all items in its controller.
As pointed out by #kerbholz (but they didn't create an answer so here it is), in your customer model you need the following function:
public function items()
{
return $this->belongsToMany('App\Item');
}
Which assumes your Item model class sits within App. You may also do the reverse in your Item model.
Now you should be able to do $customer->items and get a collection of items.
If you want to include the qty field then you need:
public function items()
{
return $this->belongsToMany('App\Item')->withPivot('qty');
}
Note that you still need the pivot table, you can't escape that, but you can now navigate it in a more elegant manner.
creat customer_items table and include custmer_item_id and user_id . in User model include this function
public function basket() // example
{
return $this->belongsToMany(User::class, 'customer_items', 'user_id', 'custmer_item_id');
}

Automatically remove related models on removing selected model in laravel

I have a Lesson model with below fields :
lesson_id
title
start_date
end_date
And a Content model that have these fields :
content_id
lesson_id
contentable_id
contentable_type
order
A OneToMany relationship is between Lesson and Content.
In addition, I have two another models named Unit with these fields :
unit_id
title
time
And Test by these :
test_id
title
description
Content contentable_type and contentable_id attributes holds unit (or test) data related to a specific Lesson.
For example in contentable_type field of Content can insert only App\Unit or App\Test string and contentable_id holds ID of that Unit or Test.
(Be careful that Content Model is not to create a morph relations between these tables and I created it beacause I want to give Ordering capability to units and test of a Lesson)
Now, Suppose I want to delete a specific Content and related Units (or Tests).
Deleting Content model instance is easy, but to remove related Unit (or Test), I must fetch appropriate model name from contentable_type and it's ID then select and delete it.
For that I wrote this :
public function destroy ($course_id, $lesson_id, $content_id)
{
$content = Content::findOrFail($content_id);
$modelName = $content->contentable_type;
$modelName::find($content->contentable_id)->delete();
$content->delete();
}
Despite working properly ,But I think that is not convenient.
I search for a way that when delete a Content model , this automatically found related model and remove it too.
What is best and Proper solution?
In this case I just do these changes :
public function destroy ($course_id, $lesson_id, $content_id)
{
$content = Content::findOrFail($content_id);
$content->delete();
}
And in the Content Model :
public static function boot()
{
static::deleting(function ($content) {
$modelName = $content->contentable_type;
$modelName::find($content->contentable_id)->delete();
});
}
This works fine.
But do this best and Most correct solution?

Laravel: Delete relationships

I'm using Laravel 4.2. I have 2 models. I want to make a list of items with a button to delete the relationship.
My models:
Word {
public function posts()
{
return $this->belongsToMany('Post');
}
}
Post {
public function words() {
return $this->hasMany('Word');
}
}
My desired list for Word with id=1
post1 x
post2 x
postn x
When I click to any x button I want to delete the relationship (not the word nor post!).
My approach (blade):
#foreach ($word->posts as $post)
{{{ helper_delete_button_with($post->id) }}}
#endforeach
In conclusion, which is the best way to delete the relation?
Making a function to WordController with a route like
/word/{$wordid}/{$postid} (so I have to have a hidden input with
$wordid)?
Making a controller like PageWordController with the destroy function
(so I have to know the id of relationship, and I don't know how to
get it using relationships)?
Any other solution?
Thank you.
well, i think that you have 3 tables, one for posts, one for words and one for the relationship, in this case is better the second option because you only have to have the id of the relationship and destroy directly.

How to return all child departments of child departments of parent department ? Weird I know

I have a big app to build which should have a possibility for Admin to create a department and assign it a supervisor. Now, a department can be a child of another department but it can also be a parent of some other department. So a parent department could have for example 3 direct child departments, and each one of those 3 departments could have 5 child departments of their own etc ( unlimited many_to_many ).
Now a supervisor of the parent department must be able to manage all of his direct departments and all of the departments that are direct or indirect children of his department(s).
I am a "bit" confused on how I could retrieve all of this from my database for a given supervisor. I just need a general idea of how this could be achieved. How can I retrieve all of his departments and all of the child departments directly or indirectly connected with them?
I am using Laravel 5 for this project, just an info. Layed out a department_department pivot table for relations, as well as department_supervisor pivot for relations with departments and their supervisors.
Is the recursive function the way to go about this ? How to do it, since I am trying this and it is not working as it should.
public function index() {
// get his direct departments of which he is a supervisor
$supervisingDepartments = $this->employeeRepo->getAllSupervisingDepartments(Auth::user()->id);
// get all the children departments of each of his direct departments
$childDepartments = $this->getAllChildDepartmentsFor($supervisingDepartments);
dd($childDepartments); // gives me only one item in the array, the LAST child department
return view("super.employees.index");
}
public function getAllChildDepartmentsFor($supervisingDepartments) {
$childDepartments = [];
foreach($supervisingDepartments as $supervisingDepartment) {
if( ! $supervisingDepartment->childDepartments()->count()) {
$childDepartments[$supervisingDepartment->name] = $supervisingDepartment;
} else {
$this->getAllChildDepartmentsFor($supervisingDepartment->childDepartments);
}
}
return $childDepartments;
}

Laravel 4 - Pivot Tables

I understand how relationships in Laravel (Eloquent) work, but let's say I've got a many to many relationship between two models, call them Posts and Tags.
So our relationship is fine, from Posts I can access all the related Tags, and from Tags I can get all related Posts.
But... I have the ID of a row in the pivot table, and want to return both the Post and Tag relating to this row, how would I go about doing this?
EDIT:
Let's introduce a third Model, called Foo. This contains the ID of the row in the pivot table,
is there anyway I can create a relationship from this to the two other models?
A Model for your pivot:
<?php
class PostTagPivot
{
public function Post()
{
return $this->belongsTo('Post');
}
public function Tag()
{
return $this->belongsTo('Tag');
}
}
And retrieve Post and Tag via:
$Post = PostTagPivot::find($fooBarId)->Post;
$Tag = PostTagPivot::find($fooBarId)->Tag;

Categories