Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MorphToMany relationships not displaying in front end. #412

Closed
mefenlon opened this issue Jan 24, 2024 · 4 comments
Closed

MorphToMany relationships not displaying in front end. #412

mefenlon opened this issue Jan 24, 2024 · 4 comments

Comments

@mefenlon
Copy link
Contributor

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 }}

Displays fine on backend
Screenshot 2024-01-24 at 2 57 41 PM

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>
Screenshot 2024-01-24 at 3 00 54 PM

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

@mefenlon
Copy link
Contributor Author

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
Screenshot 2024-01-30 at 3 27 50 PM

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'],
        ],
        ],

@mefenlon
Copy link
Contributor Author

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

@duncanmcclean
Copy link
Member

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).

@mefenlon
Copy link
Contributor Author

mefenlon commented Feb 1, 2024

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants