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

时间:2009-08-08 16:31:49

标签: zend-framework url session redirect

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

首先,我考虑使用Zend Session并将每个页面的url保存在变量中。但我在文档中读到它有开销。那么,有更好的方法吗?还是有另一种方法来使用zend会话而没有开销?

11 个答案:

答案 0 :(得分:16)

首先,您需要获取重定向的原始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));

答案 1 :(得分:8)

我发现,作为一种简单的方法,您只需在登录表单中添加隐藏字段即可。

现在,我不确定您的登录表单是否为通用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输入文本框的值以进行测试。

答案 2 :(得分:6)

基本上和Jesta在他的答案中所做的一样,但是我将以下函数添加到我的“MW_Form”类中 - 这是我所有表单的超类 - 从控制器到任何文件都很容易$form->trackReferrer($this->getRequest());形成。 getReferrer()函数采用“默认”参数(如果用户禁用了REFERER标头,或者没有引用者 - 您希望将默认位置重定向回来)

  /**
   * 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>中任何行的好处:

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'));
  }
}

答案 3 :(得分:3)

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

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

答案 4 :(得分:2)

我看到这已经有了答案,但是我也想把它扔进去,就像使用静态方法来处理这种交易一样。

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

答案 5 :(得分:1)

这个Zend框架插件允许您保存当前和最后限定的URL并过滤掉不需要的URL。随意使用和评论:

<?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>';
    }
}

答案 6 :(得分:0)

除了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));

答案 7 :(得分:0)

您可以尝试使用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"));  

答案 8 :(得分:0)

如果您不是通过会话传递变量的粉丝,您可以尝试以安全的方式获取$ _SERVER ['HTTP_REFERER']变量。基本上它会检查您的引荐来源网址是否与您的服务器本地名称和方案(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('/')

答案 9 :(得分:0)

$这 - &GT; _redirect($这 - &GT; Request()方法 - &GT; getServer( 'HTTP_REFERER'));

答案 10 :(得分:-2)

我确信在ZF的某个地方有一些内置的方法,但我很懒,所以我这样做了:

创建自己的 App_Controller_Action 类(创建/library/App/Controller/Action.php)。将所有控制器扩展到此类

在我的每个控制器中,我调用$ this-&gt; _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('/');