MorphToMany relationships not displaying in front end.
Closed this issue · 4 comments
Description
In runway v5, I was working with MorphToMany relationships and the front and back ends displayed correctly.
In v6, I am not unable to loop over the relationship on the front end despite the backend displaying correctly.
Error in log:
LOG.debug: Cannot loop over non-loopable variable: {{ titles }}
Display on frontend
<div>
Field name: {{ name }}
</div>
<div>
Computed city_and_state: {{ city_and_state }}
</div>
<div>
Title Relationship
{{ titles }}
{{ sort_title }}
{{ /titles }}
{{# LOG.debug: Cannot loop over non-loopable variable: {{ titles }} { #}}
{{# "line": 9, #}}
{{# "file": "\/var\/www\/html\/resources\/views\/runway\/city\/show.antlers.html" #}}
</div>
Steps to reproduce
runway.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Resources
|--------------------------------------------------------------------------
|
| Configure the resources (models) you'd like to be available in Runway.
|
*/
'resources' => [
\App\Models\Title::class => [
'cp_icon' => 'book-open',
'name' => 'Titles',
'route' => '/journals/{{ abbreviation }}',
'title_field' => 'sort_title',
'template' => 'runway.journal.show',
'relationships' => ['cities'],
],
\App\Models\City::class => [
'cp_icon' => 'flag',
'name' => 'Cities',
'route' => '/cities/{{ slug }}',
'title_field' => 'city_state_and_country',
'template' => 'runway.city.show',
'read_only' => true,
'relationships' => ['titles'],
],
City Model
class City extends Model
{
use HasRunwayResource;
use RunwayRoutes;
public $guarded = [];
protected $appends = ['coordinates', 'city_state_and_country'];
protected $with = ['titles'];
public function titles(): MorphToMany
{
return $this->morphedByMany(Title::class, 'cityable');
}
public function cityStateAndCountry(): Attribute
{
return Attribute::make(
get: fn () => ( is_numeric($this->state_code) ) ? $this->name .', ' . $this->country_code : $this->name .', ' . $this->state_code.', ' . $this->country_code,
)->shouldCache();
}
public function cityAndState(): Attribute
{
return Attribute::make(
get: fn () => ( is_numeric($this->state_code) ) ? $this->name .', ' . $this->country_code : $this->name .', ' . $this->state_code,
)->shouldCache();
}
public function coordinates(): Attribute
{
return Attribute::make(
get: fn () => !empty($this->latitude)&&!empty($this->longitude) ? '['. $this->latitude .',' . $this->longitude.']' : '',
)->shouldCache();
}
public function slug(): Attribute
{
return Attribute::make(
get: fn () => Str::of($this->cityStateAndCountry)->slug('-')
)->shouldCache();
}
}
City blueprint
tabs:
main:
display: Main
sections:
-
fields:
-
handle: city_state_and_country
field:
type: text
display: City
visibility: computed
-
handle: slug
field:
type: text
display: Slug
visibility: computed
listable: false
instructions_position: above
replicator_preview: true
input_type: text
antlers: false
hide_display: false
-
handle: country_id
field:
type: integer
display: CountryId
validate: required
listable: false
-
handle: state_id
field:
type: integer
display: StateId
validate: required
listable: false
-
handle: name
field:
type: text
display: Name
validate: required
-
handle: country_code
field:
type: text
display: CountryCode
validate: required
-
handle: state_code
field:
type: text
display: StateCode
validate: required
-
handle: latitude
field:
type: text
display: Latitude
validate: required
-
handle: longitude
field:
type: text
display: Longitude
validate: required
-
handle: city_and_state
field:
input_type: text
antlers: false
type: text
display: city_and_state
icon: text
listable: hidden
instructions_position: above
visibility: computed
replicator_preview: true
hide_display: false
-
display: Relationships
fields:
-
handle: titles
field:
mode: default
resource: title
create: false
title_format: '{{ title }}'
reorderable: false
type: has_many
display: Titles
icon: has_many
listable: hidden
instructions_position: above
visibility: visible
replicator_preview: true
hide_display: false
sidebar:
display: Sidebar
sections:
- { }
title: City
Title Model
class Title extends Model
{
use HasRunwayResource;
use RunwayRoutes;
public $guarded = ['backend_extra_attributes'];
public $with = ['cities'];
public function cities(): MorphToMany
{
return $this
->morphToMany(City::class, 'cityable');
}
/**
* Get the title attribute.
* Will return the display_title if set. Otherwise, returns sort_title
*/
public function title(): Attribute
{
return Attribute::make(
get: fn () => !empty($this->display_title) ? $this->display_title : $this->sort_title,
)->shouldCache();
}
}
Title blueprint
tabs:
main:
display: Main
sections:
-
fields:
-
handle: sort_title
field:
type: text
display: 'Sort Title'
validate: required
-
handle: display_title
field:
type: text
display: DisplayTitle
listable: hidden
instructions: 'OPTIONAL! Only use if you need the title to display in something other than the sortable title. Example- If Sort Title is Mississippi Rag, The then enter The Mississippi Rag here.'
-
handle: abbreviation
field:
type: text
display: Abbreviation
-
handle: title
field:
input_type: text
antlers: false
type: text
display: Title
icon: text
listable: false
instructions_position: above
visibility: computed
replicator_preview: true
hide_display: false
validate:
- image
-
display: Relationships
fields:
-
handle: cities
field:
mode: default
resource: city
create: false
reorderable: false
type: has_many
display: Cities
icon: has_many
listable: hidden
instructions_position: above
visibility: visible
replicator_preview: true
hide_display: false
sidebar:
fields:
-
handle: created_at
field:
type: date
display: CreatedAt
listable: hidden
-
handle: updated_at
field:
type: date
display: UpdatedAt
listable: hidden
title: Title
Environment
Environment
Application Name: App_name
Laravel Version: 10.42.0
PHP Version: 8.2.14
Composer Version: 2.6.6
Environment: local
Debug Mode: ENABLED
URL: app_name.test
Maintenance Mode: OFF
Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED
Drivers
Broadcasting: log
Cache: statamic
Database: mysql
Logs: stack / single
Mail: smtp
Queue: sync
Session: file
Statamic
Addons: 1
Antlers: runtime
Stache Watcher: Enabled
Static Caching: Disabled
Version: 4.45.0 PRO
Statamic Addons
statamic-rad-pack/runway: 6.0.4
I have done a bit more digging. If I comment out the relationships for the resource in runway.php, I get the following error:
Object of class Illuminate\Database\Eloquent\Relations\MorphToMany could not be converted to string
With the relationships defined the dump is returning Illuminate\Database\Eloquent\Relations\MorphToMany
But I am unable to loop through the resource
I have traced this back to
/statamic-rad-pack/runway/src/Resource.php line 137
public function eloquentRelationships(): Collection
I am not familiar enough with the project to troubleshoot any further, but I will keep digging.
city/show.antlers.html
Resource name field {{ name }} <br>
Resource computed field {{ city_state_and_country }} <br>
Relationship:<br>
{{ titles | dump }}<br>
Nothing here:
{{ titles }}
{{ slug }}
{{ /titles }}
runway.php
'resources' => [
\App\Models\Title::class => [
'cp_icon' => 'book-open',
'name' => 'Journals',
'route' => '/journals/{{ abbreviation }}',
'title_field' => 'sort_title',
'template' => 'runway.journal.show',
'relationships' => ['cities'],
],
\App\Models\City::class => [
'cp_icon' => 'flag',
'name' => 'Cities',
'route' => '/cities/{{ id }}',
'title_field' => 'city_state_and_country',
'read_only' => true,
'template' => 'runway.city.show',
'layout' => 'debug',
// 'relationships' => ['titles'],
],
],
Submitted a PR that resolves the issue when relationships is not defined for the resource in runway.php
If the relationship is defined, I am still getting the error
[13:42:49] LOG.debug: Cannot loop over non-loopable variable: {{ titles }} {
"line": 10,
"file": "\/var\/www\/html\/resources\/views\/runway\/city\/show.antlers.html"
}
The docs say to devine eager loaded relationships with the key 'relationships'
https://runway.duncanmcclean.com/upgrade-guides/v5-x-to-v6-0#content-low-changes-to-overriding-eager-loaded-relationships
If i change the key from 'relationships' back to 'with', the resource works as expected.
'resources' => [
\App\Models\Title::class => [
'cp_icon' => 'book-open',
'name' => 'Titles',
'route' => '/journals/{{ abbreviation }}',
'title_field' => 'sort_title',
'template' => 'runway.journal.show',
'with' => ['cities'],
],
\App\Models\City::class => [
'cp_icon' => 'flag',
'name' => 'Cities',
'route' => '/cities/{{ slug }}',
'title_field' => 'city_state_and_country',
'template' => 'runway.city.show',
'read_only' => true,
'with' => ['titles'],
],
There are still refrences to 'with' in files RunwayTag.php, RunwayTagTest.php and BaseFieldtype.php
Hey 👋
Sorry for not getting back to you regarding this issue. I looked at it briefly last week but kept running into issues getting your example running (not related to your issue) so I moved onto something else and didn't end up looping back to it until now.
Thanks for your PR - I've merged it and it's part of v6.0.5.
Also, on the back of your comment regarding the relationships
setting. It seems like I caused some issues as part of my refactoring in v6. I've changed the name of the setting back to with
like it was in v5 (#418).
Thanks for the note. I understand that the morph relations are lacking support, but I am using them as read only for now. I just noticed a similar error with MorphTo and will be submitting a PR for that shortly.
Great package by the way!