Jump to:

22979 Posts in 11815 Topics by 2826 members

General Questions

SilverStripe Forums » General Questions » Clarification of inheritance, please

General questions about getting started with SilverStripe that don't fit in any of the categories above.

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

Page: 1
Go to End
Author Topic: 993 Views
  • Romeo
    Avatar
    Community Member
    67 Posts

    Clarification of inheritance, please Link to this post

    Something didn't work just now which I thought would, which suggests my understanding of the way inheritance works in Silverstripe is slightly flawed. I'm hoping someone can clarify things for me.

    I have, as usual, a Page.php. I also have a ChildPage.php which extends that. In my themes directory, I have templates called Page.ss and ChildPage.ss, which behave exactly as they should. I also have a PHP class called StudentsPage, which extends ChildPage. My expectation was that unless I created a matching template file called StudentsPage.ss, it would default to using the parent template file, namely ChildPage.ss. But it doesn't, it uses Page.ss, skipping a generation. This is puzzling to me. It's not hugely problematic, because if I do create a file called StudentsPage.ss, it does use it. It doesn't go well with the Don't Repeat Yourself philosophy, though, as it is fundamentally the same as ChildPage.ss.

    What have I misunderstood here? This is Silverstripe 2.3.4.

  • Willr
    Avatar
    Forum Moderator
    5462 Posts

    Re: Clarification of inheritance, please Link to this post

    I believe this is just a limitation with the SSViewer. AFAIK How it works is it looks for a template with the same classname, if it can't find one then it defaults to page. It doesn't take any inheritance / class structure into account. You could customize the rendering of StudentPage by supplying a custom renderWith('ChildPage').

  • Sean
    Avatar
    Forum Moderator
    921 Posts

    Re: Clarification of inheritance, please Link to this post

    SilverStripe should have gone through the template stack, going up until it finds a template to render with. Perhaps this is a bug, as I'd expect it to work the way you want it.

  • Romeo
    Avatar
    Community Member
    67 Posts

    Re: Clarification of inheritance, please Link to this post

    Thanks, Willr and Sean. At least if it is a bug, I can presumably get around the consequences of it Willr's way.

  • Romeo
    Avatar
    Community Member
    67 Posts

    Re: Clarification of inheritance, please Link to this post

    I just created a little SS website purely to test this out, and I can confirm that in the case of a class hierarchy more than 2 levels deep, SilverStripe doesn't go up the template stack until it finds a template to render with, it goes straight to the Page template. At least, as structured in my little site it does. Just to make this clearer:

    I have 3 classes - the standard Page.php; ChildPage.php which extends Page.php; and GrandChildPage.php which extends ChildPage.php.

    In my templates, I have the standard Page.ss at the top level, and within the Layout directory, the standard Page.ss and also ChildPage.ss.

    When I display a ChildPage record, it is automatically rendered with the Layout/ChildPage.ss template. When I display a GrandChildPage record, though, it is not rendered with Layout/ChildPage.ss, despite it being a subclass of ChildPage, but is rendered instead with Layout/Page.ss. This definitely doesn't strike me as what it should do.

    I said I could get round the consequences of this by using renderWith, but I'm evidently not using it right. In my GrandChildPage_Controller class, I tried adding this:

       function Index(){
          return $this->renderWith("ChildPage");
       }

    It does indeed render it with ChildPage.ss, but ONLY with ChildPage.ss. That is, it just renders the page fragment ChildPage.ss, not the whole page as rendered by Page.ss with $Layout being rendered by ChildPage.ss, which is of course what I want. How do I force this to happen?

  • dalesaurus
    Avatar
    Community Member
    283 Posts

    Re: Clarification of inheritance, please Link to this post

    renderWith() only invokes the specific template you sent to it, and doesn't traverse up the regular Layout paths. Currently in 2.3 you are limited to the Page/Layout method of 2 levels. Templates don't inherit along side subclasses as they are selected by where you are generating content for, not by a hierarchical "Who's your daddy".

    You can probably force it to render with your templates manually by mimicking the way SSViewer processes templates in your controller.

    public function index() {
       foreach(array('GrandChildPage','ChildPage') as $template) {
          $subtemplateViewer = new SSViewer($template);
          $this->customise(array(
             $template => $subtemplateViewer->process($this)
          ));
       }
       return $this->renderWith('Page');

    Check out SSViewer.php, Line 303 for more meat. I'm not 100% sure this will work but if you need a custom rendering solution beyond the Layout method you're going to have to do something like this.

    Perhaps you could rethink your layout to use the 2 level system or create a new template with everything from your Page and ChildPage (html to /html) and use renderWith() on that. Its dirty but it works.

  • Romeo
    Avatar
    Community Member
    67 Posts

    Re: Clarification of inheritance, please Link to this post

    Thanks, that's very helpful and it does clarify things. It's not a huge problem and I can certainly work around it. I was just wanting to be clear about how it should work.

    993 Views
Page: 1
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.