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.

All other Modules /

Discuss all other Modules here.

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

Default Function


Reply


6 Posts   1716 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, 4092 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
Pigeon

Community Member, 243 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