PHP有没有类似Java的RequestDispatcher.forward的等价物?

9
在Java中,我可以编写一个非常基本的JSP index.jsp,如下所示: <% request.getRequestDispatcher("/home.action").forward(request, response); %> 这样做的效果是,请求index.jsp(或者仅仅是包含该目录,假设index.jsp是该目录的默认文档)的用户将看到home.action,没有浏览器重定向,即[forward](http://java.sun.com/javaee/5/docs/api/javax/servlet/RequestDispatcher.html#forward(javax.servlet.ServletRequest,%20javax.servlet.ServletResponse))发生在服务器端。
我能用PHP做类似的事情吗?我怀疑可以配置Apache来处理这种情况,但由于我可能无法访问相关的Apache配置,因此我对仅依赖于PHP的解决方案感兴趣。
7个回答

1

试试这个。

function forward($page, $vars = null){
    ob_clean();
    include($page);
    exit;
}

在包含页面中,$vars 变量将作为 Java 请求属性工作。

1

我认为最接近的类比方法之一是在运行php作为apache模块时使用virtual()函数。

virtual()是一个Apache特定的函数,类似于mod_include中的“include”。它执行一个Apache子请求。


1

如果你使用像Zend Framework提供的MVC,你可以更改控制器操作甚至在控制器操作之间跳转。 方法是_forward,如此处描述


1
关于Request.Forward的诀窍在于它为您提供了一个干净、新的请求,以执行您想要的操作。因此,您没有当前请求的残留物,例如,不会出现依赖于java eq $_SERVER['REQUEST_URI']的脚本的问题。
您可以只使用CURL类并编写一个简单的函数来执行此操作:
<?php 
/**
 * CURLHandler handles simple HTTP GETs and POSTs via Curl 
 * 
 * @author SchizoDuckie
 * @version 1.0
 * @access public
 */
class CURLHandler
{

    /**
     * CURLHandler::Get()
     * 
     * Executes a standard GET request via Curl.
     * Static function, so that you can use: CurlHandler::Get('http://www.google.com');
     * 
     * @param string $url url to get
     * @return string HTML output
     */
    public static function Get($url)
    {
       return self::doRequest('GET', $url);
    }

    /**
     * CURLHandler::Post()
     * 
     * Executes a standard POST request via Curl.
     * Static function, so you can use CurlHandler::Post('http://www.google.com', array('q'=>'belfabriek'));
     * If you want to send a File via post (to e.g. PHP's $_FILES), prefix the value of an item with an @ ! 
     * @param string $url url to post data to
     * @param Array $vars Array with key=>value pairs to post.
     * @return string HTML output
     */
    public static function Post($url, $vars, $auth = false) 
    {
       return self::doRequest('POST', $url, $vars, $auth);
    }

    /**
     * CURLHandler::doRequest()
     * This is what actually does the request
     * <pre>
     * - Create Curl handle with curl_init
     * - Set options like CURLOPT_URL, CURLOPT_RETURNTRANSFER and CURLOPT_HEADER
     * - Set eventual optional options (like CURLOPT_POST and CURLOPT_POSTFIELDS)
     * - Call curl_exec on the interface
     * - Close the connection
     * - Return the result or throw an exception.
     * </pre>
     * @param mixed $method Request Method (Get/ Post)
     * @param mixed $url URI to get or post to
     * @param mixed $vars Array of variables (only mandatory in POST requests)
     * @return string HTML output
     */
    public static function doRequest($method, $url, $vars=array(), $auth = false)
    {
        $curlInterface = curl_init();

        curl_setopt_array ($curlInterface, array( 
            CURLOPT_URL => $url,
            CURLOPT_CONNECTTIMEOUT => 2,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_FOLLOWLOCATION =>1,
            CURLOPT_HEADER => 0));

        if (strtoupper($method) == 'POST')
        {
            curl_setopt_array($curlInterface, array(
                CURLOPT_POST => 1,
                CURLOPT_POSTFIELDS => http_build_query($vars))
            );  
        }
        if($auth !== false)
        {
              curl_setopt($curlInterface, CURLOPT_USERPWD, $auth['username'] . ":" . $auth['password']);
        }
        $result = curl_exec ($curlInterface);
        curl_close ($curlInterface);

        if($result === NULL)
        {
            throw new Exception('Curl Request Error: '.curl_errno($curlInterface) . " - " . curl_error($curlInterface));
        }
        else
        {
            return($result);
        }
    }

}

将此代码放入class.CURLHandler.php中,您就可以这样做:

当然,使用$_REQUEST并不是很安全(您应该检查$_SERVER['REQUEST_METHOD']),但您明白了重点。

<?php
include('class.CURLHandler.php');
die CURLHandler::doRequest($_SERVER['REQUEST_METHOD'], 'http://server/myaction', $_REQUEST);
?>

当然,CURL并没有在所有地方安装,但我们有本机PHP curl仿真器来应对。

此外,这比Request.Forward还给你更多的灵活性,因为你可以捕捉和后处理输出。


PHP默认情况下未启用curl。此外,curl将发起另一个HTTP请求,这意味着更多的CPU使用。 - Ivan
是的,但是 .forward 也会做类似的事情 FAIK。您没有与当前请求相关联的任何环境内容。因此,必须发生另一个“http请求”,您不希望在相同的范围内执行此脚本。因为它可能会导致已定义变量的问题。 - SchizoDuckie

0

Java中的重定向(Redirect)和转发(Forward)概念,也可以在PHP中实现。

重定向 :: header("Location: redirect.php"); -- (地址栏URL会改变)

转发 :: include forward.php ; -- (地址栏URL不会改变)

这些及其他编程逻辑都是可以处理的。


0
如果您担心CURL的可用性,那么您可以使用file_get_contents()和流。设置一个类似以下的函数:
function forward($location, $vars = array()) 
{
    $file ='http://'.$_SERVER['HTTP_HOST']
    .substr($_SERVER['REQUEST_URI'],0,strrpos($_SERVER['REQUEST_URI'], '/')+1)
    .$location;

    if(!empty($vars))
    {
         $file .="?".http_build_query($vars);
    }

    $response = file_get_contents($file);

    echo $response;
}

这只是设置了一个GET请求,但你也可以使用file_get_contents()进行POST请求。


那种方法有很多问题。首先,它不会传递任何标头,并且只能使用GET类型请求。 - troelskn

-3

你可以像这样使用:

header ("Location: /path/");
exit;

出口只有在先输出了一些HTML后才需要,因为header()将无法工作,因此您必须在向浏览器发送任何输出之前发送新标题。

这个解决方案涉及到客户端,而内部重定向则不是这种情况。 - MatthieuP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接