lundi 19 août 2019

How do I eager-load nested relationships and go through the collection in nested foreach loops?

I am trying to eager-load a collection multiple levels deep and then go through that collection and let it forget parts of it.

My problem is that the foreach loops here just do not trigger at all and dd() on certain levels just gives me a relationship instead of collection elements.

I also know that my approach is probably not the best of doing something like this. I would be happy to learn a better way :)

So what I have is data similar to the following:

    MainChannel->GroupChannel->Channel->Activities

    OnlineChannels->SocialMedia->Youtube->Activities
    OnlineChannels->SocialMedia->Facebook->Activities
    OnlineChannels->Webpages->Something.com->Activities
    OfflineChannels->Face-To-Face->Congress->Activities

The Channels are nested in a tree-structure and can go 3 levels deep. They have a lft rgt and depth attribute.

id  |  name  |  lft  |  rgt  |  depth  |  color  |  important_links  | parent_id

So first I try to eager load the whole thing:

    $GroupChannels = Channel::where('depth', 2)->with(
                    'parent', 
                    'children', 
                    'children.activities'
                );

and maybe filter it by

    if(isset($input['filtered_channels'])){
        $Channels = $Channels->whereIn('id', $input['filtered_channels']);
    }
    $Channels = $Channels->get();

and then I want to go through it like this:

    foreach($GroupChannels as $Channel){   
        foreach($Channel->children as $Subchannel){
            foreach ($Subchannel->activities as $Activity){
                $removeActivity = false;
                // do some checks on the activity that will maybe turn the $removeActivity to true
                if($removeActivity){
                    $Subchannel->forget($Activity);
                }         
            }
        //forget Subchannel if not Activities remain
        }
    //forget Channel if not Subchannels remain
    } 

Here is my model:

class Channel extends Model
{
use CrudTrait;
use SoftDeletes;
use \Venturecraft\Revisionable\RevisionableTrait;
/*
|--------------------------------------------------------------------------
| GLOBAL VARIABLES
|--------------------------------------------------------------------------
*/

protected $table = 'channels';
protected $primaryKey = 'id';
protected $fillable = ['name', 'color', 'parent_id', 'lft', 'rgt', 'depth', 'important_links'];
protected $dates = ['created_at', 'updated_at', 'deleted_at'];

/*
|--------------------------------------------------------------------------
| FUNCTIONS
|--------------------------------------------------------------------------
*/
public static function boot()
{
    parent::boot();
}
/*
|--------------------------------------------------------------------------
| RELATIONS
|--------------------------------------------------------------------------
*/
public function activities()
{
    return $this->belongsToMany(Activity::class);
}
public function children()
{
    return $this->hasMany(Channel::class, 'parent_id', 'id');
}
public function parent()
{
    return $this->hasOne(Channel::class, 'id', 'parent_id');
}

/*
|--------------------------------------------------------------------------
| ACCESORS
|--------------------------------------------------------------------------
*/
public function getChildrenAttribute(){
    return $this->children()->orderBy('lft');
}
}

The problem occurs on the second level foreach($Channel->children as $Subchannel){ because this does not trigger.

When I do a dd($Subchannel) here it does not show up and if I do it above that line for dd($Channel->children) I get a relation instead of a collection.

    HasMany {#872 ▼
      #foreignKey: "channels.parent_id"
      #localKey: "id"
      #query: Builder {#831 ▶}
      #parent: Channel {#840 ▶}
      #related: Channel {#832 ▶}
    } 

So I guess the eager-load does not return nested collections or I can not traverse through the tree in that collection like that. I have honestly no idea how to do this the correct way.



from Newest questions tagged laravel-5 - Stack Overflow https://ift.tt/33CGHTo
via IFTTT

Aucun commentaire:

Enregistrer un commentaire