Я надеюсь, что смогу предложить лучший способ решения проблемы, упомянутой Soph .Я знаю, что это не решение, связанное с JavaScript, к которому добавлен этот вопрос, но, как я вижу, это самый правильный путь.
Я столкнулся с тем же требованием - обновить заголовок при обновлении страницы, но сохранитьэто когда пользовательский ввод недопустим в других полях, потому что повторение нового кода проверки при каждой ошибке проверки раздражает.Таким образом, похоже, что эта задача не обновляет заголовок в запросе POST
и обновляет его в противном случае (запрос GET
).Решение, предложенное самим Soph , не может этого достичь - как можно знать, POST
запросы отправляются на сервер, и их данные не могут быть проанализированы клиентским JavaScript.
ПоэтомуЯ решил посмотреть на реализацию капчи Yii.Он состоит из двух классов, расположенных в пакете system.web.widgets.captcha
.Первый CCaptcha
расширен от CWidget
и который мы используем для добавления капчи в веб-форму следующим образом:
<?php
$this->widget("CCaptcha", array(
'buttonLabel' => "Generate another code",
'showRefreshButton' => false,
'clickableImage' => true
));
?>
Последний - CCaptchaAction
, который делает большинствозначительная работа по предоставлению капчи путем генерации проверочного кода и создания изображения.Принимая во внимание, что Yii разработан для объектно-ориентированного подхода, мы можем создать пару наших собственных классов Captcha
и CaptchaAction
, расширенных относительно CCaptcha
и CCaptchaAction
относительно, и поместить их в подкаталог components
нашего веб-приложения.directory.
Моя реализация обоих этих классов приведена ниже.
run()
метод CCaptchaAction
переопределен и очень похож на оригинальный, за исключением того, что есть еще один if
-ветвь выполняется, когда установлен render_refreshed
GET-параметр и где новый код проверки генерируется на лету, а соответствующее новое изображение отображается и возвращается как результат действия.
Введена открытая переменная refresh
в Captcha
классе и по умолчанию false
означает, что поведение виджета аналогично поведению CCaptcha
.Переопределив метод renderImage
, мы изменим код, отвечающий за подготовку выходного HTML-кода виджета.Чтобы быть более точным, именно здесь подготовлена ссылка на действие капчи, используемую как атрибут src
тега img
.В случае refresh
элемент имеет значение true
, к этой ссылке добавляется дополнительный параметр render_refreshed
.
Вот CaptchaAction.php
:
<?php
Yii::import("system.web.widgets.captcha.CCaptchaAction");
class CaptchaAction extends CCaptchaAction
{
const RENDER_REFRESHED_GET_VAR = "render_refreshed";
public function run()
{
if (isset($_GET[self::REFRESH_GET_VAR])) // AJAX request for regenerating code
{
$code = $this->getVerifyCode(true);
echo CJSON::encode(array(
'hash1' => $this->generateValidationHash($code),
'hash2' => $this->generateValidationHash(strtolower($code)),
// we add a random 'v' parameter so that FireFox can refresh the image
// when src attribute of image tag is changed
'url'=> $this->getController()->createUrl($this->getId(), array(
'v' => uniqid()
)),
));
}
else if (isset($_GET[self::RENDER_REFRESHED_GET_VAR]))
{
$this->renderImage($this->getVerifyCode(true));
}
else
$this->renderImage($this->getVerifyCode());
Yii::app()->end();
}
}
И этоCaptcha.php
:
<?php
Yii::import("web.system.widgets.CCaptcha");
class Captcha extends CCaptcha
{
public $refresh = false;
protected function renderImage()
{
if (!isset($this->imageOptions['id']))
$this->imageOptions['id'] = $this->getId();
if ($this->refresh)
{
$url = $this->getController()->createUrl($this->captchaAction, array(
'v' => uniqid(),
CaptchaAction::RENDER_REFRESHED_GET_VAR => 1
));
}
else
{
$url = $this->getController()->createUrl($this->captchaAction, array(
'v' => uniqid()
));
}
$alt = isset($this->imageOptions['alt']) ? $this->imageOptions['alt'] : '';
echo CHtml::image($url, $alt, $this->imageOptions);
}
}
Таким образом, использование довольно просто.В процессе подготовки данных модели для страницы сайта сделайте следующее:
...
// Creating order model's instance
$model = new MyModel();
$refreshCaptcha = true;
if (isset($_POST['MyModel']))
{
$refreshCaptcha = false;
...
}
...
$this->render("myView", array(
'model' => $model,
'refreshCaptcha' => $refreshCaptcha
));
После этого измените вызов виджета капчи в myView
шаблоне действия этой страницы:
<?php
$this->widget("Captcha", array(
'buttonLabel' => "Generate another code",
'showRefreshButton' => false,
'clickableImage' => true,
'refresh' => $refreshCaptcha
));
и незабудьте изменить actions
метод контроллера страницы, заменив CCaptchaAction
class на CaptchaAction
:
public function actions()
{
return array(
'captcha'=>array(
'class'=>'CaptchaAction',
'backColor'=>0xFFFFFF
)
);
}
Мне кажется, что он работает как положено.Надеюсь, это кому-нибудь поможет.