Jak řešit chybějící parametr konstruktoru subkomponenty

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
darkweaver
Člen | 18
+
0
-

Zdravím,

měl bych tu dotaz ohledně komponent. Nejprve se pokusím přiblížit, oč se to vlastně snažím než přejdu ke kódu.

Dělám jednoduchý přehled sportovišť a jejich rezervací. Komponent tu mám více, ale zajímalo by mě, jak řešíte takovouto situaci:

Presenter

class ReservationPresenter extends Presenter
{
    public function action()
    {
    }


    public function render()
    {
    }


    protected function createComponentSportsFieldsOverview()
    {
        $comp = $this->sportsFieldsOverviewFactory
                     ->create(
                         (new SportsFieldQuery())
                         ->notFrozen()
                         ->indexById()
                     );

        return $comp;
    }
}

Komponenta pro přehled sportovišť

class SportsFieldsOverviewControl extends Control
{
    /** @var ISportsFieldRowFactory */
    private $sportsFieldRowFactory;

    /** @var SportsFieldsFacade */
    private $sportsFieldsFacade;

    /** @var SportsFieldQuery */
    private $sportsFieldQuery;

    /** @var SportsField[] */
    private $sportsFields;


    public function __construct(
        SportsFieldQuery $query,
        SportsFieldsFacade $sportsFieldsFacade,
        ISportsFieldRowFactory $sportsFieldRowFactory
    ) {
        $this->sportsFieldQuery = $query;
        $this->sportsFieldsFacade = $sportsFieldsFacade;
        $this->sportsFieldRowFactory = $sportsFieldRowFactory;
    }


    public function render()
    {
        $template = $this->getTemplate();

        if ($this->sportsFields === null) {
            $this->sportsFields = $this->sportsFieldsFacade
                                       ->findSportsFields($this->sportsFieldQuery)->toArray();
        }
        $template->sportsFields = $this->sportsFields;


        return $template->render();
    }


    protected function createComponentSportsFieldRow()
    {
        return new Multiplier(function ($sportsFieldId) {
            if ($this->sportsFields === null) {
                $this->sportsFields[$sportsFieldId] = $this->sportsFieldsFacade->getSportsFieldById($sportsFieldId);
                // volá se pouze pokud se jedná o zpracování signálu z komponenty SportsFieldRow (i ajaxem)
                // Jak řešit situaci, kdy sportoviště se $sportsFieldId neexistuje?
            }

            // tady vznikne chyba, pokud se dané sportoviště nenajde
            $comp = $this->sportsFieldRowFactory->create($this->sportsFields[$sportsFieldId]);

            return $comp;
        });
    }

}

A poslední komponenta, ve které se pak zobrazují rezervace apod.

class SportsFieldRow extends Control
{
    /** @var SportsField */
    private $sportsField;


    public function __construct(SportsField $sportsField)
    {
        $this->sportsField = $sportsField;
    }
}

V podstatě jde o to, že když se snažim zpracovat nějaký signál z komponenty SportsFieldRow, ajaxem nebo bez, tak se zavolá onen if blok:

if ($this->sportsFields === null) {
    $this->sportsFields[$sportsFieldId] = $this->sportsFieldsFacade->getSportsFieldById($sportsFieldId);
    // volá se pouze pokud se jedná o zpracování signálu z komponenty SportsFieldRow (i ajaxem)
    // Jak řešit situaci, kdy sportoviště se $sportsFieldId neexistuje?
}

Property $this->sportsFields je null, protože se plní až v render metodě, kde se opět kontroluje, zda-li je null.

A tady se nachází onen problém, když nenaleznu sportoviště s daným ID, tak do vytvářené komponenty místo objektu SportsField předávám NULL.

Jde nějak v tomto místě, nebo nějak jinak zastavit vytváření komponenty SportsFieldRow?

Chtěl bych v tomto případě prostě zobrazit text, že prováděnou akci nejde dokončit z důvodu chybějícího sportoviště.

Snad jsem popsal dobře, oč mi jde :-))

Mnohokrát děkuji za odpovědi a přeji krásný den.

David Matějka
Moderator | 6445
+
0
-

ja vetsinou vyhazuju klasicky badrequest exception, takze to ukaze 404

darkweaver
Člen | 18
+
0
-

Tady se jedná o intranetovou aplikaci a zadávání rezervace se děje v modálním okně a celé je to ajaxové. Přes to modální okno se uživatel prokliká až k samotné rezervaci, protože se tam vybírá, zda-li chce vytvořit rezervaci na novou účtenku, nebo již existujíci otevřenou apod.

Proto bych spíš potřeboval, aby, když dojde k této situaci na jakékoliv úrovni, tak abych mohl nějak ukončit celou tu kaskádu vytváření komponent a zobrazit prostou hlášku, která se objeví v tom modálním okně.

Je dost možné, že na to jdu špatně a mělo by se to řešit trochu jinak, ale vůbec mě nenapadá jak :(

CZechBoY
Člen | 3608
+
0
-

jak psal David… throw exception + try-catch někde v createComponentXXX v presenteru

Editoval CZechBoY (28. 8. 2016 20:18)

Martk
Člen | 652
+
0
-

@darkweaver Můžeš zveřejnit prosím i šablonu komponenty?

darkweaver
Člen | 18
+
0
-

@Antik Ahoj, tady přikládám odkaz na gist

V podstatě je tam komponenta pro přehled sportovišť, která obsahuje komponentu pro vykreslení každého sportoviště. V každém řádku je seznam hodin jako odkaz a po kliknutí na odkaz se spustí modální okno a ajaxem se natáhne komponenta, přes kterou se poté uživatel prokliká až k rezervaci.

V kódu, co jsem poslal už je to vyřešený, ale asi ne moc pěkně.

Zkoušel jsem vyhazovat vlastní vyjímku a chytat ji v presenteru, ale pokaždé to na té vyjímce umřelo, nedostalo se to ke catch bloku v presenteru.

Nakonec jsem to vyřešil tak, že můžu do konstruktoru komponenty vložit jak objekt SportsField, tak NULL a potom s tím dál v kódu pracuju, aby se zobrazila konkrétní hláška a zároveň se i updatovala tabulka sportovišť na pozadí. Řešení asi nic moc, ale funguje :-))

// edit link na gist, zapoměl jsem tam dát šablonu a jednu komponentu

Editoval darkweaver (29. 8. 2016 15:35)