jak ošetřit vyjímku v url

tomas_straka
Člen | 32
+
0
-

Ahoj, posilam parametry do metody public function actionEdit(int $postId, int $page): void
Hodnoty jsou z formuláře. Jak osetrit, aby mi uzivatel v url nezmenil $postId na string? Zkousel jsem do tela metody dat try catch, to je blbost. Jde nejak vynutit POST? Diky

Šaman
Člen | 2659
+
0
-

Do actionEdit($postId, $page) ti vždycky může někdo něco podstrčit. Osobně v těchto metodách nemám typovou kontrolu paramterů a v action, nebo render metodě si kontroluji že paramtery mají správný typ a že dávají smysl (třeba že to není neexistující stránka) a že na danou akci má přihlášený uživatel oprávnění.

Edit: Tak koukám, že v novém PHP 7.2 projektu už typovou kontrolu mám. Tam to spadne jako 404 do ErrorPresenteru, tam si můžeš odchytit BadRequestException a nějak to zpracovat po svém. Nebo to prostě nechat jako Page Not Found.

Editoval Šaman (20. 1. 2021 20:13)

tomas_straka
Člen | 32
+
0
-

Ahoj, kod tady

/**
     * @param int $postId
     * @param int $page
     * @throws Nette\Application\AbortException
     */
    public function actionEdit(int $postId, int $page): void
    {
        try {
            $existEntity = $this->companyRepository->getExistCompany($postId);
            if (!$existEntity ) {
                $this->template->flashes = $this->flashMessage("Společnost nebyla upravena.", 'alert-warning ');
                $this->redirect('Company:show');
            }
            $comp= $this->companyRepository->getOneCompany($postId);
            $this['createCompany']->setDefaults($comp->toArray());

        }catch (Exeption $e){
            $this->redirect('Company:show');
            echo('chyba '.$e);
        }
    }
<form n:name=createFirma>
       <div class="form-group row">
           <label for="company" class="col-sm-2 col-form-label">Společnost:</label>
           <div class="col-md-10">
               <input n:name=company type="text" class="form-control" id="nazev">
           </div>
       </div>
       <div class="form-group row">
           <label for="owner" class="col-sm-2 col-form-label">Majitel:</label>
           <div class="col-md-10">
               <input n:name=owner type="text" class="form-control" id="owner">
           </div>
       </div>
       <div class="form-group row">
           <label for="note" class="col-sm-2 col-form-label">Pozn:</label>
           <div class="col-md-10">
               <textarea n:name=notetype="text" class="form-control" id="note" rows="5"></textarea>
           </div>
       </div>
       <div class="form-group row">
           <div class="col-sm-6">
               <button n:name=send type="submit" class="btn btn-primary mb-2">Uložit</button>
           </div>
       </div>
   </form>

Jak muzu kontrolovat typ promenne, kdyz v URL ho zmenim z int na string? To jedine ze bych na to udelal nejaky router.

tomas_straka
Člen | 32
+
0
-

Takze oprava......POST defaultni hodnota formulare i kdyz v neni tag method=„POST“. Nicmene jsem ji tam radeji pridal. Ale to porad neresi tu metodu. v URL http://nette-test-back/company/edit?… Jak se zbavit postId resp. to nejak odchytit?

Kamil Valenta
Člen | 815
+
+1
-

Proč Tě vadí, že někdo v URL přepíše id na string?

$existEntity = $this->companyRepository->getExistCompany($postId);

vrátí false a v podmínce dojde k redirectu, ne? Nebo jak se chová getExistCompany? Vyhodí výjimku?

tomas_straka
Člen | 32
+
0
-

No prave.........nedostane se to do vyjimky. Dostanu hlasku: Nette\Application\BadRequestException #404

Argument $postId passed to App\Presenters\FirmyPresenter::actionEdit() must be int, string given.

Šaman
Člen | 2659
+
+1
-

Opakuji, stejný problém budeš řešit když si někdo ručně přepíše třeba URL /company/show/blbost123 pro routu Company:show, $id. S tím nic nenaděláš.

@KamilValenta Řeší to, že pokud $postId bude blbost123, tak aplikace spadne už při typové kontrole předaného parametru. Tedy že actionEdit očekává jako první parametr int a dostane string.

Jak jsem psal – buď to necháš spadnout do Error Presenteru, nebo zrušíš tu typovou kontrolu v záhlaví funkce.


P.S. David to tady na fóru evidentně nechává spadnout do ErrorPresenteru a nechává tam běžné zpracování chyby. Zkus si v url odstranit to číslo za lomítkem. Versus když ho jen přepíšeš za neexistující, třeba tam přidáš pár devítek na začátek.

Zajímavé je, že do textu zasahovat můžeš – imho je to ukázka chytrého routování. Důležité je evidentně jen to číslo ($id). To další přidá do adresy asi až router jen pro lepší uživatelskou orientaci. Třeba když si to uložíš do záložek, vidíš rovnou název tématu. A při zpracování routy se pak zase zahodí, protože appce stačí vyparsovat jen to id.

Editoval Šaman (20. 1. 2021 22:01)

tomas_straka
Člen | 32
+
0
-

Diky a jak to necham spadnout do error presenteru? Musim pridat routu, ktera se vykona vzdy, kdyz ne ty predchozi?

Šaman
Člen | 2659
+
+1
-

Tam to spadne samo (pokud máš jako základ Sandbox, nebo Nette\web-project). Jen si zkus vypnout laděnku (nasimulovat produkční server).

tomas_straka
Člen | 32
+
0
-

Šaman napsal(a):

Tam to spadne samo (pokud máš jako základ Sandbox, nebo Nette\web-project). Jen si zkus vypnout laděnku (nasimulovat produkční server).

Diky to pomohlo. Pises, ze kontrolujes „správný typ“. Jak to myslis? Ten typ se kontroluje v paramterech metody, ne? Mohl bys mi ukazat nejaky priklad? Diky

Šaman
Člen | 2659
+
0
-

O čem teď mluvíš? Kontrolu typu dělám v případě, že odstraním typy z parametrů handle*, action* nebo render* metody. To může být užitečné, pokud chci nějak víc analyzovat co mi vlastně přišlo a nenechat spadnout presenter do chybové stránky.

Nicméně když jsem teď koukal do kódu nové aplikace, tak už i tady používám striktní typovou kontrolu a tahle ruční tedy je už zbytečná. Nicméně si vzpomínám, že ve výjimečnych případech jsem ji schválně zrušil, abych si mohl i špatně předaný parametr zpracovat sám. Nejspíš to byl nějaký požadavek abych polopaticky uživateli napsal v čem je problém a nevrátil mu jen 404.

/**
 * @param int $id
 */
public function actionEdit($id): void
{
	if ( is_int($id) && $id > 0 ) {
		// mohu se pokusit získat záznam
		// většinou pak ještě kontrola oprávnění
	}
	else {
		// uživatel se snaží podstrčit nějakou blbost
		// ale teď mu mohu třeba zobrazit flashmessage a zůstat na stránce
	}
}

P.S. Mimochodem, pokud používáš php7 typovou kontrolu actionEdit(int $id), tak už není potřeba to mít jako phpDoc anotaci. A dokonce může dojít k nekonzistenci.

Editoval Šaman (22. 1. 2021 17:12)

tomas_straka
Člen | 32
+
0
-

Šaman napsal(a):

O čem teď mluvíš? Kontrolu typu dělám v případě, že odstraním typy z parametrů handle*, action* nebo render* metody. To může být užitečné, pokud chci nějak víc analyzovat co mi vlastně přišlo a nenechat spadnout presenter do chybové stránky.

Nicméně když jsem teď koukal do kódu nové aplikace, tak už i tady používám striktní typovou kontrolu a tahle ruční tedy je už zbytečná. Nicméně si vzpomínám, že ve výjimečnych případech jsem ji schválně zrušil, abych si mohl i špatně předaný parametr zpracovat sám. Nejspíš to byl nějaký požadavek abych polopaticky uživateli napsal v čem je problém a nevrátil mu jen 404.

/**
 * @param int $id
 */
public function actionEdit($id): void
{
	if ( is_int($id) && $id > 0 ) {
		// mohu se pokusit získat záznam
		// většinou pak ještě kontrola oprávnění
	}
	else {
		// uživatel se snaží podstrčit nějakou blbost
		// ale teď mu mohu třeba zobrazit flashmessage a zůstat na stránce
	}
}

P.S. Mimochodem, pokud používáš php7 typovou kontrolu actionEdit(int $id), tak už není potřeba to mít jako phpDoc anotaci. A dokonce může dojít k nekonzistenci.

Díky za vyčerpávající odpověď. Práve mi bylo vyčteno, že jsem ty parametry neošetřil, bohužel jsem z dotyčného nevyrazil jak. Tu anotaci používám, protože mi doplňuje nápovědu při volání metody.

Šaman
Člen | 2659
+
0
-

Tu nápovědu by IDE mělo vzít z definice metody. Ale samozřejmě nějaké starší to neumí, je to v PHP teprve pár let.