Jump to:

3460 Posts in 1064 Topics by 739 members

Data Model Questions

SilverStripe Forums » Data Model Questions » Parent Controller-methods aren`t available in Custom Controller?

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

Page: 1 2
Go to End
Author Topic: 2579 Views
  • mtz
    Avatar
    Community Member
    17 Posts

    Parent Controller-methods aren`t available in Custom Controller? Link to this post

    Hello,

    im a little bit confused about the fact that i don`t get an contoller-Object back when im calling the
    DataObject::get_one method in custom controller:

    class App_Controller extends Page_Controller {

       function getSiteviaURLSegment($arguments) {
                
          $params = $arguments->allparams();
          $whereStatement = "URLSegment = '" . $params['URLSegment'] . "'";

          return DataObject::get_one("Page", $whereStatement);
          
    ....

       }

    }

    The Object im getting back is an ContentPage - Object in my Case. But i expected an Page-Controller - Object.
    That also seems to be reason for the fact that im unable to call the parent Controller-Methods like:

    $page = getSiteviaURLSegment($arguments);

    return $page->someFunctionThatIhaveDefinedintheparentPage_Controller();

    help Anybody?

    Cheers,
    Mattes

  • mtz
    Avatar
    Community Member
    17 Posts

    Re: Parent Controller-methods aren`t available in Custom Controller? Link to this post

    ok, by trying around i found out that the init() - Function in Page_Contoller is fireing by loading my AppController. So what is about the other Page_Controller-methods?

    i don`t get it .... ;(

  • MarcusDalgren
    Avatar
    Community Member
    288 Posts

    Re: Parent Controller-methods aren`t available in Custom Controller? Link to this post

    DataObject::get_one() does just that, it gets a DataObject or in this case a Page object.
    That's what you get back, not the controller.

    Could you explain what you're trying to do?

  • Martijn
    Avatar
    Community Member
    271 Posts

    Re: Parent Controller-methods aren`t available in Custom Controller? Link to this post

    App_Controller extends Page_Controller : then App_Controller has all the methods defined in Page_Controller....

  • tilluigi
    Avatar
    Community Member
    9 Posts

    Re: Parent Controller-methods aren`t available in Custom Controller? Link to this post

    hi, i am here with MTZ trying to solve this.

    the problem we are having is that the dataRecord property of our custom controller is empty.
    we tried to set the property manually in one of the Controller's action methods, but it didn't work.

    In the documentation it says that the ContentController is passed a DataObject on construction and that the DataRecord is being fetched from the SiteTree based on the URLSegment. however, this is not happening in our case, our DataRecord is always empty/ a new object:

    "Its constructor is passed a DataObject which is stored in $this->dataRecord. Any unrecognised method calls, for example, Title() and Content(), will be passed along to the data record.

    Subclasses of ContentController are generally instantiated by ModelAsController; this will create a controller based on the URLSegment action variable, by looking in the SiteTree table."
    (http://api.silverstripe.org/2.4/sapphire/control/Page_Controller.html)

    How do we have to configure SS so our controller will be instantiated WITH a DataObject (by ModelAsController?)

    Our Rules look like this:

    Director::addRules(50, array(
       'myapp/$Action/$URLSegment' => 'AppController'
    ));

    The controller (essentials) like this:

    class AppController extends Page_Controller {

       
    function content($arguments) {

          $html = '';
          
          $html .= $this->Title; // THIS WILL ALWAYS BE EMPTY
          
          return $html;
       }
       

    }

    if this is solved, the next question would be how to use a custom template for our controller..hehe..thanks for your help
    tilluigi

  • MarcusDalgren
    Avatar
    Community Member
    288 Posts

    Re: Parent Controller-methods aren`t available in Custom Controller? Link to this post

    Since you made your own URL rule for AppController then ModelAsController won't do it's thing. Like the docs say it attaches a DataRecord when __construct() is run. This is because the Object class runs defineMethods() on __construct() which dynamically adds methods from extensions etc.

    They do this and set a property called failover to the dataRecord like this (from ContentController.php __construct()):

    $this->dataRecord = $dataRecord;
    $this->failover = $this->dataRecord;

    The crux is that this has to be done before parent::__construct() is called, otherwise it won't work. The failover concept comes from ViewableData. Also keep in mind that if you're extending ContentController (which you are indirectly) then it's pretty much assuming that the attached dataRecord will be a SiteTree object of some sort and will fail under some circumstances if the dataRecord isn't.

    I can help you guys all the way down this road since I've made my own Controller implementation that works outside of the SiteTree model but with pretty much all the cool functionality we've come to expect. However you really only should go down this road if you're absolutely shure that the normal way of doing things really won't work for you.

  • tilluigi
    Avatar
    Community Member
    9 Posts

    Re: Parent Controller-methods aren`t available in Custom Controller? Link to this post

    thanks for clarifying! of course we could work our ways around this circumstance by fetching our page object manually and creating all the HTML within the controller - but this wouldn't have all the elegance we're used to from silverstripe...

    but what you say sounds a little scary!! will we have to sell our smiles to go down that road?? ;-)
    even then your solutions sounds very interesting, but will it mean mingling in the core of SS and loosing updateability?
    or: under what circumstances would you recommend this solution?

    we are working on a custom controller to feed an iPad App with custom HTML and we've done AJAXified websites where your solution would have been very handy, too!

  • MarcusDalgren
    Avatar
    Community Member
    288 Posts

    Re: Parent Controller-methods aren`t available in Custom Controller? Link to this post

    No you won't have to touch the core at all so no worries there. What I've done is code my own nested controller which replaces ModelAsController. Since ModelAsController has such a low priority in the routing it's easy to replace. I then wrote my own version of a ContentController that uses any kind of dataobject as a dataRecord instead of just SiteTree objects.

    The functionality mimics many other PHP frameworks in the sense that for example mysite.com/projects would map to ProjectController and it will look for a Project dataobject to use as a dataRecord unless you set it to something else. It also comes with a templating system based on SS normal templating system so you don't have to put your html in the controllers. It also hands over to ModelAsController if it doesn't find anything that matches so your regular site will keep on working just fine.

    When to use it? I use it whenever I have to build something that really doesn't fit in the normal site with pages model. In one case a customer wanted a project management tool to use with their customers and that doesn't fit so then I use my own custom controllers for that. If you just want to show custom page layout when someone visits your site with an iphone or when they're using AJAX then you can easily do that with normal SilverStripe. You'd do something like this in your Page_Controller for example.

    public function index() {
    //However you check for Iphone visitors, $isIphone is just a dummy
    if ($isIphone) {
    return $this->renderWith(array("IphoneLayout", "IphoneMaster"));
    }
    else {
    return $this->render();
    }
    }

    Attached to this post are the two controllers I use for this. Keep in mind though that the BaseController uses an external library (Flourish) to figure out the singular versions of verbs so you either have to include Flourish in your project or go into BaseController and change how it figures out what controller to load. All that stuff is done in getNestedController().

    You'll also need to put the URL rule below in your _config.php in order for the BaseController to take over.

    Director::addRules(2, array(
    '$URLSegment//$Action/$ID/$OtherID' => 'BaseController'
    ));

    Attached Files
    2579 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.