Извините за длинное сообщение, но это могло бы быть интересно
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
public static string ReverseUsingArrayClass(string text)
{
char[] chars = text.ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
public static string ReverseUsingCharacterBuffer(string text)
{
char[] charArray = new char[text.Length];
int inputStrLength = text.Length - 1;
for (int idx = 0; idx <= inputStrLength; idx++)
{
charArray[idx] = text[inputStrLength - idx];
}
return new string(charArray);
}
public static string ReverseUsingStringBuilder(string text)
{
if (string.IsNullOrEmpty(text))
{
return text;
}
StringBuilder builder = new StringBuilder(text.Length);
for (int i = text.Length - 1; i >= 0; i--)
{
builder.Append(text[i]);
}
return builder.ToString();
}
private static string ReverseUsingStack(string input)
{
Stack<char> resultStack = new Stack<char>();
foreach (char c in input)
{
resultStack.Push(c);
}
StringBuilder sb = new StringBuilder();
while (resultStack.Count > 0)
{
sb.Append(resultStack.Pop());
}
return sb.ToString();
}
public static string ReverseUsingXOR(string text)
{
char[] charArray = text.ToCharArray();
int length = text.Length - 1;
for (int i = 0; i < length; i++, length--)
{
charArray[i] ^= charArray[length];
charArray[length] ^= charArray[i];
charArray[i] ^= charArray[length];
}
return new string(charArray);
}
static void Main(string[] args)
{
string testString = string.Join(";", new string[] {
new string('a', 100),
new string('b', 101),
new string('c', 102),
new string('d', 103),
});
int cycleCount = 100000;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingCharacterBuffer(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingCharacterBuffer: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingArrayClass(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingArrayClass: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingStringBuilder(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingStringBuilder: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingStack(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingStack: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingXOR(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingXOR: " + stopwatch.ElapsedMilliseconds + "ms");
}
}
}
Результаты:
Я нашел простой способ добиться этого - просто иметь скрытое поле в вашей форме входа в систему.
Теперь я не уверен, является ли ваша форма входа в систему общим элементом HTML или на самом деле является экземпляром Zend_Form
, но если это экземпляр Zend_Form
, вы можете просто добавить следующее:
$this->addElement('hidden', 'return', array(
'value' => Zend_Controller_Front::getInstance()->getRequest()->getRequestUri(),
));
Затем в моем сценарии аутентификации, как и в приведенном выше комментарии, у меня есть простое перенаправление, которое использует переданное значение, чтобы вернуть их на ту же страницу.
$this->_redirect($this->_request->getPost('return'));
Очевидно, что в этих двух примерах они написаны только для сжатия кода и, вероятно, не представляют собой лучший способ его выполнения. Два метода, использующие getRequest ()
в моем коде, на самом деле не встроены в перенаправление
или addElement
, но для примера я просто вставил их туда .
Очевидно, что приведенный выше ответ тоже будет работать, если только у вас не происходит массовое перенаправление страниц. Основная причина, по которой я сейчас использую такой способ, заключается в том, что не все мои формы работают в Zend_Form
, и также приятно иметь возможность изменять значение скрытого входного текста return
коробка для тестирования.
По сути то же самое, что Джеста делает в своем ответе, но я добавил следующие функции в свой класс "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:
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'));
}
}
У меня есть хук предиспетчинга в плагине для авторизации . В нем, если (и только если) пользователь должен быть зарегистрирован, я сохраняю URI запроса в сеансе и после входа в систему перенаправляю туда. Нет накладных расходов, кроме случаев перенаправления в форму входа. Но это тот случай, когда накладные расходы не проблема. :)
if(!$auth->hasIdentity()){
$this->_insertLastUrlToSession();
$this->redirect('/index/login');
} else {
//no overhead
}
Я уверен, что есть - это какой-то встроенный метод для этого где-то в ZF, но я ленив, поэтому я сделал это следующим образом:
Создайте свой собственный App_Controller_Action класс (create / library / App / Controller / Action. php). Расширьте все свои контроллеры из этого класса
В каждом из моих контроллеров я вызываю функцию $ this -> _ 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('/');