Co je to nej řešení? Udělat si službu která bude mít v sobě DAO a požadovaná data se budou získávat pomocí této služby? Nebo si do presenteru/control předat EM a z něj pak získávat vlastní DAO pro jednotlivé entity a využívat tak ty funkce KDYBY\DAO find* atd?

Do teď jsem měl službu fasády která mi potřebná data předávala, jenže to přinášelo tvorbu X metod findByBlaBla když jsem chtěl někde načíst pole enetit a nebo někde jen udělat jednoduché pole pro formulář atd.

Jako správné řešení mi připadá to co popisuješ. Tedy mít fasády a v nich zabalenou veškerou manipulaci s modelem.

Ovšem je to hodně psaní. Já to proto dělám tak, že si předám vždy EM, z něj vytahuju repozitáře, volám nad ním flush atd. A když se logika roztáhne na víc než pár řádků a nebo když by měla být na více místech, tak to zrefaktoruju do fasády.

No veškerou změnu hodnot v DB mám řešeno přes službu manažera abych tam naházel i jednotlivé eventy atd, takže ty fasády mám jen na získávání dat.

Mě se ty fasády taky líbí, co se mě ale nelíbí, nebo resp. zatím nevím jak elegantně řešit ten rostoucí počet metod findBy*

Obecně mám fasády rozděleny na dva typy. Jeden typ má za úkol vytáhnout jen jeden a nebo žáden záznam a druhý typ je na množinu.

Pokud se tahají jednoduchá data tak to findBy* docela jednoduché, ale problém nastane pokud tam chci zapojit více filtrů tak pak bych musel pokrýt vicero kombinací pro findByXYZ, findByAXZ, atd.Částečně používám QueryObject, koukal sem i na tvůj příklad s načítáním postů ale nějak mě nenapadá jak tohle dát rozumně do nějaké fasády?

Leda snad část te logiky co dělá query object duplikovat do té fasády a skládat nějak magicky ten query object v ní?

Dost často píšu ve facade metody typu

public function findBySomething(User $author)
{
    $query = (new ArticlesQuery)
        ->onlyPublished()
        ->byAuthor($author)

   return $this->articles->fetch($query);
}

a zatím mi to nepřipadalo jako problém :) Každopádně, rozdělit facade na víc facades není vůbec špatný nápad, pokud začne moc růst.

Jo takhle nějak to zatím mám taky, ale štvě me když potřebuju nějaké kombinace inCategory, byUser, isPublihsed, někdy chcu všechny tři, někdy jen jednu atd, takže těch findBy* musím udělat více. A tak mě napadlo aby ta fasáda si v konstrutkrou vytvořila tu query, resp. ten query object a přidal by se tam __call co by umožnil té fasádě volat metod toho query objektu?

$articles = $articlesFacade
    ->onlyPublished()
    ->byAuthor($author)
    ->fetch();

$articles = $articlesFacade
    ->onlyPublished()
    ->byAuthor($author)
    ->inCategory($category)
    ->fetch();

No a v té fasádě by to bylo třeba nějak takto:

class ArticlesFacade
{
    function __construct()
    {
        $this->query = (new ArticlesQuery)
    }

    public function fetch()
    {
        $result = $this->dao->fetch($this->query);
        $this->query->clear();

        return $result;
    }

    public function __call($method, $args)
    {
        if (method_exists($this->query, $method)) {
            call_user_func_array(array($this->query, $method), $args);

            return $this;
        }

        return parent::__call($method, $args);
    }
}

takže bych tím odstranil ty find by metody a měl k dispozici fluentní zápis pro filtr/získání dat co?

To se mi nelíbí, protože pak si držíš v té facade stav a to podle mě u facade není dobře.

Raději něco jako

public function query(\Closure $filters = NULL)
{
    $query = new ArticlesQuery();
    if ($filters) { $filters($query); }
    return $this->articles->fetch($query);
}
$result = $facade->query(function (ArticlesQuery $query) use ($author) {
    $query->byAuthor($author);
});

Ale pokud si pěkně napíšeš svůj QueryObject, tak podle mě není nic špatného ani na použití přímo v presenteru, bez té facade.

hmm to máš pravdu. Takže udělat jen metodu query či fetch v té fasádě a předávat ji ten QueryObject?

Přesně tak to dělám.

Fasáda:

class FileSystemFacade extends Facade\BaseFacade
{

    /** @var EntityDao */
    protected $fileDao;

    /**
     * @param EntityManager $em
     */
    function __construct(EntityManager $em)
    {
        parent::__construct($em);

        $this->fileDao = $em->getDao(File::class);
    }

    // ..... další metody obsluhující logiku

    /**
     * @param Folder $folder
     * @param string $name
     * @param string $path
     *
     * @return File
     */
    public function createFile(Folder $folder, $name, $path)
    {
        $file = new File($folder, $name, $path);

        return $this->fileDao->save($file);
    }


    /**
     * @param FileQO $fileQO
     * @param bool   $onlyOne
     *
     * @return File[]|ResultSet|File|NULL
     */
    public function fetchFile($fileQO, $onlyOne = FALSE)
    {
        $resultSet = $this->fileDao->fetch($fileQO);
        if ($onlyOne) {
            return $resultSet->getIterator()->current();
        }

        return $resultSet;
    }
}

Takže ty si v presenteru či kde vytvoříš QueryObject a ten pak předáš fasádě? Taky jsem nad tím takto přemýšlel, timpádem by mě stačila jedna metoda findBy které by se ten QO předal a tím by se vrátilo vše co by bylo potřeba je tak?

J přeně tak, v presenteru vytvořím a nakonfiguruji QO, ten pak předám do fasády, která ho za pomocí Daočka fetchne (viz “fetchFile” metoda výše – findBy je asi lepší pojmenování .-) )


You must first log in to participate in this discussion