Validace formuláře – výpis form hodnoty do message

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Sentinel
Člen | 5
+
0
-

!! Koukám že jsem to založil do špatné skece, .. jestli je to možné, přesuňte to prosím do sekce Forms

Dobrý den,
snažím se proniknout do nette, vytvářím jednoduchý form. Odeslání e-mailu do databáze. Před uložením chci provézt kontrolu, jeslti záznam existuje. Pokud existuje rád bych vypsal vyplněný údaj do chybové hlášky, např. Email aaa@bbb.ccc byl již zaregistrován. Používám následující kód, ale domnívám se, že určitě existuje efektivnejší řešení.

<?php
class RegisterForm extends AppForm {

 public function __construct($parent = NULL, $name = NULL) {
  parent::__construct($parent, $name);

  $this->addText('email', 'E-mail')
   ->addRule(Form::FILLED, 'Nevyplnili jste e-mail')
   ->addRule('RegisterForm::emailValidator', 'Email %s byl již registrován.', $this['email']);
  $this->addText('nick', 'Nick')->addRule(Form::FILLED, 'Nevyplnili jste nick');
  $this->addSubmit('save', 'Registrovat')
    ->setValidationScope(TRUE)
          ->onClick[] = array($this, 'RegisterUser');
 }

 public static function emailValidator($control, $arg) {
  foreach ($control->rules as $rule) {
   $operationName = split('::', $rule->operation);

   if (count($operationName) > 1) {
    if ($operationName[1] == 'emailValidator') {
     $rule->message = sprintf($rule->message, $arg->value);
    }
   }
  }

  // tady bude nejaká kontrola, ted vzdy vratim false
  return false;
 }

 ...
}
?>

Metoda emailValidator($control, $arg) má v sobě cyklus, kdy procházím rules a když se jedná o validaci ulozim arg hodnotu do zprávy. V případě, že pouze vrátím false (bez foreach cyklu), hodnota z textboxu email se mi nezobrazí. Jde tedy pouze o zobrazení hodnoty z formuláře do zprávy.

Otázka tedy zní: jak to napsat efektivně?
Děkuji :)

Editoval Sentinel (14. 6. 2009 15:54)

jasir
Člen | 746
+
0
-

Mě stačí jen vrátit FALSE a nic neprocházet:

<?php
public static function emailValidator($control,$arg) {
	return FALSE;
}
?>

Hláška se vypíše. Registraci formuláře jsem dal do actionDefault() v presenteru.

Editoval jasir (14. 6. 2009 16:59)

lucass
Člen | 89
+
0
-

jasir napsal(a):

Mě stačí jen vrátit FALSE a nic neprocházet:

<?php
public static function emailValidator($control,$arg) {
	return FALSE;
}
?>

Hláška se vypíše. Registraci formuláře jsem dal do actionDefault() v presenteru.

Samotná validace je ok, hlášku to vrátí, ale bez nahrazení té konkrétní hodnoty %s za $this[‚email‘], tj. v pseudopřepisu: Email %s byl již registrován. → Email $this[‚email‘]->value byl již registrován, např. tedy Email aaa@bbb.ccc byl již registrován. Jestli jsem to napsal srozumitelněji.

jasir
Člen | 746
+
0
-

Samotná validace je ok, hlášku to vrátí, ale bez nahrazení té konkrétní hodnoty %s za $this[‚email‘], tj. v pseudopřepisu: Email %s byl již registrován. → Email $this[‚email‘]->value byl již registrován, např. tedy Email aaa@bbb.ccc byl již registrován. Jestli jsem to napsal srozumitelněji.

Teď mi došlo o co ti jde. A nevím jak na to :)
Ideální by asi bylo, kdyby Nette umožňovalo nějaký placeholder, něco jako:
...->addRule('RegisterForm::emailValidator', 'Email %value% byl již registrován.');. Místo %value% by se pak vložila aktuálně odeslaná hodnota.

Editoval jasir (15. 6. 2009 12:06)

vlki
Člen | 218
+
0
-

Podpora pro toho v pravidlech je. Konkrétně je to řešeno pomocí funkce vsprintf. Viz API – https://api.nette.org/…les.php.html#194

Myslím, že stačí argument pravidla dát do pole…

<?php
...
	->addRule('RegisterForm::emailValidator', 'Email %s byl již registrován.', array($this['email']));
...
?>
jasir
Člen | 746
+
0
-

vlki napsal(a):

Podpora pro toho v pravidlech je. Konkrétně je to řešeno pomocí funkce vsprintf. Viz API – https://api.nette.org/…les.php.html#194
Myslím, že stačí argument pravidla dát do pole…

Nene, to nestačí. Odeslaná hodnota formulářového prvku ještě není při vytváření formuláře známa.

vlki
Člen | 218
+
0
-

Jojo, už to taky vidím. Řešením by byl placeholder.

A nešlo by tu hodnotu předat odkazem? Vyžadovalo by to úpravu v útrobách Nette, ale pokud by se $this['email']->value předalo odkazem, tak v okamžiku validace (kdy se chybová zpráva vytváří) už bude hodnota formulářového prvku taková, jakou potřebujeme testovat.

jasir
Člen | 746
+
0
-

Nebo by Nette mohlo vkládat aktuální hodnotu do pole argumentů vsprintf() vždy, na první místo.
Pak by se na něj dalo odkazovat jako $1%s$, další argumenty by byly $2%s$, …
Bohužel je to BC Break.

_Martin_
Generous Backer | 679
+
0
-

No, zatím lze použít řešení, kdy chybu hlásí samotný validátor, tj.:

static function emailValidator(IFormControl $control)
{
	$email = $control->value;

	if (emailExists($email)) { // nějaká vlastní funkce kontrolující existenci emailu
		$control->addError("Email $email byl již registrován.");
		return FALSE;

	} else {
		return TRUE;
	}
}

Edit: ještě jsem si pozorněji prohlídnul tvůj kód a říkám si, zda by nešlo následující:

public static function emailValidator(IFormControl $control, $arg)
{
	foreach ($control->rules as $rule) {
		$operationName = split('::', $rule->operation);

		if (count($operationName) > 1) {
			if ($operationName[1] == 'emailValidator') {
				$rule->message = str_replace('%value%', $control->value, $rule->message);
				$rule->message = sprintf($rule->message, $arg->value); // pro případné další parametry
			}
		}
	}

	// ...
}

Editoval _Martin_ (15. 6. 2009 14:19)

Sentinel
Člen | 5
+
0
-

Díky moc vyzkouším to.

David Grudl
Nette Core | 8228
+
0
-

jasir napsal(a):

Nene, to nestačí. Odeslaná hodnota formulářového prvku ještě není při vytváření formuláře známa.

Tohle už by mělo aktuálně fungovat, během vytváření formuláře zpravidla je hodnota známa. Nicméně zkusil jsem experimentálně přidat podporu pro placeholder %value, ale samozřejmě to nebude fungovat v JavaScriptu.