Question

I have a controller and action which I'm accessing through a custom URL. The original route is still accessible though at the default location

zend.com/controller/action

How can I change this to simulate a "Page not found" when the user tries to access this URL? Is it possible?

Was it helpful?

Solution

If the action handler is used to respond to both URLs, you would first have to detect which URL is being requested (using $this->_request->getRequestUri()). If the default URL is detected I think the easiest way to create a "page not found" would be to use

$this->_redirect("/path/to/simulated/404/page") 

and set up a controller and action to respond.

This won't actually send an HTTP 404, though. To do that, I think you would have to raise an exception within your action handler. I don't know what the official "zendy" way of doing this is, but this seems to work:

throw new Zend_Controller_Action_Exception('Not Found', 404);

OTHER TIPS

You could change the main controller script to redirect a certain controller name and action name to a new page. But it's probably easier to add a new rule to the .htaccess file, indicating that this specific URL should be redirected to an error page. Example:

RewriteRule ^controller/action/?$ / [R=404,L]

Or redirect the page to an error page within your site:

RewriteRule ^controller/action/?$ /error/page-not-found/ [L]

You need to use:

$this->getResponse()->setHttpResponseCode(404);

And build your own 404 view

$this->view->message = 'Page not found';

Or you could forward to an error controller for example

$this->_forward('page-not-found', 'error');

Finally, if you have in your error controller

//...
switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:

                // 404 error -- controller or action not found
                $this->getResponse()->setHttpResponseCode(404);
                $this->view->message = 'Page not found';
                break;
//...

You can just do as @bogeymin said:

throw new Zend_Controller_Action_Exception('Not Found', 404);

If you are looking other solutions than mod_rewrite based, you may create a Regex Route to match the actions you need to hide.

The other solution is to restrict access to Actions using Zend_Acl, treating each action as an ACL resource.

But the simplest and most lightweight solution is still mod_rewrite in .htaccess.

Edit:

As you can see, this may be done in numerous ways. But probably, you will need some kind of the switch, to still allow somehow to access the "hidden" action. In this case, use:

  • mod_rewrite for quick implementation (switching requires the person to know the .htaccess rules)
  • Zend_Router - the person who knows the right route can still access the feature
  • Zend_Acl + Zend_Auth for scalable and secure solution.

If you don't need to have authenticated users, Zend_Acl combined with Zend_Router might be the solution.

For smart handling the exceptions and building ACL's, see this (and other posts on this blog):

Handling errors in Zend Framework | CodeUtopia - The blog of Jani Hartikainen

By default the router includes default routes for :module/:controller/:action/ and :controller/:action/. You can disable these with:

$router->removeDefaultRoutes();

then only routes you setup will work. If you still want to use the default routes for some other things, you'll either have to go with one of the other answers posted or add your own 'default' routes which will match all but the modules/controllers you have custom routes for.

If you don't want to remove the default route as @Tim Fountain suggests, you should do something like this in your controller (either preDispatch or whateverAction methods)

$router = $this->getFrontController()->getRouter();
$route = $router->getCurrentRouteName();
// if we reached this controller/action from the default route, 404
if ($route == 'default')
{
  throw new Zend_Controller_Action_Exception('Not Found', 404);
}

I think, all answers above are incorrect. Those show ways to achieve the same thing, but present logic at the wrong place in your application, which eventually can cause trouble later on.

The correct part of your route logic is, how extremely simple, in the routes. What is missing is that the default route Zend_Controller_Router_Route_Module does not allow you to add exceptions to specific routes. So what you need to do, is remove the default route from your routes, and add a new custom route (which should function exactly as the default route, but allows excludes) at it's place.

You can write the new route by extending the class of the default route.

class My_Custom_Route extends Zend_Controller_Router_Route_Module
{
    protected $_excludes = array();

    public function exclude($abc)
    {
         //add to $_excludes here the controller/action you want to exclude
    }

    public function match($abc)
    {
         //add functionality here that denies if the mod/contr/action is in $_excludes
         //you can also add this in a separate method
         //re-use parent code
    }
}

You can now add add the excludes for example in a config file, and load + add the excludes at the place you initiate the new Route (and add it to the router). Off you go.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top