Перенаправление на предыдущую страницу в Zend Framework - PullRequest
28 голосов
/ 08 августа 2009

Я хочу добавить URL-адрес перенаправления к своему действию форм входа в систему (в виде запроса) на странице входа в систему, поэтому после входа в систему можно перейти на предыдущую страницу, на которой он или она просматривал.

Сначала я подумал об использовании Zend Session и сохранил URL каждой страницы в переменной. но я прочитал в документации, что это накладные расходы. Так есть ли лучший способ сделать это? или есть другой способ использовать сессию Zend без накладных расходов?

Ответы [ 11 ]

16 голосов
/ 22 мая 2011

Во-первых, вам нужно получить исходный 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));
8 голосов
/ 08 августа 2009

То, что я нашел в качестве простого метода для достижения этой цели, это просто иметь скрытое поле в форме входа в систему.

Теперь я не уверен, является ли ваша форма входа универсальным HTML-элементом или фактически является экземпляром Zend_Form, но если это экземпляр Zend_Form, вы можете просто добавить следующее:

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

Затем в моем скрипте аутентификации, как и в приведенном выше комментарии, у меня есть простое перенаправление, которое использует переданное значение, чтобы вернуть их на ту же страницу.

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

Очевидно, что в этих двух примерах они просто написаны для сжатия кода и, вероятно, не представляют лучший способ его выполнить. Два метода, использующие getRequest() в моем коде, на самом деле не встроены в redirect или addElement, но для примера я просто вставил их туда.

Ответ выше, очевидно, также будет работать, если только у вас не будет массового перенаправления страниц. Основная причина, по которой я сейчас запускаю свой метод, заключается в том, что не все мои формы работают в Zend_Form, и также приятно иметь возможность изменять значение скрытого текстового поля return для тестирования.

6 голосов
/ 09 августа 2009

В основном то же самое, что делает Джеста в своем ответе, но я добавил следующие функции в свой класс "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;
  }

Используемый декоратор - дает вам дополнительную выгоду от неиспользования каких-либо строк в <dl>, созданном zend_form:

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 голосов
/ 08 августа 2009

У меня есть плагин predispatch в плагине для авторизации. В нем, если (и только если) пользователь должен войти в систему, я сохраняю URI запроса в сеансе и после входа в систему перенаправляю туда. Нет накладных расходов, кроме как при перенаправлении на форму входа. Но это тот случай, когда накладные расходы не проблема. :)

if(!$auth->hasIdentity()){
  $this->_insertLastUrlToSession();
  $this->redirect('/index/login');
} else {
  //no overhead
}
2 голосов
/ 02 сентября 2010

Я вижу, что на этот вопрос уже есть ответ, но я бы хотел добавить и мой, просто как другой способ заключить сделку с котом, используя статические методы.

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)

1 голос
/ 30 августа 2012

Этот плагин Zend Framework позволяет сохранять текущие и последние квалифицированные URL-адреса и отфильтровывать нежелательные URL-адреса. не стесняйтесь использовать и комментировать:

<code><?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 '
'; // echo '
';var_dump($_SESSION['redirect']);echo '
'; } }
0 голосов
/ 27 марта 2013

$ это -> _ редирект ($ this-> GetRequest () -> getServer ( 'HTTP_REFERER'));

0 голосов
/ 27 ноября 2012

Если вы не являетесь поклонником передачи переменных через сеанс, вы можете попытаться получить переменную $ _SERVER ['HTTP_REFERER'] безопасным способом. По сути, он проверяет, совпадает ли URL вашего реферера с локальным именем вашего сервера и схемой (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 ('/')

0 голосов
/ 08 мая 2012

Вы можете попробовать использовать заголовок 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 голосов
/ 06 октября 2010

В дополнение к ответу 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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...