NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Výběr pouze potřebných dat z více tabulek ORM

Aktivity
Avatar
Jan Blažek
Tvůrce
Avatar
Jan Blažek:7.7.2017 18:41

Ahojte, chci se zeptat, jestli byste mi někdo dokázal poradit s DQL dotazem.
Mám autentizaci uživatelů, kde se jsou podmínky na 2 vlastnosti z tabulky user a 2 vlastnosti ze settings.
Když jsem se díval na vygenerovaný SQL dotaz, zjistil jsem, že se vybírá zbytečně strašně moc dat. Proto jsem si zkusil napsat kód, který mi vybere pouze to, co doopravdy potřebuji.
UserQuery:

protected $filters = [];

/**
 * @param \Kdyby\Persistence\Queryable $repository
 * @return \Doctrine\ORM\Query|\Doctrine\ORM\QueryBuilder
 */
protected function doCreateQuery(Kdyby\Persistence\Queryable $repository)
{
    $qb = $repository->createQueryBuilder()
    //    ->select('u')
        ->from(User::class, 'u');

    foreach ($this->filters as $filter) $filter($qb);

    return $qb;
}

public function loginUserQuery($username)
{
    $this->filters[] = function (QueryBuilder $qb) use ($username){
        $qb->innerJoin(Ban::class, 'b')
            ->select('u.{username,password}')
            ->addSelect('b.{banUntil, permanent}')
            ->where('u.name = ?', $username)
            ->where('b.user = u');
    };
}

UserFacade:

private function loginUserQuery($username)
{
    $query = new UserQuery();
    $query->loginUserQuery($username);
    return $this->em->getRepository(User::class)->fetch($query);
}

pak v authenticate mám

$user = $this->loginUserQuery($username);

Problém mám v tom, že se mi mi SQL dotaz ani neproběhne a hned dostanu chybovou hlášku
"Cannot read an undeclared property Kdyby\Doctrine\Re­sultSet::$pas­sword."
Mohli byste se mi na ten kód podívat a zkusit ho prosím poupravit?

 
Odpovědět
7.7.2017 18:41
Avatar
d4rkw34v3r
Tvůrce
Avatar
d4rkw34v3r:7.7.2017 19:47

Ahoj, postni sem kód všech Entit, kterých se výběr týká.

 
Nahoru Odpovědět
7.7.2017 19:47
Avatar
Odpovídá na Jan Blažek
Martin Konečný (pavelco1998):7.7.2017 19:47

Ahoj,

nebál bych se klidně vybrat celého uživatele, i když z toho nepotřebuješ doslova všechny sloupce.

protected function doCreateQuery(Kdyby\Persistence\Queryable $repository)
{
    $qb = $repository->createQueryBuilder()
        >select('u')
        ->from(User::class, 'u');

    foreach ($this->filters as $filter) $filter($qb);

    return $qb;
}


public function loginUserQuery($username)
{
    $this->filters[] = function (QueryBuilder $qb) use ($username){
        $qb->innerJoin('u.ban', 'b')
            ->addSelect('b')
            ->where('u.name = ?', $username);
    };
}

Problém nicméně bude nejspíš v tom, že metoda fetch() vrací ResultSet, čili sadu záznamů. Jestli chceš jen jeden konkrétní záznam, pak zvol metodu fetchOne(), viz https://api.kdyby.org/…ository.html#….

Toto by šlo případně i řešit zápisem přímo v DQL:

$user = $this->em->createQuery("
        SELECT user, ban
        FROM App\Model\Entities\User user
        INNER JOIN user.ban ban
        WHERE user.name = :name
")
        ->setParameter("name", $username)
        ->setMaxResults(1)
        ->getOneOrNullResult();

// $user je pak buď instancí App\Model\Entities\User nebo NULL
Editováno 7.7.2017 19:49
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
7.7.2017 19:47
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Jan Blažek
Tvůrce
Avatar
Jan Blažek:7.7.2017 20:12

Ahoj, díky za odpověď. Mohl bych tě poprosit, pokud víš, zvládl bys napsat ten DQL dotaz pomocí PARTIAL, já se o to snažím podle (http://docs.doctrine-project.org/…objects.html#…), ale moc mi to nejde. :/
Nakonec to tedy zvolím i pár dat navíc, ale kdybych se mi to někdy hodilo do budoucna.

 
Nahoru Odpovědět
7.7.2017 20:12
Avatar
Odpovídá na Jan Blažek
Martin Konečný (pavelco1998):7.7.2017 20:15

No mělo by to fungovat tak, že jen vypíšeš seznam atributů. Mám ale pocit, že musíš vybírat i ID, tzn.:

SELECT PARTIAL user.{id, name, password}

Nejsem si tím ale teď 100% jistý. Pokud chceš neúplný objekt, ale jen pár konkrétních údajů, možná by i bylo lepší to nehydratovat na objekt, ale jen na pole.

Nahoru Odpovědět
7.7.2017 20:15
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Jan Blažek
Tvůrce
Avatar
Jan Blažek:7.7.2017 20:37

Dík moc. Funguje :) fakt tam stačilo vybrat navíc i id

Editováno 7.7.2017 20:38
 
Nahoru Odpovědět
7.7.2017 20:37
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 6 zpráv z 6.