I\'m working on a project in Laravel. I have an Account model that can have a parent or can have children, so I have my model set up like so:
public
I think I've come up with a decent solution as well.
class Organization extends Model
{
public function customers()
{
return $this->hasMany(Customer::class, 'orgUid', 'orgUid');
}
public function childOrganizations()
{
return $this->hasMany(Organization::class, 'parentOrgUid', 'orgUid');
}
static function addIdToQuery($query, $org)
{
$query = $query->orWhere('id', $org->id);
foreach ($org->childOrganizations as $org)
{
$query = Organization::addIdToQuery($query, $org);
}
return $query;
}
public function recursiveChildOrganizations()
{
$query = $this->childOrganizations();
$query = Organization::addIdToQuery($query, $this);
return $query;
}
public function recursiveCustomers()
{
$query = $this->customers();
$childOrgUids = $this->recursiveChildOrganizations()->pluck('orgUid');
return $query->orWhereIn('orgUid', $childOrgUids);
}
}
Basically, I'm starting with a query builder relationship and adding orWhere conditions to it. In the case of finding all of the child organizations, I use a recursive function to drill down through the relationships.
Once I have the recursiveChildOrganizations relationship, I've run the only recursive function needed. All of the other relationships (I've shown recursiveCustomers but you could have many) use this.
I avoid instantiating the objects at every possible turn, since the query builder is so much faster than creating models and working with collections.
This is much faster than building a collection and recursively pushing members to it (which was my first solution), and since each method returns a query builder and not a collection, it stacks wonderfully with scopes or any other conditions you want to use.