Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A Generic, catch-all action in Zend Framework... can it be done?

This situation arises from someone wanting to create their own "pages" in their web site without having to get into creating the corresponding actions.

So say they have a URL like mysite.com/index/books... they want to be able to create mysite.com/index/booksmore or mysite.com/index/pancakes but not have to create any actions in the index controller. They (a non-technical person who can do simple html) basically want to create a simple, static page without having to use an action.

Like there would be some generic action in the index controller that handles requests for a non-existent action. How do you do this or is it even possible?

edit: One problem with using __call is the lack of a view file. The lack of an action becomes moot but now you have to deal with the missing view file. The framework will throw an exception if it cannot find one (though if there were a way to get it to redirect to a 404 on a missing view file __call would be doable.)

like image 573
rg88 Avatar asked Nov 30 '22 07:11

rg88


2 Answers

Using the magic __call method works fine, all you have to do is check if the view file exists and throw the right exception (or do enything else) if not.

public function __call($methodName, $params)
{
    // An action method is called
    if ('Action' == substr($methodName, -6)) {
        $action = substr($methodName, 0, -6);

        // We want to render scripts in the index directory, right?
        $script = 'index/' . $action . '.' . $this->viewSuffix;

        // Script file does not exist, throw exception that will render /error/error.phtml in 404 context
        if (false === $this->view->getScriptPath($script)) {
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception(
                sprintf('Page "%s" does not exist.', $action), 404);
        }

        $this->renderScript($script);
    }

    // no action is called? Let the parent __call handle things.
    else {
        parent::__call($methodName, $params);
    }
}
like image 175
Ludwig Avatar answered Dec 06 '22 10:12

Ludwig


You have to play with the router http://framework.zend.com/manual/en/zend.controller.router.html

I think you can specify a wildcard to catch every action on a specific module (the default one to reduce the url) and define an action that will take care of render the view according to the url (or even action called)

new Zend_Controller_Router_Route('index/*', 
array('controller' => 'index', 'action' => 'custom', 'module'=>'index') 

in you customAction function just retrieve the params and display the right block. I haven't tried so you might have to hack the code a little bit

like image 27
stunti Avatar answered Dec 06 '22 08:12

stunti