Zimní výprodej Zimní výprodej
40 % bodů zdarma díky naší Zimní akci!

Diskuze: Žádné ověření duplicitního jména

Aktivity (1)
Avatar
Lukáš
Redaktor
Avatar
Lukáš:7.7.2019 13:11

Ahoj, mám SignUpForm a v něm :

public function create(callable $onSuccess): Form
{
        $form = $this->factory->create();
        $form->addText('username', 'Username:')
                ->setRequired('Please enter a username.');
        $form->addEmail('email', 'Your e-mail:')
                ->setRequired('Please enter your e-mail.');
        $form->addPassword('password', 'Password:')
                ->setRequired('Please create a password.');
        $form->addSubmit('send', 'Sign up');
        $form->onSuccess[] = function (Form $form, \stdClass $values) use ($onSuccess): void {
                try {
                        $this->userManager->add($values->username, $values->email, $values->password);
                } catch (DuplicateNameException $e) {
                        $form['username']->addError('Username is already taken.');
                        return;
                }
                $onSuccess();
        };
        return $form;
}

a UserManager:

public function add(string $username, string $email, string $password): void
{
        Nette\Utils\Validators::assert($email, 'email');
        try {
                $this->database->table(self::TABLE_NAME)->insert([
                        self::COLUMN_NAME => $username,
                        self::COLUMN_PASSWORD => $this->passwords->hash($password),
                        self::COLUMN_EMAIL => $email,
                ]);
        } catch (Nette\Database\UniqueConstraintViolationException $e) {
                throw new DuplicateNameException;
        }
}

Ale když si do formuláře zadám jméno, které mám již v databázi tak to úplně přeskočí ten catch (DuplicateName­Exception) a zase se zaregistruje stejné jméno.. Kde je chyba? :/

Editováno 7.7.2019 13:12
 
Odpovědět
7.7.2019 13:11
Avatar
Odpovídá na Lukáš
Martin Konečný (pavelco1998):7.7.2019 13:39

Ahoj, patrně máš tu exception v jiném namespace.
Např. pokud UserManager je v namespace App\Model, pak danou výjimku máš patrně také tam, tedy App\Model\DuplicateNameException.

No a továrnu na formulář máš patrně jinde, např. v App\Forms, a pokud v ní zachytáváš

catch (DuplicateNameException)

tak se to bude snažit zachytávat výjimku v daném namespace, tedy App\Forms\DuplicateNameException, kterou to pochopitelně nezachytí, jelikož taková se nevyhazuje.

Osobně výjimky řeším tak, že mám pro ně samotný namespace např. App\Exceptions a v souborech, kde výjimky vyhazuji/zachycuji, mám

use App\Exceptions;

v takovém případě poté všude píšu

throw new Exceptions\DuplicateNameException;

catch (Exceptions\DuplicateNameException)

Nestane se mi tedy, že bych omylem zachytával výjimku ve špatném namespace a zároveň mám v kódu přehled o tom, o jakou třídu jde, jelikož v use nepoužívám celou cestu ke třídě, ale jen k jejímu namespace. Tedy pak píšu např.

Entities\User
Facades\UserManager
Exceptions\DuplicateNameException

// atd.

Edit: Ještě taková drobnost - unikátní index ve výchozím stavu neřeší velká a malá písmena, tedy ti půjde registrovat uživatel "Lukáš" i "lukáš", což možná nechceš (závisí na typu aplikace), tak na to dej pozor :D

Editováno 7.7.2019 13:42
Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
Nahoru Odpovědět
7.7.2019 13:39
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na Lukáš
Martin Konečný (pavelco1998):7.7.2019 13:44

I když jsem asi špatně pochopil problém :D Pokud ti to do databáze vloží řádek se stejným jménem, pak patrně vůbec na tom sloupci s 'username' nemáš unikátní index.

Nahoru Odpovědět
7.7.2019 13:44
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Lukáš
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Lukáš:7.7.2019 13:54

Super, díky.. Neměl jsem v databázi přidanej ten unikátní index. :D
A k tomu předchozímu komentu, takže ty si uděláš soubor např. Exceptions a tam dáš

namespace App\Exceptions

a necháš to prázdný nebo tam i nějak zpracováváš ty výjimky?

 
Nahoru Odpovědět
7.7.2019 13:54
Avatar
Odpovídá na Lukáš
Martin Konečný (pavelco1998):7.7.2019 14:13

V namespace App\Exceptions mám jednotlivé výjimky, tzn. 1 soubor = 1 výjimka, kdy to nejčastěji vypadá

namespace App\Exceptions;

class DuplicateNameException extends \RuntimeException
{
}

Jen výjimečně potřebuji ve třídě výjimky něco mít, takže naprostá většina jich jenom dědí a nic víc.
A potom ve třídách, které výjimky používají, to řeším jednoduše

namespace App\Model\Facades;

use Nette;
use App\Exceptions;

class UserManager
{

        public function addUser($data)
        {
                try {
                        $this->db->insert($data);
                } catch (Nette\Database\UniqueConstraintViolationException $e) {
                        throw new Exceptions\DuplicateNameException();
                }
        }

}

namespace App\Forms;

use Nette;
use App\Exceptions;


class RegistrationFormFactory
{

        public function create()
        {
                $form = new Form();
                // ...

                $form->onSuccess[] = array($this, "submitted");

                return $form;
        }


        public function submitted($form, $values)
        {
                try {
                        $this->userManager->addUser($values);
                } catch (Exceptions\DuplicateNameException $e) {
                        $form->addError("Jméno již existuje");
                }
        }

}

Ten kód je jen ukázkový pro představu.

Editováno 7.7.2019 14:14
Nahoru Odpovědět
7.7.2019 14:13
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Lukáš
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Lukáš:7.7.2019 16:58

Dobrá, díky moc a ještě jestli mohu jeden dotaz :-D Když mám formulář s ->addTextArea
a pak to chci dále zpracovávat, tak mi to napíše: Object of class Nette\Forms\Con­trols\TextArea could not be converted to string. Jak to mohu tedy převést do stringu?

 
Nahoru Odpovědět
7.7.2019 16:58
Avatar
Odpovídá na Lukáš
Martin Konečný (pavelco1998):7.7.2019 17:20

Co přesně s tou textarea chceš dělat?

Nahoru Odpovědět
7.7.2019 17:20
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Lukáš
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Lukáš:7.7.2019 17:21

Do text area někdo vloží text a já ho chci rozkouskovat podle svého pomocí preg_split()

 
Nahoru Odpovědět
7.7.2019 17:21
Avatar
Odpovídá na Lukáš
Martin Konečný (pavelco1998):7.7.2019 17:25

A to nejde jednoduše nějak takhle?

public function create()
{
        $form = new Form();
        $form->addTexarea("content", "Obsah");

        return $form;
}

public function formSubmitted(Form $form, $values)
{
        $content = $values->content;
        preg_split(..., $content);
}
Editováno 7.7.2019 17:25
Nahoru Odpovědět
7.7.2019 17:25
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Lukáš
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Lukáš:7.7.2019 18:55

Jop, to funguje. Díky moc za tvůj čas! ;)
Hezký večer.

 
Nahoru Odpovědět
7.7.2019 18:55
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.