Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Data Model Questions /

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

Retrieving Data based on URL fragment.


Go to End


9 Posts   4478 Views

Avatar
Crossbound

Community Member, 14 Posts

8 November 2009 at 7:12am

Edited: 08/11/2009 7:16am

Okay the title might be a little confusing, but here is my actual problem. I was able to add a new Data Object to my CMS and can add entries using CMS backend. Now I would like to access a specific entry using something like 'mysite.com/sermons/2009-10-16', while sermons is the page type and I would like to display entry in the database using the date as the filter.
how can I access that date fragment in the URL to then us it in the call to the database. I was looking at http://www.silverstripe.org/customising-the-cms/show/251362 but was not able to figure out how to customize it for my needs. Is it even possible the way I would like to do it? or is there maybe a better way of doing it.

Thanks for your help!

Avatar
bummzack

Community Member, 904 Posts

8 November 2009 at 10:34am

Edited: 08/11/2009 10:35am

Hi. Should be easy to do, but it will be easier if you specify an action to be called on the Controller.
Eg, your URL should be: mysite.com/page/action/parameter
So for your case it could be: mysite.com/sermons/date/2009-10-16

Then you would create a method date on your Sermon_Controller. This will be called, whenever sermons/date is being opened in the browser. There you can get the date parameter via Director::urlParam('ID').

Here's an example code:

public function date(){
	$date = Director::urlParam('ID');
	
	// check if it's a correctly formatted date, otherwise just render the page
	// with the default template.
	if(!preg_match('/\d{2}-\d{2}-\d{4}/', $date)){
		return $this->renderWith(array($this->ClassName, 'Page'));
	}
	
	// get the dataobject that matches $date
	$dataObject = DataObject::get_one('DataObjectClass', "DATE_FORMAT(DateField, '%d-%m-%Y') = '$date'");
	if(!$dataObject){
		// if no dataobject, render with default template.
		return $this->renderWith(array($this->ClassName, 'Page'));
	}
	
	// render the dataObject with a custom template (DataObjectTemplate.ss)
	// can be Layout too!
	return $dataObject->renderWith(array('DataObjectTemplate', 'Page'));
}

Hope that helps. If you don't want to render the DataObject with its own template, you can just store the DataObject as a private member of the Controller class and provide an accessor Method to get it in your template.

Avatar
bummzack

Community Member, 904 Posts

8 November 2009 at 10:35am

Edited: 08/11/2009 10:36am

Ouch. Accidentally double posted.

Avatar
Crossbound

Community Member, 14 Posts

8 November 2009 at 3:53pm

Thanks for pointing me in the right direction. Your method worked, but the problem I was running into was that my Menus and some other content disappeared. I looked around and found this thread http://www.silverstripe.org/template-questions/show/252412
I was not able to figure out how their solution was supposed to work :-)

I was able to circumvent this problem by doing the following. The URL structure I left the same /sermons/date/2009-10-15 but instead of creating a date() method, I created a method called GetSermon()
(I did have to change the preg_match and DATE_FORMAT because in the URL the raw SQL date is used and I could not figure out how to change it to m-d-Y, in my custom link structure: $this->SermonHolder()->Link() . 'date/'. $this->sermonDate)

function GetSermon() {
        $date = Director::urlParam('ID');

        if(!preg_match('/\d{4}-\d{2}-\d{2}/', $date)){
            // if date is not properly formatted, return latest entry
            return DataObject::get("Sermon", "", "sermonDate DESC", "", "1");
        }

        $dataObject = DataObject::get_one('Sermon', "DATE_FORMAT(sermonDate, '%Y-%m-%d') = '$date'");
        if(!$dataObject){
            // if no dataobject, return latest entry
            return DataObject::get("Sermon", "", "sermonDate DESC", "", "1");
        }

        return $dataObject;
}

and the method is called in the template:

<% control GetSermon %>
   ... data output goes here ...
<% end_control %>

It works, but I'm not sure if there could be any draw backs for doing it this way.

Thanks again Banal for your help!!

Avatar
bummzack

Community Member, 904 Posts

8 November 2009 at 9:48pm

Hi

No, your method works just as well. There are always different ways to approach a problem like this.
Instead of using DataObject::get with a limit clause, you could also use DataObject::get_one which does basically the same but is better readable in my opinion.

The problem you got with your Menus and content is probably because you didn't pass the right templates to the renderWith method. Or it could be caused because you access stuff in the template that isn't accessible via the DataObject.

As long as you don't need two different appearances/templates (for sermon/ and sermon/date/xxxx-xx-xx), your approach works fine. I suggest you leave it the way it is. You could improve the URL in two ways though:
1) You can now skip the '/date' string in your url. Create URLs like this: mypage.com/sermon/xxxx-xx-xx and use $date = Director::urlParam('Action'); instead.
2) Use the Format method of the Date object to format the date as you desire (dd-mm-yyyy). Eg.
$this->SermonHolder()->Link() . $this->sermonDate->Format('d-m-Y')

Avatar
Crossbound

Community Member, 14 Posts

9 November 2009 at 2:14am

Edited: 09/11/2009 2:16am

Ah okay.. I was under the impression that the urlParam['action'] needed to be a method, so I didn't even try to just using it for my date.
And formatting the date to was my limited OOP understanding. I tried sermonDate.Format() instead of sermonDate->Format()
I definitely will make the changes to have a shorter URL because that's what I initially intended to do.

P.S: Ich hatte noch festgestellt das du in der Schweiz wohnst! Cool.. ich bin in der naehe von Schaffhausen aufgewachsen und meine Eltern und Geschwister wohnen alle noch in CH.

Avatar
bummzack

Community Member, 904 Posts

9 November 2009 at 8:37am

The action usually maps to a method on the controller, but if the method isn't available, the Action parameter will still be available for you to use. In PHP you'll always have to use the -> syntax when dealing with Objects and Members/Methods. The dot-syntax is used in the .ss template, which can cause confusion sometimes.

Re P.S: Ja, ich wohne tatsächlich in der Schweiz (Biel). Die Welt ist klein, nicht wahr ;)

Avatar
ajshort

Community Member, 244 Posts

9 November 2009 at 10:52am

Just to let you know that as of 2.4 you will need to explicitly define an action for it to be available - otherwise it will throw a 404 error (so the GetSemon method won't work). Also, Director::urlParam() is deprecated and you should use $this->request->param().

Go to Top