Vlastní validátor na pole z formuláře
- .:M@rt!n:.
- Člen | 201
Ahoj,
na webu jsem si udělal vlastní validátor který mě kontroluje zda zadaná
hodnota je v intervalu, který je zadán v databázi. Kód vypadá takto:
presenter:
$db = $this->encoreRepository;
$form->addText('id', 'Innendurchmesser (ID) [mm]:', 30, 20)
//->addRule(Form::RANGE, 'ID musí být v rozmezí %d až %d.', array(0, 2750))
->addCondition($form::FILLED)
->addRule(function ($control) use ($db, $form) {
$p = $form->values->ad;
return ($db->compareID($control, $p));
}, 'Hodnota ID musí být z intervalu A a B.');
Třída:
public function compareID($control, $AD) {
return $this->getTable()->where('odA <= ?', $AD)->where('doA >= ?', $AD)->where('odI <= ?', $control->getValue())->where('doI >= ?', $control->getValue())->count() == 12;
}
Potřeboval bych ale aby mě pravidlo vypsalo i ten interval. Čili hraniční hodnoty ‚odI‘ a ‚doI‘ z dotazu:
$this->getTable()->where('odA <= ?', $AD)->where('doA >= ?', $AD)->where('odI <= ?', $control->getValue())->where('doI >= ?', $control->getValue())->count() == 12;
Ať zkouším co zkouším, furt se k tomu nemohu dostat. Proto bych prosil o radu
Editoval .:M@rt!n:. (22. 10. 2012 11:19)
- ViPEr*CZ*
- Člen | 822
Když mrkneš na dokumentaci: https://doc.nette.org/cs/forms#…
Tak se tam dají používat zástupné znaky s %.
A přes model stačí dvě metody s použitím funckí min() a max().
https://api.nette.org/…lection.html#_min
https://api.nette.org/…lection.html#_max
Doufám, že to pomůže… nijak zvlášť jsem to teď nestudoval
z dokumentace… už zase běžím jinám.
- .:M@rt!n:.
- Člen | 201
O zástupných znacích vím. min a max mě nenapadlo, ale stejně to nedělá to co potřebuji ještě. Dané intervaly (co potřebuji vypsat) jsou ještě omezené jinými intervaly. Jinak řečeno mám interval 0–399 ve kterém je asi další 5 intervalů(z těch potřebuji vypsat to max a min).
Nadřazený interval mě udá hodnota zadaná do pole AD.
takhle mě to najde pouze první záznam v db a ne aktuálně zjištěný podle zadané hodnoty v AD.
public function findMin($AD){
return $this->getTable()->where('odA <= ?', $AD)->where('doA >= ?', $AD)->min('odI');
}
Editoval .:M@rt!n:. (22. 10. 2012 12:53)
- MartyIX
- Člen | 217
Co nejak takto? Nezkousel jsem to. Je to jen napad.
$A = null;
$B = null;
$form->addText('id', 'Innendurchmesser (ID) [mm]:', 30, 20)
//->addRule(Form::RANGE, 'ID musí být v rozmezí %d až %d.', array(0, 2750))
->addCondition($form::FILLED)
->addRule(function ($control) use ($db, $form, &$A, &$B) {
$p = $form->values->ad;
$A = $this->getTable() ...;
$B = $this->getTable() ...;
return ($A < $p) && ($p < $B);
}, 'Hodnota ID musí být z intervalu %d a %d.', array(&$A, &$B));
- .:M@rt!n:.
- Člen | 201
bylo by to pěkné ale bohužel :)
EDIT: Pro doplnění píše to chybu
Using $this when not in object context
Editoval .:M@rt!n:. (22. 10. 2012 13:21)
- ViPEr*CZ*
- Člen | 822
Dobře, tak nepoužijete dostupné max a min, ale nějakou vlastní funkci co
získá ten interval. Toto bylo jen nakopnutí… nevím jak to je postavené,
co je to za interval ani jak se získá. A vlastně mě to ani nezajímá. Ale
přeci pokud ho nezískám vestavenými metodami, tak si musím napsat
vlastní.
Pointa je předat hodnoty metodě addRule, tak aby je mohla dosadit za ty
zástupné znaky.
- .:M@rt!n:.
- Člen | 201
Interval mám získaný takto:
public function compareID($control, $AD) {
return $this->getTable()->where('odA <= ?', $AD)->where('doA >= ?', $AD)->where('odI <= ?', $control->getValue())->where('doI >= ?', $control->getValue())->count() == 12;
}
To funguje tak jak má, čili mě to vypíše hlášku když jsem mimo interval, ale nevím jak vypsat ty hraniční hodnoty.
- MartyIX
- Člen | 217
.:M@rt!n:. napsal(a):
bylo by to pěkné ale bohužel :)
EDIT: Pro doplnění píše to chybu
Using $this when not in object context
Vy snad žertujete, pane Feynmane! Toto bys měl být schopný snad opravit, ne? Nicméně takto se to opraví:
$A = null;
$B = null;
$that = $this;
$form->addText('id', 'Innendurchmesser (ID) [mm]:', 30, 20)
//->addRule(Form::RANGE, 'ID musí být v rozmezí %d až %d.', array(0, 2750))
->addCondition($form::FILLED)
->addRule(function ($control) use ($db, $form, &$A, &$B, $that) {
$p = $form->values->ad;
$A = $that->getTable() ...;
$B = $that->getTable() ...;
return ($A < $p) && ($p < $B);
}, 'Hodnota ID musí být z intervalu %d a %d.', array(&$A, &$B));
- .:M@rt!n:.
- Člen | 201
MartyIX napsal(a):
…
I tak nejde.
>ViPErCZ napsal(a):
…
Tabulka vypadá následovně:
odA | do A | odI | doI
----|------|-----|----
0 | 599 | 0 | 399
0 | 599 | 400 | 599
600| 799 | 0 | 399
600| 799 | 400 | 599
600| 799 | 600 | 799
800| 999 | 400 | 599
800| 999 | 600 | 799
800| 999 | 800 | 999
a když mám tento kód:
$db = $this->encoreRepository;
$A = $this->encoreRepository->findMin($form->values->ad);
$B = $this->encoreRepository->findMax($form->values->ad);
$form->addText('id', 'Innendurchmesser (ID) [mm]:', 30, 20)
//->addRule(Form::RANGE, 'ID musí být v rozmezí %d až %d.', array(0, 2750))
->addCondition($form::FILLED)
->addRule(function ($control) use ($db, $form) {
$p = $form->values->ad;
return ($db->compareID($control, $p));
}, 'Wert ID muss vom Interval %d bis %d sein.', array($A, $B))
public function findMin($AD) {
$A = $this->getTable()->select('odI')->where('odA <= ?', $AD)->where('doA >= ?', $AD)->fetch()->odI;
return $A;
}
public function findMax($AD) {
$B = $this->getTable()->select('doI')->where('odA <= ?', $AD)->where('doA >= ?', $AD)->fetch()->doI;
return $B;
}
Tak mě to vrátí hodnoty pouze z prvního intervalu (hodnoty odI a doI). Čili do dotazu potřebuji ještě dostat nějak hodnoty toho pole ID z formuláře aby to vybralo to co má
Myslí mě to trochu pomaleji tak na mě buďte hodní :)
Editoval .:M@rt!n:. (23. 10. 2012 10:21)
- ViPEr*CZ*
- Člen | 822
$A = $this->getTable()->select('odI')->where('odA <= ?', $AD)->where('doA >= ?', $AD)->fetch()->odI;
Tohle asi nebude úplně dobře ne? Co když dosadím za $AD hodnotu 600?
Pak:
odA <= 600 a zároveň doA >= 600
Tak to podle té tabulky dostanu tyto výsledky:
600| 799 | 0 | 399
600| 799 | 400 | 599
600| 799 | 600 | 799
čili tři řádky, kde odI je 0, 400, 600 a tím, že uděláte fetch()
vyberete jen ten první, takže výsledek je 0. To takhle má být?
Podle mě teď jde o to, že nevíte jak sestavit SQL?
- .:M@rt!n:.
- Člen | 201
Ano mělo by to vybrat 0 do spodní hodnoty, ale 799 do horní hodnoty… A ano, s tím dotazem se pěkně plácám.
- ViPEr*CZ*
- Člen | 822
$min = $this->getTable()->select('odI')->where('odA <= ?', $AD)->where('doA >= ?', $AD)->min('odI');
$max = $this->getTable()->select('doI')->where('odA <= ?', $AD)->where('doA >= ?', $AD)->max('doI');
Narychlo… možná to jde lépe… ale nechci se s tím příliš seznamovat. A co toto udělá. Vybere ty 4 řádky co jsem už psal, ale navíc to nad nima vybere vždy max a min podle daného sloupce.
- .:M@rt!n:.
- Člen | 201
Takhle jsem to tam zkoušel taky dát, ale to vybere spodní hodnotu 0 a hodní 999 při AD 650. Při tom by tam měla být horní hranice 799. A na víc když zadám AD 850 tak mě to spodní hranici píše pořád 0 a horní 999, když by tam mělo být 400–999 (dle té tabulky)
- ViPEr*CZ*
- Člen | 822
$min = $this->getTable()->select('odI')->where('odA <= ?', $AD)->where('doA >= ?', $AD)->min('odI');
AD = 650 vybere odA <= 650 a zároveň doA >= 650
600| 799 | 0 | 399
600| 799 | 400 | 599
600| 799 | 600 | 799
a vybírá se jen odI což je třetí sloupec… nad ním je opravdu min 0. U max se vybere čtvrtý sloupec a tam je max 799. Tak nevím, ale vážně musíte něco dělat špatně :-)
Editoval ViPEr*CZ* (23. 10. 2012 12:51)
- .:M@rt!n:.
- Člen | 201
No já už to taky nechápu, podle mě by to mělo vybrat správně :) Dám sem radši celý kód kterého se to týká.
Presenter:
$form->addText('ad', 'Aussendurchmesser (AD) [mm]: ', 30, 20)
->addRule(Form::INTEGER, 'Wert AD muss numerisch sein.')
->setRequired('Füllen Sie bitte dieses Feld aus.');
$db = $this->encoreRepository;
$A = $this->encoreRepository->findMin($form->values->ad);
$B = $this->encoreRepository->findMax($form->values->ad);
$form->addText('id', 'Innendurchmesser (ID) [mm]:', 30, 20)
//->addRule(Form::RANGE, 'ID musí být v rozmezí %d až %d.', array(0, 2750))
->addCondition($form::FILLED)
->addRule(function ($control) use ($db, $form) {
$p = $form->values->ad;
return ($db->compareID($control, $p));
}, 'Wert ID muss vom Interval %d bis %d sein.', array($A, $B))
->addRule(function ($control) use ($db, $form) {
$p = $form->values->ad;
return ($db->compare($control, $p));
}, 'Wert ID muss kleiner als Wert AD sein.')
->addRule(Form::INTEGER, 'Wert ID muss numerisch sein.');
Model:
public function compareID($control, $AD) {
return $this->getTable()->where('odA <= ?', $AD)->where('doA >= ?', $AD)->where('odI <= ?', $control->getValue())->where('doI >= ?', $control->getValue())->count() == 11;
}
public function compare($control, $AD) {
return $control->getValue()<= $AD;
}
public function findMin($AD) {
return $this->getTable()->select('odI')->where('odA <= ?', $AD)->where('doA >= ?', $AD)->min('odI');
}
public function findMax($AD) {
return $this->getTable()->select('doI')->where('odA <= ?', $AD)->where('doA >= ?', $AD)->max('doI');
}
- .:M@rt!n:.
- Člen | 201
Tak první chyba odhalena-byla chyba v záznamech v db.
Dotazy by měly být ok
SELECT MIN(`odI`)
FROM `encore`
WHERE (`odA` <= ?) AND (`doA` >= ?)
SELECT MAX(`doI`)
FROM `encore`
WHERE (`odA` <= ?) AND (`doA` >= ?)
Ale stejně to teď vezme vždy hodnoty jen z prvního intervalu AD. Čili když zadám AD 100 tak interval odpovídá ale když zadám AD 800 tak se vyíšou hodnoty toho prvního intervalu. Tedy 0–599 a ne 400–999.