Laravel Recursive Relationships
This is how you can use recursive relations:
public function childrenAccounts()
{
return $this->hasMany('Account', 'act_parent', 'act_id');
}
public function allChildrenAccounts()
{
return $this->childrenAccounts()->with('allChildrenAccounts');
}
Then:
$account = Account::with('allChildrenAccounts')->first();
$account->allChildrenAccounts; // collection of recursively loaded children
// each of them having the same collection of children:
$account->allChildrenAccounts->first()->allChildrenAccounts; // .. and so on
This way you save a lot of queries. This will execute 1 query per each nesting level + 1 additional query.
I can't guarantee it will be efficient for your data, you need to test it definitely.
This is for childless accounts:
public function scopeChildless($q)
{
$q->has('childrenAccounts', '=', 0);
}
then:
$childlessAccounts = Account::childless()->get();
Laravel Eloquent query recursive relationship model with pagination
You could use nested set technique to store categories.
Nested set technique allows to retrieve all descendants or ancestors for a certain node in hierarchical structures in one query.
You could try this package: https://github.com/lazychaser/laravel-nestedset. Imho it's the best implentation of nested set in laravel.
Installation and configuring will cost you 10 min.
After that you could retrieve your products something like this:
public function products($slug)
{
//first query: retrieving current category
$category = CatalogCategory
::where('slug', $slug)
->first();
//second query: retrieving all category descendants and self ids.
$categoryIds = $category
->descendants
->pluck('id')
->push($category->id);
//third query: retrieving all products.
$products = CatalogProduct
::whereIn('parent_id', $categoryIds)
->where('is_active', 1)
->whereDate('active_from', '<=', Carbon::now('Europe/Sofia'))
->orderBy('created_at', 'desc');
->paginate(50);
return view('path_to_view', compact('products', 'category'));
}
Recursive relationship and nested eager loading with constraints
Assuming that HomeCity
is one of the related models for GrandChild
and the relationship is defined as
//GrandChild.php
public function home_city()
{
return $this->hasMany(HomeCity::class);
}
Then the query to return GrandChild
records who live in HomeCity
(id_something
is a column on home_city
table) identified by $id
may written as:
public function read($id)
{
$data = Hierarchy::query()
->whereNull('parent_id')
->with(['children' => function ($query) use($id) {
$query->with(['grandchildren' => function($query) use($id) {
$query->whereHas('home_city', fn($query) => $query->where('id_something', $id);
}]);
}])
->get();
}
laravel recursive relationship with directed acyclic graph
This is how you can use recursive relations:
public function dependsOn()
{
return $this->hasMany('Account', 'task_id','dependent_id');
}
public function dependents()
{
return $this->dependsOn()->with('dependents');
}
Then:
$dependents = Dependents::with('dependents')->first();
$dependents->dependents;
$dependents->dependents->first()->dependents; // .. and so on
Eloquent recursive relation
A collection only solution would be something like this (place the custom macro in a Service Provider of your application):
Collection::macro('whereDeep', function ($column, $operator, $value, $nested) {
return $this->where($column, $operator, $value)->map(function ($x) use ($column, $operator, $value, $nested) {
return $x->put($nested, $x->get($nested)->whereDeep($column, $operator, $value, $nested));
});
});
Then where needed call:
$yourArray->whereDeep('type', '!=', 1, 'children');
On your example, the macro works like this:
- Filter all the elements where:
type != 1
(the outer array will beuntouched as both items hastype => 0
) - For each element of the current array:
- Retrive the
children
property and apply the same filtering to this subarray starting with the first point of this instructions. - Replace the
children
property with the new children property just filtered.
- Retrive the
Anyways, you should try to deep dive into why the relation filtering doesn't work. That solution would be more efficient if optimized correctly.
Related Topics
How to Add an Order by Clause Using Codeigniter's Active Record Methods
Is Making Asynchronous Http Requests Possible with PHP
Close Open HTML Tags in a String
Extending the Controller Class in Codeigniter
Limit Execution Time of an Function or Command PHP
Get a PHP Object Property That Is a Number
Sqlsrv_Num_Rows Not Returning Any Value
PHP Header() Redirect with Post Variables
Phpunit Mock Objects and Static Methods
Getting Time Difference Between Two Times in PHP
Access Get Directly from JavaScript