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.

All other Modules /

Discuss all other Modules here.

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

Default Function


Go to End


6 Posts   2840 Views

Avatar
craigm

Community Member, 9 Posts

10 June 2010 at 10:31am

Edited: 10/06/2010 10:33am

Hi there,

I've created a module called 'view' which renders a bunch of data into a template. The templates get rendered by calling the function 'viewTemplate' within the page_controller of view and it gets passed a template ID through the urlParams['ID'] variable.

So to view a template, you'd go to the URL:

www.mysite.com/view/viewTemplate/1

Ive created a template called 'InvalidPage' which will get rendered if the user enters an ID that does not exist, which is easy because i just write that into the viewTemplate function.

What i was wondering is if there was a way to handle incorrect function calls with a default function. So if the user tried to browse to:

www.mysite.com/view/incorrectFunctionName/1

Which is a valid page, but an incorrect function, can i get it to render the 'InvalidPage' template?

should i do something like, create a __construct function for my view page_controller and loop through all the values returned by 'get_defined_functions()' and check them against the URL segment. Then if its not found, renderWith(array('InvalidPage)) ?

Any other suggestions?

Cheers.

Avatar
craigm

Community Member, 9 Posts

10 June 2010 at 10:52am

ok, so instead of looping through all the defined functions, because there are a lot inherited, ive simply created my own array of allowed function names and written this:

public function __construct(){
        parent::__construct();
        $functions = array('viewTemplate', 'testFunction');
        $this->validFunction($functions);
    }

    public function validFunction($functions){
        $counter = 0;
        foreach($functions as $function){
            if(Director::urlParam('Action') != $function){
                $counter++;
            }
        }

        if($counter == count($functions)){
            //echo 'invalidFunction';
            return $this->renderWith(array('InvalidPage'));
        }
    }

if i uncomment out the echo, i do get it when it hits a function that is not valid, however its not rendering my template.

I get the error: [Notice] Undefined index:

I assume this is getting thrown by the parent::__construct call but it has to be there otherwise the code breaks.

Any suggestions?

Avatar
UncleCheese

Forum Moderator, 4102 Posts

10 June 2010 at 11:12am

I'm having a really hard time wrapping my head around what you're trying to do. What is this module for, exactly?

A couple things that might help you:

1) As of 2.4, you cannot pass arbitrary actions through the URL. Any value for the URLParam "Action" has to be accounted for in your $allowed_actions array.

2) Without an action to run, a controller falls back on the index() function

3) You might look into the PHP wildcard method __call() to handle dynamically called functions.

Avatar
craigm

Community Member, 9 Posts

10 June 2010 at 11:20am

Edited: 10/06/2010 11:22am

Ok, so with that not working, ive tried to do it a different way. Instead of rendering the template, ive tried to do a Director::redirect like this:

public function __construct(){
        parent::__construct();
        $functions = array('viewTemplate', 'invalidFunction');
        $this->checkFunction($functions);
    }//construct

    public function checkFunction($functions){
        $counter = 0;
        foreach($functions as $function){
            if(Director::urlParam('Action') != $function){
                $counter++;
            }
        }

        if($counter == count($functions)){
            Director::redirect('invalidFunction');
        }
    }//checkFunction

    public function invalidFunction(){
        $this->errorMessage = "Im sorry, function that you have tried to call seems to be invalid.";
        return $this->renderWith(array('InvalidPage'));
    }//invalidFunction

Which as i understand it, should hit the Director::redirect call and then render the page using the 'invalidFunction' function within the current page_controller which will render the 'invalidPage' template.

If i directly browse to: www.mysite.com/view/invalidFunction
it does render the 'invalidPage' template properly.

However, if i browse to: www.mysite.com/view/sdfsfsdfsdfsdfsdfsd which is not a valid function then it breaks and says:

"Fatal error: Call to a member function getHeader() on a non-object in C:\wamp\www\mysite\sapphire\core\control\Controller.php on line 448"

so im not sure what exactly is causing that, but for some reason it wont redirect. any ideas?

Avatar
craigm

Community Member, 9 Posts

10 June 2010 at 11:26am

Edited: 10/06/2010 11:27am

haha, crap, thats exactly what i was trying to do except i was basically trying to write that functionality myself because i didnt know it existed!

Thanks for that!

So when it hits a function that is not in the $allowed_actions array, is there a way to make it render an template i specify?

Currently, when i enter an Action that isnt in the array, it simply echos out:

"Action 'sdfsdfsd' isn't allowed on class View_Controller"

onto a white screen.

Avatar
dhensby

Community Member, 253 Posts

10 June 2010 at 11:43am

I think you really want to be using the $url_handlers static in the controller.

This allows you to define the default handling function for URLs.

eg:

class Page_Controller extends ContentController {

static $url_handlers = array(
'' => 'index',//this is the default handler for a URLSegment
'$URLSegment/$Action/$ID' => 'myHandler' //this means if there is an action defined, then handle it with the function 'myHandler'
);

function index() {
return $this;
}

function myHandler() {
if ($this->urlParam['Action'] == 'view') {
$this->renderWith(...);
}
....
}

}

Further reading: http://doc.silverstripe.org/controller#url_handling

I use this to allow me to do: example.com/image-gallery/1 (and this will show the image in the gallery with ID == 1) rather than example.com/image-gallery/view/1