问题
In Java I can write a really basic JSP index.jsp
like so:
<% request.getRequestDispatcher("/home.action").forward(request, response); %>
The effect of this is that a user requesting index.jsp
(or just the containing directory assuming index.jsp
is a default document for the directory) will see home.action
without a browser redirect, i.e. the [forward](http://java.sun.com/javaee/5/docs/api/javax/servlet/RequestDispatcher.html#forward(javax.servlet.ServletRequest,%20javax.servlet.ServletResponse)) happens on the server side.
Can I do something similar with PHP? I suspect it's possible to configure Apache to handle this case, but since I might not have access to the relevant Apache configuration I'd be interested in a solution that relies on PHP alone.
回答1:
If you are concerned about CURL availability then you could use file_get_contents()
and streams. Setting up a function like:
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;
}
This just sets up a GET, but you can do a post with file_get_contents()
as well.
回答2:
The trick about Request.Forward is that it gives you a clean, new request to the action you want. Therefore you have no residu from the current request, and for example, no problems with scripts that rely on the java eq of $_SERVER['REQUEST_URI'] being something.
You could just drop in a CURL class and write a simple function to do this:
<?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);
}
}
}
Just dump this in class.CURLHandler.php and you can do this:
ofcourse, using $_REQUEST is not really safe (you should check $_SERVER['REQUEST_METHOD']) but you get the point.
<?php
include('class.CURLHandler.php');
die CURLHandler::doRequest($_SERVER['REQUEST_METHOD'], 'http://server/myaction', $_REQUEST);
?>
Ofcourse, CURL's not installed everywhere but we've got native PHP curl emulators for that.
Also, this gives you even more flexibility than Request.Forward as you could also catch and post-process the output.
回答3:
I believe one of the closest analogous methods would be to use the virtual() function on while running php as an apache module.
virtual() is an Apache-specific function which is similar to in mod_include. It performs an Apache sub-request.
回答4:
If you use an MVC like the Zend Framework provides you can change the controller action or even jump between controller actions. The method is _forward as described here.
回答5:
Try this.
function forward($page, $vars = null){
ob_clean();
include($page);
exit;
}
on included page the $vars
variable will work as the java request attributes
回答6:
Concepts Redirect and Forward like in Java, can be achievable in PHP too.
Redirect :: header("Location: redirect.php");
-- (URL in address bar changes)
Forward :: include forward.php ;
-- (URL unchanged at address bar)
Its manageable with this & other programming logics
回答7:
You can use like:
header ("Location: /path/");
exit;
The exit is need just in case some HTML output was sent before, the header() will not work, so you must sent new header before any output to the browser.
来源:https://stackoverflow.com/questions/433774/does-php-have-an-equivalent-of-javas-requestdispatcher-forward