在zend框架中重定向到上一页

问题描述:

我想在登录页面中为我的登录表单操作(作为查询)添加重定向URL,因此登录后可以访问他或她正在浏览的上一页。在zend框架中重定向到上一页

首先我想到了使用Zend Session并将每个页面的url保存在一个变量中。但我在文档中看到它有开销。那么,有没有更好的方法来做到这一点?还是有没有其他的方式来使用zend会议没有开销?

首先,您需要抓取重定向的原始URL。 你可以通过做由Zend_Controller_Request类:

$url = Zend_Controller_Front::getInstance()->getRequest()->getRequestUri(); 

或者干脆:

$url = $_SERVER['REQUEST_URI']; 

然后,棘手的部分是通过用户的请求将它传递。 我推荐使用图书馆Zend_Session实例,尽管使用POST参数也是合法的:

$session = new Zend_Session_Namespace('Your-Namespace'); 
$session->redirect = $_SERVER['REQUEST_URI']; 

请注意,我们不停的地址包括基本路径。 要重定向的客户端控制器类,禁用选项“prependBase”就失去了基本路径插入:

$this->_redirect($url, array('prependBase' => false)); 
+3

也可以序列化请求对象:'$ session-> redirect = serialize($ this-> getRequest())'。实际上,这是我现在使用的解决方案,一年后;) – 2011-07-21 22:38:21

+0

序列化请求对象保留所有接收的数据,如POST数据。 – 2011-07-21 22:43:56

+0

@Morteza M.你在哪里(或什么时候)用你的方法重建请求?插入? – Julian 2011-08-23 14:35:00

我敢肯定有一些内置的方法,这样做的某处ZF,但我很懒,所以我也这样说:

创建自己的App_Controller_Action类(创建/库/应用/控制器/ action.php的)。扩展所有的控制器关闭该类

在我的每个控制器的,我调用$这个 - > _ initAuth()函数粘贴下面:

protected function _initAuth() 
{ 
    $auth = Zend_Auth::getInstance(); 
    if (!$auth->hasIdentity() && strcmp($_SERVER['REQUEST_URI'], '/auth/login') <> 0) 
     $this->_redirect('/auth/login' . $_SERVER['REQUEST_URI']); 
    else 
     $this->_identity = $auth->getIdentity(); 
} 

在我AuthController,我这样做,使确保我的表格点的完整URL:

$uri = str_replace('/auth/login','',$_SERVER['REQUEST_URI']); 
if (strlen($uri) > 0) 
    $form->setAction($this->_helper->url('login') . $uri); 
else 
    $form->setAction($this->_helper->url('login')); 

如果登录验证,然后我做到以下几点:

if (strlen($uri) > 0) 
    $this->_redirect($uri); 
else 
    $this->_redirect('/'); 
+0

很明显,在你的应用程序上线之前,一旦你知道所有可能接受的输入,你都会想要净化$ uri,我还没有完成。 – Mark 2009-08-08 16:58:32

我发现作为一种简单的方法来实现这一点,只是在你的登录表单中有一个隐藏的字段。

现在,林不知道,如果你的登录表单是一个通用的HTML元素或实际上是Zend_Form一个实例,但如果它的Zend_Form一个实例,你可以简单的添加如下内容:

$this->addElement('hidden', 'return', array(
     'value' => Zend_Controller_Front::getInstance()->getRequest()->getRequestUri(),    
      )); 

然后在我的身份验证脚本,就像上面的注释一样,我有一个简单的重定向,它使用传入的值将它们返回到同一页面。

$this->_redirect($this->_request->getPost('return')); 

很显然,在这两个例子中,他们只是写来压缩代码,可能并不代表来完成它的最佳方式。在我的代码中使用getRequest()的两种方法实际上并未嵌入redirectaddElement中,但出于示例目的,我只是将它们滑入其中。

上面的答案显然也适用,除非你有一些大规模的页面重定向。我现在以这种方式运行我的主要原因是因为并非我所有的表单都在Zend_Form中运行,并且它也能很好地更改隐藏的return输入文本框的值以用于测试目的。

+0

谢谢Mark和Jesta, 我更喜欢Jesta Answer。因为我在做大量的路由,转发,preDispatch功能等!不管怎样,谢谢你。我等待更多答案。 – 2009-08-08 18:21:03

+1

此解决方案不能始终工作。 – sanders 2010-10-22 14:40:58

+0

此解决方案的问题是数据丢失。场景:用户登录到应用程序并加载表单。他开始填写表格。同时,会话过期,他需要重新登录。当他提交表格时,使用这个解决方案,他发布的数据就会丢失。 – 2011-07-21 22:42:41

我在插件中有一个predispatch挂钩用于授权。其中如果(且仅当)用户需要登录,我将请求URI保存到会话中,登录后我在那里重定向。除了重定向登录表单之外,没有开销。但是这是一个没有问题的情况。 :)

if(!$auth->hasIdentity()){ 
    $this->_insertLastUrlToSession(); 
    $this->redirect('/index/login'); 
} else { 
    //no overhead 
} 
+0

谢谢大家, 因此,我将在_insertLastUrlToSession助手中使用新的Zend_Session_Namespace而不是Zend_Session :: start(),ha?谢谢。 – 2009-08-09 07:48:20

基本上相同的事情,Jesta正在做他的答案,但我增加了以下功能到我的“MW_Form”类 - 从控制器很容易$form->trackReferrer($this->getRequest()); - 这是我的所有形式的超以任何形式。该getReferrer()函数接受一个“默认”的说法(其中,如果用户参考标头禁用,或者没有来源 - 你会希望有一个默认的地方重定向回)

/** 
    * Adds a form element named "referrer" and sets its default value to either 
    * the 'referrer' param from the request, or the HTTP_REFERER header. 
    * 
    * @param Zend_Controller_Request_Abstract $request 
    * @return MW_Form 
    * @author Corey Frang 
    */ 
    public function trackReferrer(Zend_Controller_Request_Abstract $request) 
    { 
    $this->addElement('hidden', 'referrer'); 
    $this->setDefault('referrer', 
     $request->getParam('referrer', 
     $request->getServer('HTTP_REFERER'))); 
     // HTTP_REFERER not HTTP_REFERRER - grrr HTTP spec misspellings 

    // use no decorator for the actual form element 
    $this->referrer->setDecorators(array()); 

    // use our custom "referrer" decorator to stick the hidden before the <dl> 
    $decorators = $this->getDecorators(); 
    $this->clearDecorators(); 
    foreach ($decorators as $class=>$decorator) 
    { 
     if (substr($class,-5) == '_Form') { 
     $this->addDecorator('Referrer'); 
     $added = true; 
     } 
     $this->addDecorator($decorator); 
    } 
    if (!$added) $this->addDecorator('Referrer'); 

    return $this; 
    } 

    /** 
    * Returns the referrer field if it exists. 
    * 
    * @return string | false 
    * @param mixed $default The value to return if referrer isn't set 
    * @author Corey Frang 
    **/ 
    public function getReferrer($default = false) 
    { 
    if (!isset($this->referrer)) return $default; 
    $val = $this->referrer->getValue(); 
    if ($val) return $val; 
    return $default; 
    } 

的装饰使用 - 给你不使用在向上通过Zend_Form生成的<dl>任何行的附加benifit:

class MW_Form_Decorator_Referrer extends Zend_Form_Decorator_Abstract { 
    /** 
    * Attaches the standard "ViewHelper" decorator for the 'referrer' element 
    * prepended on the content 
    * 
    * @return void 
    * @author Corey Frang 
    **/ 
    public function render($content) 
    { 
    $form = $this->getElement(); 
    if ($form instanceOf MW_Form) 
    { 
     $referrer = $form->referrer; 
     if ($referrer) 
     { 
     $decorator = new Zend_Form_Decorator_ViewHelper(array('placement'=>self::PREPEND)); 
     $decorator->setElement($referrer); 
     return $decorator->render($content); 
     } 
    } 
    return "Error - No Referrer Found".$content; 
    } 
} 

示例用法(来自控制器):

$form = $description->getEditForm(); 
$form->trackReferrer($this->_request); 
if ($this->_request->isPost()) 
{ 
    if ($form->process($this->_request->getPost())) 
    { 
    return $this->_redirect($form->getReferrer('/page')); 
    } 
} 
+0

Gnarf看起来不错。但“trackReferrer”函数在哪个文件中执行?它是什么类型的?它是帮手还是什么? – sanders 2010-10-22 07:22:45

+0

它在我的'My_Form'类中,它扩展了'Zend_Form',并且我的所有表单都从此延伸... – gnarf 2010-10-26 16:59:53

我看到这已经有了一个答案,但我也想抛弃它,就像用不同的方式来使用静态方法来处理猫的交易。

class App_Helpers_LastVisited { 
    /** 
    * Example use: 
    * App_Helpers_LastVisited::saveThis($this->_request->getRequestUri()); 
    */ 
    public static function saveThis($url) { 
     $lastPg = new Zend_Session_Namespace('history'); 
     $lastPg->last = $url; 
     //echo $lastPg->last;// results in /controller/action/param/foo 
    } 

    /** 
    * I typically use redirect: 
    * $this->_redirect(App_Helpers_LastVisited::getLastVisited()); 
    */ 
    public static function getLastVisited() { 
     $lastPg = new Zend_Session_Namespace('history'); 
     if(!empty($lastPg->last)) { 
      $path = $lastPg->last; 
      $lastPg->unsetAll(); 
      return $path; 
     } 

     return ''; // Go back to index/index by default; 
    } 
} 

这不会一直运行,只是需要根据。

,这里(http://hewmc.blogspot.com/2010/08/simple-way-to-store-last-visited-url-in.html

+0

谢谢。我阅读你的博客文章和这个答案。你知道,在这个问题中接受的答案在应用程序根本不使用会话的情况下使用表单时非常简单。但是Web应用程序通常使用会话,因此添加另一个键/值对来存储以前的URL是没有意义的,您的答案很有帮助。 – 2010-09-03 16:07:56

+0

感谢您的回复,非常友善。并感谢您访问我的博客,我通常会哼哼,没有访客:)。其实我已经更新了这篇博文,但只是我的态度更多地包含了其他用例,代码没有改变。祝你有美好的一天! – 2010-09-04 01:14:47

就是全部的代码,我的博客文章的一部分。除了gnarfs答案,我修改了它使它验证 - 对于那些你得到的就踢它一脚。

$this->addDecorator(array('WrapClose' => 'HtmlTag'), array('tag' => 'div', 'placement' => 'PREPEND', 'closeOnly' => true)); 
$this->addDecorator('Referrer'); 
$this->addDecorator(array('WrapOpen' => 'HtmlTag'), array('tag' => 'div', 'placement' => 'PREPEND', 'openOnly' => true)); 

您可以尝试使用HTTP_REFERRER标题是这样的:

// str_replace is the easiest way to get rid of domain - u can also preg_replace it 
return str_replace("http://".Zend_Controller_Front::getInstance()->getRequest()->getServer("HTTP_HOST"),"",Zend_Controller_Front::getInstance()->getRequest()->getServer("HTTP_REFERER")); 
+0

它并不总是可用的。 – 2012-11-28 11:59:31

这Zend框架插件允许您保存当前和上次合格的网址并过滤掉不需要的网址。如果你不通过会话传递变量的粉丝,你可以尝试获得$ _ SERVER [“HTTP_REFERER”]变量以安全的方式

<?php 

class Plugins_PageLog extends Zend_Controller_Plugin_Abstract 
{ 
    public function preDispatch(Zend_Controller_Request_Abstract $request){ 
     $module = $request->getModuleName(); 
     $controller = $request->getControllerName(); 
     $action = $request->getActionName(); 
     $params=$request->getParams(); 

     // to grap urls that are in default module, not in auth controller, and not an error url 
     $controller2= Zend_Controller_Front::getInstance(); 
     if ($controller2->getDispatcher()->isDispatchable($request) 
      && ($module == 'default' || $module == NULL) 
      && $controller != 'auth' 
      && (!isset($params['error_handler'])) 
     ) { 

      // init 2 session variables: the current and last qualified url 
      if (!isset($_SESSION['redirect'])) $_SESSION['redirect'] = ''; 
      if (!isset($_SESSION['last_visited_url'])) $_SESSION['last_visited_url'] = ''; 

      // tempurl is to save current qualified url temporarily to ensure current and last qualified url will not be same 
      if (!isset($tempUrl)) $tempUrl = ''; 
      if ($_SESSION['last_visited_url'] != $_SESSION['redirect']) { 
       $tempUrl = $_SESSION['redirect']; 
       $tempParams = $_SESSION['redirect_params']; 
      } 

      // save current qualified url 
      $_SESSION['redirect']=$request->getRequestUri(); 
      $_SESSION['redirect_params'] = $params; 

      // to ensure there are no duplicated urls due to browser refresh 
      if ($tempUrl != $_SESSION['redirect']){ 
       $_SESSION['last_visited_url'] = $tempUrl; 
       $_SESSION['last_visited_url_params'] = $tempParams; 
      } 
     } 

     //echo '<pre>';var_dump($_SESSION['last_visited_url']);echo '</pre>'; 
     //echo '<pre>';var_dump($_SESSION['redirect']);echo '</pre>'; 
    } 
} 

:随意使用和评论。基本上它会检查您的引荐网址,并与您的服务器本地名称和方案(http/https)相匹配。

class My_Tools 
{ 
    public static function doesUrlMatchServerHttpHost($url) 
    {  
     $scheme = Zend_Controller_Front::getInstance()->getRequest()->getScheme(); 
     $httpHost = Zend_Controller_Front::getInstance()->getRequest()->getHttpHost(); 
     $needleUrl = $scheme.'://'.$httpHost.'/'; 
     if (strpos($url, $needleUrl) !== 0) 
     { 
      return false; 
     } 
     return true; 
    } 

    public static function safelyGetReferrerUrl($default) 
    { 
     if (isset($_SERVER['HTTP_REFERER']) == false){ 
      return $default; 
     } 
     if (self::doesUrlMatchServerHttpHost($_SERVER['HTTP_REFERER']) == false){ 
      return $default; 
     } 
     return $_SERVER['HTTP_REFERER']; 
    } 
} 

然后就是

$referrerUrl = My_Tools::safelyGetReferrerUrl('/'); 

缺省状态下,你可以设置本地URI( '/')

$此 - > _重定向(这 - $> Request()方法 - > getServer( 'HTTP_REFERER'));

+0

它不保存状态。而HTTP_REFERER并不总是可用的。 – 2013-03-27 15:06:18