oliverbj
oliverbj

Reputation: 6052

Access relationship of relationship

I have below three models:

In my Stream model, I have:

public function FieldRoutes()
{
    return $this->hasMany(FieldRoute::class);
}

Then, in my FieldRoute model, I have:

public function fields()
{
    return $this->hasMany(Field::class);
}

I am trying to access the Field model through FieldRoute, like so:

$stream = Stream::find(1);

$routeFields = $stream->FieldRoutes()->fields;

However, above gives me the error:

Undefined property: Illuminate\Database\Eloquent\Relations\HasMany::$fields

Am I even able to get the fields, that belongs to FieldRoute, by only having the Stream object?

Upvotes: 0

Views: 74

Answers (3)

TMH
TMH

Reputation: 6246

You could try eager loading and plucking out the values.

$stream = Stream::with('FieldRoute.fields')->pluck('FieldRoute')->flatten()->pluck('fields')->flatten();

Upvotes: 0

Tim Lewis
Tim Lewis

Reputation: 29258

You're gonna need some nested looping to handle nested relationships. But first, the error you're getting is due to a missing closure; you need to call ->get() after the relationship name:

$routeFields = $stream->FieldRoutes()->get();
// Or, omit the ()
$routeFields = $stream->FieldRoutes;

Next, do some looping to get the fields:

foreach($routeFields AS $routeField){
  $fields = $routeField->fields()->get();
  // Or, again, omit the () (in fact, never use () in a loop)
  $fields = $routeField->fields;
}

Lastly, one more loop to access the properties of each Field:

foreach($fields AS $field){
  // Do whatever you want with $field...
}

Altogether, this would look like:

$stream = Stream::with(["FieldRoutes", "FieldRoutes.fields"])->find(1);

$routeFields = $stream->FieldRoutes;
foreach($routeFields AS $routeField){
  $fields = $routeField->fields;
  foreach($fields AS $field){
    // Do whatever with $field
  }
}
// Simplified
foreach($stream->FieldRoutes AS $routeField){
  foreach($routeField->fields AS $field){
    // Do whatever with $field
  }
}

Also, please fix your function name FieldRoutes, that should be fieldRoutes (function names are camelCase)

Note: I've used ::with() to "Eager load" the relationships so you're not querying them while looping, as that's a huge performance hit.

Upvotes: 1

Try

$stream = Stream::with('FieldRoute.Field')->get();

Upvotes: 0

Related Questions