http://trac.symfony-project.org/ticket/9494
тобто в файлі sfGuardUserValidator.class.php в методі doClean() треба
$user = $this->getTable()->retrieveByUsername($username);
замінити на:
$user = $this->getTable()->$method($username);
http://trac.symfony-project.org/ticket/9494
тобто в файлі sfGuardUserValidator.class.php в методі doClean() треба
$user = $this->getTable()->retrieveByUsername($username);
замінити на:
$user = $this->getTable()->$method($username);
public function executeDelete(sfWebRequest $request)
{
$request->checkCSRFProtection();
$this->dispatcher->notify(new sfEvent($this, 'admin.delete_object', array('object' => $this->getRoute()->getObject())));
if(count($this->getRoute()->getObject()->getDetail()) > 0) {
$this->getUser()->setFlash('error', 'Не вдалось видалити. У вас є деталі цієї підкатегорії. Видаліть спочатку їх.');
$this->redirect('@subcategory');
}
if ($this->getRoute()->getObject()->delete())
{
$this->getUser()->setFlash('notice', 'The item was deleted successfully.');
}
$this->redirect('@subcategory');
}
В цьому випадку, якщо у вас будуть деталі цієї підкатегорії, замість помилки ви отримаєте флеш-повідомлення. Таким само варто перезавантажити і метод batchDelete().Question: actAs: Timestampable: ~ columns: title: string(250) body: text(5000) author_mail: string(100) author_name: string(100) answer: text(5000)
public function executeIndex(sfWebRequest $request) {
$this->questions = Doctrine::getTable('Question')->getQuestions();
$this->form = new QuestionsForm();
}
У вигляді IndexSuccess.php підключаємо таблиці стилів для вигляду форми і плагіна notifyBar та викликаємо партіал, передаючи йому екземпляр форми $form, отриманий з контроллера:
<link rel="stylesheet" href="<?php echo stylesheet_path('questions.css'); ?>">
<div id="question">
<?php include_partial('qform', array('form' => $form)); ?>
</div>
В партіалі _qform.php відображаємо форму та підключаємо Javascript з використаням слота questform:
<div class="gform">
<form id="qform" action="<?php echo url_for('@postquestion') ?>" method="POST" name="register">
<?php echo $form->renderGlobalErrors() ?>
<?php echo $form->renderHiddenFields() ?>
<br/>
<div>
<div class="form_label">
<div id="name_lbl">Ваше ім'я: <span class="err_lbl"></span></div>
<div id="email_lbl">Ваш e-mail: <span class="err_lbl"></span></div>
</div>
<input type="text" name="questions[author_name]" id="qfname" class="form_inputtext"/>
<input type="text" name="questions[author_mail]" id="qfemail" class="form_inputtext"/>
<p class="form_label" id="title_lbl">Запитання:
<span class="err_lbl"></span>
</p>
<input type="text" name="questions[title]" id="qftitle" class="form_inputtext"/>
<p class="form_label" id="full_lbl">Розгорнуте запитання:
<span class="err_lbl"></span>
</p>
<textarea type="text" class="form_textarea" name="questions[body]" id="qfbody"></textarea>
</div>
<div id="qcaptcha"> <?php echo $form['captcha'] ?> </div>
<p class="captcha_label err_lbl"><span></span></p>
</form>
<div class="qbtholder">
<div class="grid_3">
<div class="fbtn" id="qsendlink"><a href="#">Надіслати запитання</a> </div>
</div>
<div class="grid_3">
<div class="fbtn qclose" id="qclose"><a href="#">Закрити</a></div>
</div>
</div>
<div class="clear"></div>
</div>
<noscript>
<input type="submit" value="Надіслати" />
</noscript>
<?php slot('questform') ?>
<script src="<?php echo javascript_path('notify.js'); ?>"></script>
<script src="<?php echo javascript_path('jquery.easing-1.3.pack.js'); ?>"></script>
<script src="<?php echo javascript_path('main.js'); ?>"></script>
<script src="<?php echo javascript_path('question.js'); ?>"></script>
<?php end_slot(); ?>Далі в контроллері actions.class.php приймаємо та обробляємо запит:
public function executeCreate(sfWebRequest $request) {
$this->forward404If(!$request->isXmlHttpRequest(), 'Не надіслано');
$this->form = new QuestionsForm();
$rez = $this->processQuestionForm($request, $this->form);
if ($rez[0]) {
return $this->renderText(
json_encode(array(
'haserror' => false,
'message' => 'Запитання прийнято',
)
));
}
return $this->renderText(
json_encode(array(
'haserror' => true,
'message' => 'Помилка, спробуйте ще раз',
'errfield' => $rez[1],
'saveerr' => $rez[2],
)
)
);
}
protected function processQuestionForm(sfWebRequest $request, sfForm $form) {
$rez = array();
$captcha = array(
'recaptcha_challenge_field' => $request->getParameter('recaptcha_challenge_field'),
'recaptcha_response_field' => $request->getParameter('recaptcha_response_field')
);
$form->bind($request->getParameter($form->getName()), array('captcha' => $captcha));
if ($form->isValid()) {
$question = new Question();
$question->author_mail = $form->getValue('author_mail');
$question->author_name = $form->getValue('author_name');
$question->title = $form->getValue('title');
$question->body = $form->getValue('body');
if ($question->trySave()) {
$rez[0] = true;
}
else
$rez[0] = false;
$rez[1] = '';
$rez[2] = 'Помилка при збереженні, спробуйте пізніше';
return $rez;
}
else {
$errors = array();
foreach ($form->getErrorSchema() as $field => $error) {
$errors[$field] = $error->getMessage();
}
$rez[0] = false;
$rez[1] = $errors;
$rez[2] = '';
return $rez;
}
}
При наявності помилок, вони будуть передані до вигляду завдяки цьому коду:
foreach ($form->getErrorSchema() as $field => $error) {
$errors[$field] = $error->getMessage();
}
Повідомлення помилок для getMessage(); можна налаштувати в класі форми, наприклад:
$this->setValidators(array(
'title'=>new sfValidatorString(array('required' => false, 'max_length' => 255), array(
'required'=>'Будь ласка, введіть заголовок новини',
'invalid'=>'Неправильний формат поля',
'max_length' => 'Значення поля перевищує 255 символів'
)),
'body'=>new sfValidatorString(array('required' => false), array(
'required'=>'Будь ласка, введіть заголовок новини',
'invalid'=>'Неправильний формат поля',
'max_length' => 'Значення поля перевищує 255 символів'
)),
))
Залишилось вивести помилки з допомогою плагіна.
В файлі main.js перевантажуємо методи плагіна для тривалішого виводу помилок:
function msg(txt, type){
type = typeof(type) != 'undefined' ? type : 'error';
$.notifyBar({
html: txt,
cls: type, //"success"
delay: 2000,
animationSpeed: "normal"
});
}
function errMsg(txt, type){
type = typeof(type) != 'undefined' ? type : 'error';
$.notifyBar({
html: txt,
cls: type, //"success"
delay: 3000,
animationSpeed: "normal"
});
}
Та, власне, в файлі question.js пишемо функції для відправки форми з допомогою AJAX, її валідації на стороні сервера та виводу помилок:
$(document).ready(function() {
$("#qlink").click(function() {
$("#question form")[0].reset();
clearErrors();
$("#question").fadeIn("slow");
return false;
});
function clearErrors() {
$('#name_lbl').children().text('');
$('#email_lbl').children().text('');
$('#title_lbl').children().text('');
$('#full_lbl').children().text('');
$('.captcha_label').children().text('');
$('#qfname').removeClass("error_border");
$('#qfemail').removeClass("error_border");
$('#qftitle').removeClass("error_border");
$('#qfbody').removeClass("error_border");
$('#recaptcha_response_field').removeClass("error_border");
}
$("#qsendlink").live('click', function(){
$("#__notifyBar").remove();
clearErrors();
var i = $("#question form").serialize();
$.post(
'questions/post',
i,
function(rez){
if (!rez.haserror)
{
msg(rez.message, "success");
$("#question").hide();
$("#question form")[0].reset();
Recaptcha.reload();
}
else {
var saveerr = '';
if(rez.saveerr != null)
{
saveerr = rez.saveerr;
}
if(rez.errfield['author_name'] != null)
{
$('#name_lbl').children().text(rez.errfield['author_name']);
$('#qfname').addClass("error_border");
}
if(rez.errfield['author_mail'] != null)
{
$('#email_lbl').children().text(rez.errfield['author_mail']);
$('#qfemail').addClass("error_border");
}
if(rez.errfield['title'] != null)
{
$('#title_lbl').children().text(rez.errfield['title']);
$('#qftitle').addClass("error_border");
}
if(rez.errfield['body'] != null)
{
$('#full_lbl').children().text(rez.errfield['body']);
$('#qfbody').addClass("error_border");
}
if(rez.errfield['captcha'] != null)
{
$('.captcha_label').children().text(rez.errfield['captcha']);
$('#recaptcha_response_field').addClass("error_border");
}
errMsg(rez.message + saveerr);
}
},
'json'
);
return false;
});
$("#qclose").click(function(){
$("#__notifyBar").remove();
$("#question").fadeOut("100");
clearErrors();
Recaptcha.reload();
$("#question form")[0].reset();
return false;
})
return false;
});
Приклад 2 (валідація на стороні сервера та клієнта):
Для виведення форми використовується плагін fancybox.
Нехай маємо вигляд usefulSuccess.php. В ньому розміщуємо лінк для форми та підключаємо партіaл:<a href="#qrequest" id="askq" class="inline">Задать вопрос</a><?php include_partial('ask') ?>
В партіалі _ask.php відображаємо саму форму:
<div style="display:none" id="clcont">
<div id="qrequest">
<h3 class="request_header">Вопрос</h3>
<form action="/" method="post" id="request_form" class="qform">
<p class="topfield">
<label for="r_name" >Имя*</label>
<input type="text" name="r_name" id="r_name" class="required" style="width: 220px;"/>
</p>
<p>
<label for="r_phone">Телефон*</label>
<input type="text" name="r_phone" id="r_phone" class="required" style="width: 220px;"/>
</p>
<p>
<label for="r_email">Email</label>
<input type="text" name="r_email" id="r_email" class="email" style="width: 220px;"/>
</p>
<p style="vertical-align: top; position: relative;">
<label for="r_question" style="position: absolute; top: 10px;">Вопрос*</label>
<label for="r_question"></label>
<span>
<textarea cols="42" rows="8" name="r_question" id="r_question" class="required" style="width: 360px;"></textarea>
</span>
</p>
<div class="clear"></div>
<button type="submit" id="request_submit" class="submit" >Отправить</button>
</form>
</div>
</div>
Валідація базуватиметься на основі класів полів вводу, наприклад для поля:
<input type="text" name="r_email" id="r_email" class="email" style="width: 220px;"/>
буде використано валідатор email. Окрім цього, плагін validate містить наступні валідатори: required, remote, email, url, date, dateISO, number, digits, creditcard, equalTo, accept, maxlength, minlength, rangelength, range, max, min.
Також при необхідності є можливсіть валідації з використанням регулярних виразів.
Налашутвання повідомлень момилок проводиться в масиві:
messages: {
required: "Это поле должно быть заполнено.",
email: "Неверный формат адреса.")
}
Він розташований в файлі плагіна jquery.validate.js
На завершення потрібно в партіалі _ask.php додати слот для відображення, перевірки і виведення помилок:
<?php slot('js') ?>
<script type="text/javascript" src="<?php echo javascript_path('jquery.validate.js'); ?>"></script>
<script type="text/javascript">
$(document).ready(function(){
$("a.inline").fancybox();
var validator = $("#request_form").validate({
errorElement: "p",
focusCleanup: true,
blockFocusCleanup: false,
submitHandler: function() {
var i = $("#qrequest form").serialize();
$.post(
'pages/ask',
i,
function(rez){
if (rez.haserror == 'no')
{
$("#clcont").hide();
$("#request_form")[0].reset();
$.fancybox.close();
}
else {
$("#clcont").hide();
$.fancybox.close();
alert ('Не удалось отослать вопрос. Попробуйте позже, пожалуйста.');
}
},
'json'
);
return false;
}
});
$("#fancybox-close").live('click', function(){
$("#request_form")[0].reset();
validator.resetForm();
return false;
})
$(document).keyup(function(e)
{
switch(e.which)
{
case 27:
$("#request_form")[0].reset();
validator.resetForm();
return false;
}
});
});
</script>
<?php end_slot() ?>
В рядках
errorElement: "p",
focusCleanup: true,
blockFocusCleanup: false,
описано куди та як виводити помилки валідації.
Для відображення помилок використовується клас error, згодом його можна описати на власний розсуд:
.error {color: #ee0101;}
Форма надсилається ajax-ом в контроллер. Код контроллера в цьому випадку матиме приблизно наступний вигляд:
public function executeAsk(sfWebRequest $request) {
if ($request->isXmlHttpRequest() || $request->getParameter('r_email') !='') {
// Заповнення даних для надсилання
$toSendVals = array(
'r_name' => $request->getParameter('r_name'),
'r_phone' => $request->getParameter('r_phone'),
'r_question' => $request->getParameter('r_question'),
'r_email' => $request->getParameter('r_email'));
//Створення партіала тіла листа (слід винести в окремий файл)
$body = "
<table>
<tr>
<td>Имя</td>
<td>".$toSendVals['r_name']."</td>
</tr>
<tr>
<td>Телефон</td>
<td>".$toSendVals['r_phone']."</td>
</tr>
<tr>
<td>Email</td>
<td>".$toSendVals['r_email']."</td>
</tr>
<tr>
<td>Вопрос</td>
<td>".$toSendVals['r_question']."</td>
</tr>
</table>
";
try {
//Конструктор повідомлення
$message = $this->getMailer()->compose(sfConfig::get('app_from_mail'), sfConfig::get('app_manager_mail'), 'Вопрос из сайта', $body);
$message->setContentType("text/html");
//Надсилання і перевірка результатів
if (!$this->getMailer()->send($message)) {
return $this->renderText(json_encode(array('haserror' => 'yes', 'senderror' => 'yes')));
}
} catch (Exception $e) {
return $this->renderText(json_encode(array('haserror' => 'yes', 'senderror' => 'no', 'error'=> $e->getMessage())));
}
return $this->renderText(json_encode(array('haserror' => 'no')));
}
return $this->renderText(json_encode(array('haserror' => 'yes')));
}
Результат відправки перевіряється прапорцем haserror. Для наочності в прикладі вивід помилки надсилання виводиться з допомогою рядка:
alert ('Не удалось отослать вопрос. Попробуйте позже, пожалуйста.');
Цей вивід можна обробляти вже на власний смак, наприклад, з використанням плагіна noifyBar з пиркладу 1. Також шаблон листа в котнроллері слід розмістити в окремому партіалі і завантажувати його при виклиці відповідного екшена.
Другий приклад є універсальнішим, бо у випадку, якщо якимось чином невірно введені дані пройдуть валідацію на стороні клієнта, вони будуть перехоплені вже на серверній стороні (при умові, що для цього буде застосована фаладація форм з прикладу 1). В даному прикладі така валідація не застосовувалась в зв'язку з її непотрібністю.
Читати далі >