Jak nesmazat hodnotu atributu třídy při zavolání onSuccess

rohlenzi
Člen | 12
+
0
-

Ahoj,
chtěl bych se zeptat, jestli jde nějak předat parametrem hodnotu skrze metodu onSuccess. Konkrétně mi tedy jde o to, že při potvrzení druhého formuláře a následném zavoláním metody onSuccess se nejspíš refreshne stránka a já ztratím hodnotu uloženou v $this->reviewId, tudíž nemohu určit do jakého řádku databáze data odeslat.

Algoritmus by měl být takový, že uživatel zadá heslo a díky němu se mu otevře druhý formulář pro napsání recenze, kde následnou recenzi odešle.

<?php

declare(strict_types=1);
namespace App\Presenters;
use Nette;
use Nette\Utils\Random;
use Nette\Application\UI\Form;
use Nette\Database\Explorer;


class ReviewPresenter extends BasePresenter {

    private $reviewId;


    public function createComponentReviewPass(): Form {
        $form = new Form;
        $form->setMethod("GET");
        $form->addText('pass', 'Heslo..')
        ->setRequired();

        $form->addSubmit('send', 'Odeslat');
        $form->onSuccess[] = [$this, 'reviewPassSucceeded'];

        return $form;
    }

    public function reviewPassSucceeded(array $values): void {
        $reviews = $this->database->query('SELECT * FROM review');

        foreach ($reviews as $review)  {
            if ($review->pass == $_GET['pass']) {
                $this->reviewId = $review->ID_r;
                dump($this->reviewId);
                $this->forward('Review:reviewForm');
            }
        }
    }

    public function createComponentReviewForm(): Form {
        $form = new Form;
        $form->addInteger('summary', 'Ohodnoť x z 5 hvězdiček')
        ->setRequired()
        ->addRule($form::RANGE, 'Rozmezí musí být 1 - 5', [1, 5]);
        $form->addText('description', 'Shrnutí recenze..');


        $form->addSubmit('send', 'Odeslat');
        $form->onSuccess[] = [$this, 'reviewSucceeded'];

        return $form;
    }

    public function reviewSucceeded(array $values): void {

        $review = $this->database->query('UPDATE review SET', [
            'summary' => $values['summary'],
            'description' => $values['description']
        ], 'WHERE ID_r = ?', $this->reviewId);

        $this->flashMessage('Recenze byla úspěšně přidána');
        //$this->redirect('Homepage:default');
        dump($this->reviewId);
    }


}
Kamil Valenta
Člen | 758
+
0
-

Není dobré předávat heslo GETem. Odešli ho POSTem a výsledek „odemčení“ si poznač do sessiony.

$reviews = $this->database->query('SELECT * FROM review');
        foreach ($reviews as $review)  {
            if ($review->pass == $_GET['pass']) {

Proč rovnou neděláš v selectu WHERE? Raději budeš procházet milion záznamů, aby sis 1 nechal a zbytek zahodil?

dakur
Člen | 493
+
0
-

@rohlenzi Neznám signatury action/render metod (tj. jaké parametry očekávají), ale myslím, že by mělo stačit předat to $this->reviewId do forward():

$this->forward('Review:reviewForm', ['reviewId' => $this->reviewId]);

forward() je de facto redirect, akorát takový interní bez vnějšího efektu (tj. přesměrování) – potřebuje tedy všechny parametry.

Dále, pokud reviewId není součástí routy, budeš muset ještě do toho druhého formuláře přidat hidden field s reviewId, které si potom v onSuccess vytáhneš:

public function createComponentReviewForm(): Form {
    $form = new Form;
    $form->addInteger('summary', 'Ohodnoť x z 5 hvězdiček')
    ->setRequired()
    ->addRule($form::RANGE, 'Rozmezí musí být 1 - 5', [1, 5]);
    $form->addText('description', 'Shrnutí recenze..');

    $form->addHidden('reviewId', $this->reviewId);

    $form->addSubmit('send', 'Odeslat');
    $form->onSuccess[] = [$this, 'reviewSucceeded'];

    return $form;
}

public function reviewSucceeded(array $values): void {

    $review = $this->database->query('UPDATE review SET', [
        'summary' => $values['summary'],
        'description' => $values['description']
    ], 'WHERE ID_r = ?', $values['reviewId']);

    $this->flashMessage('Recenze byla úspěšně přidána');
    //$this->redirect('Homepage:default');
    dump($values['reviewId']);
}

Jinak s tím heslem má @KamilValenta pravdu – jakmile ho máš v URL, může si ho jednak přečíst kdokoliv, kdo se ti koukne přes rameno, a navíc nezapomeň, že navštívené URL adresy zůstávají v historii prohlížeče.

Editoval dakur (11. 6. 2021 7:24)

Kamil Valenta
Člen | 758
+
0
-

dakur napsal(a):

public function reviewSucceeded(array $values): void {

    $review = $this->database->query('UPDATE review SET', [
        'summary' => $values['summary'],
        'description' => $values['description']
    ], 'WHERE ID_r = ?', $values['reviewId']);

    $this->flashMessage('Recenze byla úspěšně přidána');
    //$this->redirect('Homepage:default');
    dump($values['reviewId']);
}

Tady ještě pozor, ne vždy (ale neznáme širší kontext) je možné / dobré slepě věřit ID z hiddenu. Pokud např. uživatel může hodnotit jen k některým ID (selektováno bylo v předchozím kroku), zde by mělo být ověření, zda to ID pochází z množiny, ke kterým má uživatel přístup. Protože ID v hiddenu se dá snadno podvrhnout…

rohlenzi
Člen | 12
+
+1
-

Dobře, děkuji všem.