Ako napísať registráciu v súlade s PDO?
- Čamo
- Člen | 798
Prečítal som si toto vlákno ale to ma neuspokojilo. Skončilo to tam pri porovnávaní konkrétneho kódu pre mysql:
catch(\PDOException $e) { // SQL chyba
if ((int)$e->errorInfo[1] === 1062) { // SQL kód pro narušení unikátního klíče
/* Nick je obsazen, vyber si jinej */
} else { /* Jiná SQL chyba */ }
} catch (\Exception $e) { /* Jakákoliv obecná chyba */ }
Ale ako napísať takú kontrolu, ktorá by bola v súlade s používaním
PDO, teda univerzálnu. Dá sa to vôbec tak napísať?
Ma napadlo pri výskyte akejkoľvek chyby testovať následne existenciu mena
v tabuľke.
catch(Exception e)
{
if($this->database->table(users)->where('name = ?', $values['name'])->fetch())
{
$form->addError('Meno je už obsadené');
$this->redirect('this');
}
else
{
'tuto neviem presne čo mám vyhodiť';
}
}
Ale moc elegantne mi to nepripadá. Dá sa to napísať lepšie?
- Jan Suchánek
- Člen | 404
Takto?
public function registrationProccess(Form $form)
{
$values = $form->getValues();
try {
$this->registerFacade->register($values); // možná v tvém případě stačí nějaký repositář, aby to nebyl takovej špageťák
$this->redirect("this"); // todo redirect na spravné místo
} catch(\MyInvalidException $e){ // vytvoř si sbírku vyjímek a neodchytávej pouze Exception
$form->addError('Sorry, this name "'. $values->name .'" already exists.');
}
}
Video o vyjímkách od Honzy Tvrdíka.
Editoval jenicek (8. 7. 2014 11:52)
- David Kudera
- Člen | 455
Třeba kdyby/doctrine vyhodí Kdyby\Doctrine\DuplicateEntryException, tu si hned v nějaké např. přidávací metodě pro uživatele odchytávám. Zkontroluji, jestli se jedná o duplikaci na emailu nebo někde jinde (třeba nějaký username) a podle toho dál vyhodím svou App\DuplicateEmailException nebo App\DuplicateUsernameException apod. Jinak nechám vyhodit zpět původní exception z kdyby.
try {
$dao->save($user);
} catch (\Kdyby\Doctrine\DuplicateEntryException $e) {
if (checkSomehowIfExceptionIsBecauseOfDuplicateEmail($e)) {
throw new \App\DuplicateEmailException($user, $e);
} else {
throw $e;
}
}
No a ve formu si odchytávám už přímo tyhle moje výjimky.
Ono když je totiž jen kontrola podle toho, jestli už ten záznam v db není a má jít pak i editovat, tak je ta kontrola hned složitější. Při přeuložení bez změny by mi totiž form hodil chybu, že email už existuje.
- David Kudera
- Člen | 455
@Šaman nene neinsertuji. Jen jsem to asi špatně napsal. Pokud by při editaci nechal jen tuhle kontrolu:
if($this->database->table(users)->where('name = ?', $values['name'])->fetch())
{
$form->addError('Meno je už obsadené');
$this->redirect('this');
}
tak formulář ukáže chybu, že jméno je obsazené, když ho nijak nezměním. Musel bych tu podmínku rozšířit a když těch „unikátních“ sloupců bude víc, tak se to zesložití a pro vkládání to bude jinak a pro editaci jinak. Proto mi přijde unique určitě lepší (spolu s tím, že do db to můžu vložit přímo atd…)
- David Kudera
- Člen | 455
@Čamo tady je dokumentace a tady je ten kód z kdyby/doctrine, ale taky koukám, že to je na mysql, asi… možná.....
á.. tak je to ještě trochu jinak.. je tam ještě tahle třída
a např. její metoda isUniqueConstraintViolation
pro kontrolu
podle jednotlivých kódů
Edit: trochu jsem se do toho asi zamotal, tady by někdo znalejší poradil víc určitě jak to vlastně funguje
Editoval David Kudera (8. 7. 2014 13:50)
- David Matějka
- Moderator | 6445
@Šaman
Při update samozřejmě unikátní index nevadí a nic nevyhazuje…
?? unikatni index se bere v potaz i pri update
- David Kudera
- Člen | 455
@matej21 myslím, že šlo jen o nedorozumění. Tuším, že @Šaman myslel, že jsem psal unique klíči a tom, že to vyhodí chybu, když provedu update a unique sloupec nijak neupravím. Já ale myslel ne-unique sloupec a kontrolu jen podle podmínky, zda záznam už v db existuje. Ta by totiž při editaci ve formu chybu zobrazila
- Jan Suchánek
- Člen | 404
To záleží jaké metody v repository používaš a jakou db používáš. Pokud Nette Database Context tak něco jako:
$this->dbContext->table("user")->insert($values);
Editoval jenicek (8. 7. 2014 15:45)
- Filip Procházka
- Moderator | 4668
DuplicateEntryException bys neměl chytat, ale měl bys jí předcházet https://github.com/…cs/en/dao.md#…
- Čamo
- Člen | 798
Tak som to nakoniec zbastlil takto:
try
{
$row = $this->database->table('users')->insert($arr);
$this->flashMessage('Boli ste zaregistrovaní. Môžete sa prihlásiť');
$this->redirect('Sign:');
}
catch(\Exception $e)
{
$db = $this->database;
if($db->table('users')->where('username', $values['username'])->fetch() && !isset($row) )
{
$this->flashMessage('Meno '.$values['username'].' je už obsadené. Vyberte si prosím iné.');
$this->redirect('this');
}
elseif($db->table('users')->where('email', $values['email'])->fetch() && !isset($row) )
{
$this->flashMessage('Email '.$values['email'].' je už obsadený.');
$this->redirect('this');
}
else
{
throw $e;
}
}
Síce ak nastane nejaká iná výnimka(než duplicate entry) a zároveň už existuje daný uživateľ(čo by bola duplicate entry), hodí to chybne duplicate enty error a neošetrí tú skutočnú výnimku. Ale po opravení mena/mailu sa aj tá neošetrená vyhodí/zaloguje(ak teda ešte je čo logovať). Ale zase je to hádam dosť nepravdepodobné. Na viac zatiaľ nevydalo.
Editoval Čamo (9. 7. 2014 1:14)
- David Kudera
- Člen | 455
Akorát to má tu nevýhodu, že u dalšího formu můžeš třeba
zapomenout na to, že aby prošel redirect, musíš pak vyhodit všechny
ostatní výjimky. Jasně dojde ti to, jakmile zjistíš, že redirect neprošel
a throw $e
hned doplníš. Ale co třeba za měsíc? Co za delší
dobu? Osobně vím, že bych pak koukal, co to je, proč to tak je a k čemu to
je. Je to prostě trochu takové...... ehm.. chápeš ne?
Asi bych to fakt raději přesunul do nějaké modelové metody, v ní
chytal ty výjimky a převáděl je na svoje vlastní
DuplicateEmailException
, DuplicateNameException
apod.
Máš to znovupoužitelný a formulář se ti krásně zjednoduší, protože
hned od pohledu budeš vědět, co znamená
třeba catch (DuplicateEmailException $e)
- David Kudera
- Člen | 455
Spíš myslím, že radši ty kódy, přijde mi to takový jistější. Zkus znovu mrknout na to video o výjimkách, co je nahoře. Myslím, že tam se o tom taky mluvilo
- David Kudera
- Člen | 455
Opět video o výjimkách. A když už jsme se bavili o kdyby/doctrine, tak tady je ukázka, jak ty exceptiony vypadají. Ale je to celkem na tobě, tady jsou např. všechny v jednom souboru, někdo je ale dává jako jedna exception == jeden soubor apod. A uložení? Je to taky na tobě.. Pokud chceš mít např. v app/models/něco, tak klidně