Jump to:

3429 Posts in 1057 Topics by 734 members

Data Model Questions

SilverStripe Forums » Data Model Questions » Retrieving Data based on URL fragment.

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

Page: 1 2
Go to End
Author Topic: 2215 Views
  • Crossbound
    Avatar
    Community Member
    14 Posts

    Retrieving Data based on URL fragment. Link to this post

    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!

  • banal
    Avatar
    Community Member
    901 Posts

    Re: Retrieving Data based on URL fragment. Link to this post

    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.

  • banal
    Avatar
    Community Member
    901 Posts

    Re: Retrieving Data based on URL fragment. Link to this post

    Ouch. Accidentally double posted.

  • Crossbound
    Avatar
    Community Member
    14 Posts

    Re: Retrieving Data based on URL fragment. Link to this post

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

  • banal
    Avatar
    Community Member
    901 Posts

    Re: Retrieving Data based on URL fragment. Link to this post

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

  • Crossbound
    Avatar
    Community Member
    14 Posts

    Re: Retrieving Data based on URL fragment. Link to this post

    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.

  • banal
    Avatar
    Community Member
    901 Posts

    Re: Retrieving Data based on URL fragment. Link to this post

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

  • ajshort
    Avatar
    Community Member
    244 Posts

    Re: Retrieving Data based on URL fragment. Link to this post

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

    2215 Views
Page: 1 2
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.