DataObjects linking to Show Page

Silverstripe Version:
4

Question:

I am following the lessons pretty much and i’ve come across a bit that I just can’t fix with regards to linking data objects as pages and using the $Link function to get a relative link, please see the code below for my basic events section

Please see gist above, the code you are viewing does actually work as expected, however if you look at line 49 in event.php you will see that i’ve had to put ‘events/show/…’ rather than just ‘show/…’.

If I just put ‘show/…’ the url for the event is basically ‘http://localhost/show/1’ rather than ‘http://localhost/events/show/1

Not exactly sure where i’ve gone wrong.

Thanks

Kevin

You might be better off just appending the bit of the segment that you want to the related page’s URL:

return $this->EventsPage()->Link().'/show/'.$this->ID;

$this->EventsPage()->Link() returns / so that wouldn’t help.

I think that’s the problem in the first place.

Hi just to clarify this slightly, if I go on to the EventsPage.ss and print $Link then I correctly get ‘/events/’

However in in the Event.php if I print $this->EventsPage()->Link() that is where it returns ‘/’

Does this mean that its Event.php that may have the issue?

That’s a bit curious. Does the page exist in the sitetree, and is it published?

Yes to both, I dunno if I’ve done something wrong.

In your ModelAdmin, are you attaching the events to the pages? If the relation isn’t being added when you are editing / adding events then the link won’t be accessible from the events end.

Looking at the DataObject, your getCMSFields() method just creates a new FieldList, so I’m guessing the related pages aren’t being added. To do this, you’ll want to add some fields to the DataObject to allow you to properly assign the events to pages. (It might be worth temporarily getting rid of your getCMSFields() method altogether to see if SilverStripe automatically scaffolds the full form.

If you’re only ever going to have one events page on the site, you could change the link method to do something like the following (although it does do away with the point of the relation in the first place, and is a bit hacky):

return EventsPage::get()->first()->Link().'/show/'.$this->ID;

The modelAdmin is just to create the admin panel and say which models it is going to manage, it is the actual Event.php entity file that creates the ‘Link’ function which is meant to get the relation to the EventsPage and return that URL, then append ‘show/{id}’ to the end of it.

You are right its as if the relationship between the entity and the events page doesn’t exist so it just returns ‘/’ but I just can’t understand why, the GIST above has all of the code in order to recreate the issue ,and I have seen on a previous forum someone having the exact same issue that they managed to fix after a bit of help but they never actually gave any i information on what the problem was.

This is that one: https://www.silverstripe.org/community/forums/data-model-questions/show/102628

I’m sure i’m just missing something, and yes I probably could do what you have suggested as i’m not expecting more than one event page, but would rather not do it that way.

Thanks

Kevin

The relationship isn’t being added, since there’s no code anywhere to make that happen. Your modeladmin is managing the dataobject, but in your dataobject the getCMSFields() method only actually has fields for the title and description. So, when the object is saved, these are the only fields.

If you look at the database table for the object, you should see a field called EventsPageID… the values are all probably set to 0 or null.

Did you try removing the getCMSFields() method from your dataobject? Quite often SilverStripe will scaffold the form you need.

If that doesn’t work, then you’ll need to add a field to your getCMSFields() method to allow you to specify the page that the event is linked to.

You can do that with something like:

        $fields->addFieldToTab('Root.Main',
            TreeDropdownField::create('EventsPageID',
                _t(__CLASS__ . '.Page', 'Parent Page'),
                EventsPage::class
            )
        );

I haven’t removed the getCMSFields() from my data object yet no, but the reason is that I want a bit more control over what fields get created and have ability to put options on them but i’ll give it a go and see what it does.

Why would an data object have an EventsPageID ? Surely the individual event data objects are there own entity… unrelated to pages.

Then in my events template (I could 2 or 3 pages of events) I would call the function to bring back the right entities, so for example, could have ‘FeaturedEvents’ or ‘PastEvents’ etc all on different pages.

If an entity (data object) record has an EventsPageId wouldn’t that make this fail?

The relationship I have so far is just EventsPage has_many Events … Although I do think I may have a has_one in the data object back to EventsPage, but I only added that so I had access to $this->EventsPage().

Do I even need a link back from Events back to EventsPage? What if I had a PastEventsPage.php page and I wanted to reuse the same data objects?

I realise that this is going off topic a little, but if I understand that it might help me understand why I need to add EventsPageID to a data object.

Thanks

Kevin

Makes sense! :slight_smile: However if I remove this has_one link… i’m assuming I can still call the Events from the EventPage in order to query and create functions, but how would I handle the show link for the individual events? Any examples on this?

Kevin

Because you told it to :wink: By adding a has_one relation from an event to a page, the system needs to know the ID of that page. This is stored in the EventsPageID field.

If you want an event object to be linked to multiple pages, then you’d want a different sort of relationship (ie. a many_many or similar)

It sounds like you may not actually need the events to be linked to pages. If they are to stand on their own, and be used in multiple places, then you might need to rethink the logic slightly, and maybe look at some custom routing for the event ‘view’ page, so there is a consistent URL for each event regardless of where it appears within the site.