Data object title as page url

<%- if @topic_view.topic.tags.present? %>
<%= t 'js.tagging.tags' %>: <%- @topic_view.topic.tags.each do |t| %> <%= t %> <%- end %>
<% end %>

I have create some events as Dataobjects and want to make the urls same as titles. The titles are all unique and have no chance of duplication. So I followed some previous posts in this forum and have the URLSegment and link working with show going to the pages. etc. localhost:8888/events/show/sand-memoirs-blah-blah. My question is the show(HTTPRequest $request ) function how do I create it to show the page as above url.

class Event extends DataObject
{


 public function Link() { return EventPage::get()->first()->Link().'show/'.$this->URLSegment = $this->generateURLSegment($this->Title); }
   
    public function LinkingMode()
    {
        return Controller::curr()->getRequest()->param('ID') == $this->ID ? 'current' : 'link';
    }

public function generateURLSegment($title) {
		$filter = URLSegmentFilter::create();
		$t = $filter->filter($title);
		
		// Fallback to generic page name if path is empty (= no valid, convertable characters)
		if(!$t || $t == '-' || $t == '-1') $t = "page-$this->ID";
		
		// Hook for extensions
		$this->extend('updateURLSegment', $t, $title);
		
		return $t;
	}

And event page controller

class EventPageController extends PageController
{
    private static $allowed_actions = [
        'show'
    ];

    public function show(HTTPRequest $request)
    {
        $event = Event::get()->byID($request->param('ID'));

        if(!$event) {
            return $this->httpError(404,'That event could not be found');
        }

        return [
            'Event' => $event,
            'Title' => $event->Title,
        ];
    }

}

You need to map the URLSegment as a parameter to the ‘show’ action.

	private static $allowed_actions = array('show');
	private static $url_handlers = array(
		'$ID!' => 'show'
	);

You can get the parameter in the action by doing this type of thing:

$params = $this->getURLParams();
$urlseg = Convert::raw2sql($params['ID']);

Okay here is the code I am working with at the moment everything seems to go through to the show page with the new slug but doesn’t show the event details in the EventPage_show.ss. Need a little fresh guidance me thinks. Getting a little brain ache.

   use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Convert;

class EventPageController extends PageController
{
	private static $current_event_id;
	
    private static $allowed_actions = [
        'show'
    ];

	private static $url_handlers = [
	
	];

    public function product(SS_HTTPRequest $request) {
		$event = Event::get_by_url_segment(Convert::raw2sql($request->param('ID')));
		if (!$event) {
			return ErrorPage::responseFor(404);
		}
		static::$current_event_id = $event->ID;
		
		return [
			'Event' => $event,
            'Title' => $event->Title, 
            ];
	}

EventPage php

namespace {

use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;

class EventPage extends Page
{
    private static $has_many = [
        'Events' => Event::class,
    ];

    private static $owns = [
        'Events',
    ];

    public function getCMSFields()
    {
        $fields = parent::getCMSFields();
        $fields->addFieldToTab('Root.Events', GridField::create(
            'Events',
            'Events on this page',
            $this->Events(),
            GridFieldConfig_RecordEditor::create()
        ));

        return $fields;
    }
}
}

Event object

namespace {
use SilverStripe\Forms\TimeField;
use SilverStripe\Forms\DateField;
use SilverStripe\ORM\DataObject;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\CurrencyField;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
use SilverStripe\ORM\ArrayLib;
use SilverStripe\Assets\Image;
use SilverStripe\Forms\TabSet;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\Parsers\URLSegmentFilter;

class Event extends DataObject
{
    private static $has_one = [
        'PrimaryPhoto' => Image::class,
        'SponsorLogo' => Image::class,
        'VideoHolding' => Image::class,
        'EventPage' => EventPage::class,
    ];
        private static $table_name = 'Event';

     public function getCMSfields()
    {
/* Lots of fields etc....*/

    return $fields;
    }
 public function Link() { return EventPage::get()->first()->Link().'show/'.$this->URLSegment = $this->generateURLSegment($this->Title); }
        
       public static function get_by_url_segment($str, $excludeID = null) {
    		if (!isset(static::$_cached_get_by_url[$str])) {
    			$list = static::get()->filter('URLSegment', $str);
    			if ($excludeID) {
    				$list = $list->exclude('ID', $excludeID);
    			}
    			$obj = $list->First();
    			static::$_cached_get_by_url[$str] = ($obj && $obj->exists()) ? $obj : false;
    		}
    		return static::$_cached_get_by_url[$str];
    	}

    public function generateURLSegment($title) {
    		$filter = URLSegmentFilter::create();
    		$t = $filter->filter($title);
    		
    		// Fallback to generic page name if path is empty (= no valid, convertable characters)
    		if(!$t || $t == '-' || $t == '-1') $t = "page-$this->ID";
    		
    		// Hook for extensions
    		$this->extend('updateURLSegment', $t, $title);
    		
    		return $t;
    	}
        
        public function onBeforeWrite(){
    		if($this->owner->Title){			
    			$this->owner->URLSegment = $this->generateURLSegment($this->owner->Title);				
    		}
    		parent::onBeforeWrite();
    	}
    	
    	public function updateCMSFields(FieldList $fields) {
    		$fields->replaceField("URLSegment", $fields->dataFieldByName("URLSegment")->performReadonlyTransformation());
    	}

EventPage_show template

<% with $Event %>
<div class="content-container unit size3of4 lastUnit">
	<article>
	debug - show page
		<h1>$Title</h1>
		<h3>$BookAuthor</h3>
		<div class="content">$Description</div>
	</article>
</div>
<% end_with %>

I assume you’re routing ‘show’ action to the product function in the YML routes file or something?
Can you var_dump($event)?
If so, you’ll need to do something like this.

	return $this->renderWith(
		'Namespace\EventsPage_show',
		array(
			'Event'=> $event,
			'Title'        => $event->Title,

		)
	);

Okay sorted this having looked I had not added routing show for my function and my static::$_cached_get_by_url not declared.

class EventPageController extends PageController
{
	private static $current_event_id;
	
    private static $allowed_actions = [
        'show'
    ];

    public function show(HTTPRequest $request) {
		$event = Event::get_by_url_segment(Convert::raw2sql($request->param('ID')));
		if (!$event) {
			return ErrorPage::responseFor(404);
		}
		static::$current_event_id = $event->ID;
		return 
			['Event' => $event,
         	'Title' => $event->Title,];
	}	
}

class Event extends DataObject
{
/* other code as previous post */

protected static $_cached_get_by_url = [ ];
    
   public static function get_by_url_segment($str, $excludeID = null) {
		if (!isset(static::$_cached_get_by_url[$str])) {
			$list = static::get()->filter('URLSegment', $str);
			if ($excludeID) {
				$list = $list->exclude('ID', $excludeID);
			}
			$obj = $list->First();
			static::$_cached_get_by_url[$str] = ($obj && $obj->exists()) ? $obj : false;
		}
		return static::$_cached_get_by_url[$str];
	}