Php 如何将控制器/操作设置为未找到页面

Php 如何将控制器/操作设置为未找到页面,php,zend-framework,zend-route,Php,Zend Framework,Zend Route,我有一个通过自定义URL访问的控制器和操作。虽然位于默认位置,但仍可访问原始管线 zend.com/controller/action 当用户尝试访问此URL时,如何更改此设置以模拟“未找到页面”?是否可能?您可以更改主控制器脚本,将某个控制器名称和操作名称重定向到新页面。但是,向.htaccess文件中添加新规则可能更容易,这表明应该将此特定URL重定向到错误页面。例如: RewriteRule ^controller/action/?$ / [R=404,L] 或将页面重定向到站点中的错误

我有一个通过自定义URL访问的控制器和操作。虽然位于默认位置,但仍可访问原始管线

zend.com/controller/action

当用户尝试访问此URL时,如何更改此设置以模拟“未找到页面”?是否可能?

您可以更改主控制器脚本,将某个控制器名称和操作名称重定向到新页面。但是,向
.htaccess
文件中添加新规则可能更容易,这表明应该将此特定URL重定向到错误页面。例如:

RewriteRule ^controller/action/?$ / [R=404,L]
或将页面重定向到站点中的错误页面:

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

如果操作处理程序用于响应两个URL,则首先必须检测请求的URL(使用$this->\u request->getRequestUri()。如果检测到默认URL,我认为创建“未找到页面”的最简单方法是使用

$this->_redirect("/path/to/simulated/404/page") 
并设置一个控制器和动作来响应

不过,这实际上不会发送HTTP404。为此,我认为您必须在操作处理程序中引发异常。我不知道官方的“zendy”方法是什么,但这似乎有效:

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

如果您正在寻找基于
mod_rewrite
以外的其他解决方案,则可以创建一个与需要隐藏的操作相匹配的解决方案

另一种解决方案是使用限制对操作的访问,将每个操作视为ACL资源

但最简单、最轻量级的解决方案仍然是
.htaccess
中的
mod_rewrite

编辑: 正如你所看到的,这可以通过多种方式实现。但,您可能需要某种类型的切换,以允许以某种方式访问“隐藏”操作。在这种情况下,请使用:

  • mod_rewrite
    快速实现(切换要求人员了解
    .htaccess
    规则)
  • -知道正确路线的人仍然可以访问该功能
  • +用于可扩展和安全的解决方案
如果您不需要有经过身份验证的用户,
Zend_Acl
Zend_路由器
相结合可能是解决方案

有关智能处理异常和构建ACL的信息,请参阅以下内容(以及本博客上的其他帖子):

您需要使用:

$this->getResponse()->setHttpResponseCode(404);
并构建自己的404视图

$this->view->message = 'Page not found';
或者,您可以转发到错误控制器,例如

$this->_forward('page-not-found', 'error');
最后,如果您的错误控制器中有

//...
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;
//...
你可以照@bogeymin说的做:

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

默认情况下,路由器包括
:模块/:控制器/:操作/
:控制器/:操作/
的默认路由。您可以通过以下方式禁用这些功能:

$router->removeDefaultRoutes();

然后,只有您设置的路线才能工作。如果您仍想在其他方面使用默认路由,则必须使用发布的其他答案之一,或添加您自己的“默认”路由,该路由将匹配除自定义路由之外的所有模块/控制器。

如果您不想按建议删除默认路由,您应该在控制器中执行类似操作(无论是
preDispatch
还是
whateverAction
方法)


我认为,以上所有答案都是错误的。这些方法显示了实现相同目标的方法,但在应用程序中的错误位置显示了逻辑,这最终可能会导致以后的问题

路线逻辑的正确部分是路线中极其简单的部分。缺少的是默认路由
Zend_控制器_路由器_路由_模块
不允许您向特定路由添加异常。因此,您需要做的是从路由中删除默认路由,并在其位置添加一个新的自定义路由(该路由的功能应与默认路由完全相同,但允许排除)

您可以通过扩展默认路由的类来编写新路由

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
    }
}

现在,您可以在配置文件中添加排除项,并在启动新路由的位置加载并添加排除项(并将其添加到路由器)。走吧。

这听起来像是一个通用的解决方案。你说的是zend吗?
.htaccess
重写是一个非常通用的解决方案,但它同样适用于用zend编写的站点。你想隐藏特定的、一个动作还是更多的动作?@takeshin,我现在有一个,但我会在将来添加更多,我需要做同样的事情。我只是还没有写出来。那么在这种情况下,答案不是一个好的解决方案(很难扩展)。有关详细信息,请参阅我的答案。那么,我如何添加自己的默认路由以匹配除我有自定义路由的控制器/操作之外的所有控制器/操作?是否有类似于
matchAllExcept($custom_routes)
?不幸的是,没有,但是您可以添加一个只匹配所需模块的正则表达式路由-类似于:(news | products | profiles)/:controller/:action这样更容易检测路由器使用的路由而不是请求uri。-查看我的回答我强烈建议避免重定向引发异常(自定义应用程序_PageNotFoundException比使用Z_C_Action_异常要好,或者您无法区分两者),然后在错误视图中显示相应的消息。
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
    }
}