Doctrine a počet čtenářů článku
- Fyasko
- Člen | 106
Ahoj opět se obracím na znalé. Snažím se Z doctrine vytáhnout ke každému článku počet čtenářů kvůli řazení, ale druhý den se nedaří.
Takto vypadá Entita pro články
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Kdyby\Doctrine;
/**
* @ORM\Entity
* @ORM\Table(name="articles")
*
*/
class Article extends Doctrine\Entities\BaseEntity
{
use Doctrine\Entities\Attributes\Identifier;
/**
* @ORM\OneToMany(targetEntity="Reader", mappedBy="article", orphanRemoval=true, cascade={"persist", "remove"})
*/
public $readers;
public function __construct()
{
$this->readers = new ArrayCollection();
}
....
?>
Toto je entita která ukládá unikátní čtenáře
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Kdyby\Doctrine;
/**
* @ORM\Entity
* @ORM\Table(name="readers")
*
*/
class Reader extends Doctrine\Entities\BaseEntity
{
use Doctrine\Entities\Attributes\Identifier;
/**
* @ORM\ManyToOne(targetEntity="Article", inversedBy="readers")
* @ORM\JoinColumn(name="id_article", referencedColumnName="id")
*/
public $id_article;
/** @ORM\Column(type="string", length=200) */
public $ip;
....
?>
Toto je dotaz kterým se snažím získat výsledek
<?php
return new ResultSet($this->repository->createQuery("
SELECT a, COUNT(b.id) // zkoušel jsem COUNT(b), COUNT(b.id_article)
FROM App\Entity\Article a
JOIN a.readers b));
?>
Když řadím podle autora, který je ManyToOne tak je vše v pořádku, ale mě se nedaří ani vytáhnout ty čísla, natož řadit(ale to už by bylo vpho).
Laděnka hlásí
Undefined index: article
Všem budu vděčný za jakékoliv reakce. Předem díky.
- chap
- Člen | 81
neměl by jsi mít toto? … vlastnost id_article predelat na article = reference na Article zvlast to ID
/**
* @var integer
*
* @ORM\Column(name="id_article", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id_article;
/**
* @ORM\ManyToOne(targetEntity="Article", inversedBy="readers")
* @ORM\JoinColumn(name="id_article", referencedColumnName="id")
*/
public $article;
- chap
- Člen | 81
Ted koukam, ze tam mas
use Doctrine\Entities\Attributes\Identifier;
, který přidává
sloupec ID tkaže asi jen toto:
/**
* @ORM\ManyToOne(targetEntity="Article", inversedBy="readers")
* @ORM\JoinColumn(name="id_article", referencedColumnName="id")
*/
public $article;
Smazal jsi cache? co píše konzole
php index.php orm:validate-schema
- Martk
- Člen | 661
Máš špatně mapující položku:
targetEntity="Reader", mappedBy="article", orphanRemoval=true, cascade={"persist", "remove"}
Ale v entitě Reader se nenachází žádná položka s názvem article,
proto to hlásí undefined index article
Správně je:
targetEntity="Reader", mappedBy="id_article", orphanRemoval=true, cascade={"persist", "remove"}
Tento řádek se dá vynechat (nepíšu, že to je špatně, můžeš to tam
nechat):
@ORM\JoinColumn(name="id_article", referencedColumnName="id")
- Fyasko
- Člen | 106
Pokud přidám tento sloupec do entity Article, tak se mi v tabulce „articles“ vytvoří sloupec který tam být nemá. Pokud bylo myšleno dát ho do entity Reader, tak sloupec který tam již je $id_article, je identický .Ta vazba v db funguje správně, takže to opět zase asi špatně chápu :)
Validate vypisuje toto:
<?php
[Mapping] FAIL - The entity-class 'App\Entity\Article' mapping is invalid:
* The association App\Entity\Article#user refers to the inverse side field App\Entity\User#articles which does not exist.
[Mapping] FAIL - The entity-class 'App\Entity\Group' mapping is invalid:
* The mappings App\Entity\Group#group and App\Entity\User#group are inconsistent with each other.
[Mapping] FAIL - The entity-class 'App\Entity\User' mapping is invalid:
* The mappings App\Entity\User#user and App\Entity\Article#user are inconsistent with each other.
* The association App\Entity\User#group refers to the inverse side field App\Entity\Group#users which does not exist.
* The association App\Entity\User#group2 refers to the inverse side field App\Entity\Group#users which does not exist.
[Database] OK - The database schema is in sync with the mapping files.
?>
Takže mapování na Reader by mělo být asi dobře ne? .. A ano cache jsem mazal :)
chap napsal(a):
Ted koukam, ze tam mas
use Doctrine\Entities\Attributes\Identifier;
, který přidává sloupec ID tkaže asi jen toto:/** * @ORM\ManyToOne(targetEntity="Article", inversedBy="readers") * @ORM\JoinColumn(name="id_article", referencedColumnName="id") */ public $article;
Smazal jsi cache? co píše konzole
php index.php orm:validate-schema
- Fyasko
- Člen | 106
Tak jo, pohli jsme se dopředu :) . Nyní už mu nevadí index, ale pro jistotu nevrátí vůbec nic :D
Trying to get property of non-object
Antik napsal(a):
Máš špatně mapující položku:
targetEntity="Reader", mappedBy="article", orphanRemoval=true, cascade={"persist", "remove"}
Ale v entitě Reader se nenachází žádná položka s názvem article, proto to hlásí undefined index article
Správně je:
targetEntity="Reader", mappedBy="id_article", orphanRemoval=true, cascade={"persist", "remove"}
Tento řádek se dá vynechat (nepíšu, že to je špatně, můžeš to tam nechat):
@ORM\JoinColumn(name="id_article", referencedColumnName="id")
- Fyasko
- Člen | 106
Dotáhl jsem to validování na stav níže pro jistotu a najednou mi na dql,
který je výše vyskočil počet záznamů správně. Poté jsem v šabloně
vypsal {count($article->readers)} a zdá se, že to vypisuje správná data.
Jen by mě zajímalo proč mu vadí ten COUNT už v dotazu?
[Mapping] OK – The mapping files are correct.
[Database] OK – The database schema is in sync with the mapping files.
Edit:
proměmnná {count($article->readers)} je funkční ikdyž ten JOIN vůbec
nepoužiju.
Editoval Fyasko (23. 3. 2016 14:20)
- leninzprahy
- Člen | 150
Fyasko napsal(a):
Dotáhl jsem to validování na stav níže pro jistotu a najednou mi na dql, který je výše vyskočil počet záznamů správně. Poté jsem v šabloně vypsal {count($article->readers)} a zdá se, že to vypisuje správná data. Jen by mě zajímalo proč mu vadí ten COUNT už v dotazu?
[Mapping] OK – The mapping files are correct.
[Database] OK – The database schema is in sync with the mapping files.Edit:
proměmnná {count($article->readers)} je funkční ikdyž ten JOIN vůbec nepoužiju.
Jen pro pořádek, mappedBy="xy"
odkazuje na property
$xy
, pokud se má sloupec v databázi jmenovat jinak, je potřeba
to definovat @ORM\JoinColumn(name="xyz" ...)
COUNT()
v sekci SELECT
mu vadí, protože ho
nemůže namapovat do žádné entity.
{count($article->readers)}
by mělo fungovat vždy, jen když
bude v dotazu JOIN
, vytáhnou se všechny záznamy jedním
dotazem, pokud tam nebude, položí se nejprve jeden dotaz na všechny články,
a pak ke každému článku jeden dotaz na jeho readers.
- Fyasko
- Člen | 106
Pravda, pomocí {count($article->readers)} se ptá na každý článek
zvlášť kolik má čtenářů.
To mappedBy jsem myslím už pochopil(snad :) ). Díky tomu jsem odstranil chyby
v tom mapování.
Dobře, tak pokud ho nemůže namapovat do žádné entity, jak docílím
toho aby mohl?
Entity jsou nahoře ukázané obě.
- leninzprahy
- Člen | 150
Fyasko napsal(a):
Ve finále mi jde vlastně o to, zobrazit např. 20 nejčtenějších článků. Řazení je už jen podle sloupců v entitě Article
Zkusil bych něco jako:
SELECT a, COUNT(b) AS HIDDEN cnt
FROM App\Entity\Article a
JOIN a.readers b
ODER BY cnt DESC
- Oli
- Člen | 1215
Pokud to chceš jen kvůli tomu řazení, tak si myslím, že ta bi-directional vazba je zbytečná. Píšu z hlavy, ale myslím, že by mohlo jít něco jako
$this->repository->createQueryBuilder()
->select('a, COUNT(r.id) AS readers')
->from(Reader::class, 'r')
->join('r.article_id', 'a')
->orderBy('readers', 'ASC')
- Fyasko
- Člen | 106
Když přidám HIDDEN, tak to projde, ale já bych raději abych byl navedenen na důvod proč to nejede. Toto není jediný případ využití na webu a potřeboval bych pomoc s tím abych mi COUNT fungovalo i bez HIDDEN
leninzprahy napsal(a):
Fyasko napsal(a):
Ve finále mi jde vlastně o to, zobrazit např. 20 nejčtenějších článků. Řazení je už jen podle sloupců v entitě Article
Zkusil bych něco jako:
SELECT a, COUNT(b) AS HIDDEN cnt FROM App\Entity\Article a JOIN a.readers b ODER BY cnt DESC
- leninzprahy
- Člen | 150
Tím HIDDEN
říkáš, že tě to ve výsledku nezajímá,
Doctrine se tento sloupec nesnaží namapovat do výsledné entity…
Fyasko napsal(a):
Když přidám HIDDEN, tak to projde, ale já bych raději abych byl navedenen na důvod proč to nejede. Toto není jediný případ využití na webu a potřeboval bych pomoc s tím abych mi COUNT fungovalo i bez HIDDEN
leninzprahy napsal(a):
Fyasko napsal(a):
Ve finále mi jde vlastně o to, zobrazit např. 20 nejčtenějších článků. Řazení je už jen podle sloupců v entitě Article
Zkusil bych něco jako:
SELECT a, COUNT(b) AS HIDDEN cnt FROM App\Entity\Article a JOIN a.readers b ODER BY cnt DESC
- Fyasko
- Člen | 106
Tomu rozumím, ale furt to není to, čeho bych rád dosáhl(naučil se). Potřeboval bych pochopit proč mi to nechce spočítat už v dql. To je v podstatě to podstatné.
leninzprahy napsal(a):
Tím
HIDDEN
říkáš, že tě to ve výsledku nezajímá, Doctrine se tento sloupec nesnaží namapovat do výsledné entity…Fyasko napsal(a):
Když přidám HIDDEN, tak to projde, ale já bych raději abych byl navedenen na důvod proč to nejede. Toto není jediný případ využití na webu a potřeboval bych pomoc s tím abych mi COUNT fungovalo i bez HIDDEN
leninzprahy napsal(a):
Fyasko napsal(a):
Ve finále mi jde vlastně o to, zobrazit např. 20 nejčtenějších článků. Řazení je už jen podle sloupců v entitě Article
Zkusil bych něco jako:
SELECT a, COUNT(b) AS HIDDEN cnt FROM App\Entity\Article a JOIN a.readers b ODER BY cnt DESC
- leninzprahy
- Člen | 150
Asi stále úplně nerozumím, čemu nerozumíš, čeho chceš dosáhnout
:)
Ono to v tom DQL spočítá, a pak to podle toho výsledek seřadí, jen se to
nedostane do toho výsledku.
Zkus si prostudovat DQL SELECT Examples kde je to celkem hezky popsáno.
Pokud v tom výsledku ty počty chceš, stačí klíčové slovo
HIDDEN
smazat, jen výsledkem už nebude pole entit, ale pole
polí, něco jako
[
0 => [
0 => Article,
cnt => 10
],
1 => [
0 => Article,
cnt => 8
],
...
]
ale to mi přijde zbytečné, protože k tomu počtu se dostaneš z entity
Article count($article->readers);
nebo si můžeš
dopsat metodu
class Article {
...
/** @return int */
public function getReadersCount() {
return count($this->readers);
}
...
}
Mimochodem, jako verzi Doctrine používáš?
Fyasko napsal(a):
Tomu rozumím, ale furt to není to, čeho bych rád dosáhl(naučil se). Potřeboval bych pochopit proč mi to nechce spočítat už v dql. To je v podstatě to podstatné.
leninzprahy napsal(a):
Tím
HIDDEN
říkáš, že tě to ve výsledku nezajímá, Doctrine se tento sloupec nesnaží namapovat do výsledné entity…Fyasko napsal(a):
Když přidám HIDDEN, tak to projde, ale já bych raději abych byl navedenen na důvod proč to nejede. Toto není jediný případ využití na webu a potřeboval bych pomoc s tím abych mi COUNT fungovalo i bez HIDDEN
leninzprahy napsal(a):
Fyasko napsal(a):
Ve finále mi jde vlastně o to, zobrazit např. 20 nejčtenějších článků. Řazení je už jen podle sloupců v entitě Article
Zkusil bych něco jako:
SELECT a, COUNT(b) AS HIDDEN cnt FROM App\Entity\Article a JOIN a.readers b ODER BY cnt DESC
- Fyasko
- Člen | 106
Používám verzi „kdyby/doctrine“: „^3.0“. No původní účel byl pouze najít např 10 nejčtenějších článků, ale z hlavy vymyslím dalších xy případů, kdy se ten COUNT hodí vytáhnout už v dotazu. Proto bych rád došel řešení proč to nejde :)
Btw pokud použiju
SELECT a, COUNT(b) AS HIDDEN cnt FROM App\Entity\Article a JOIN a.readers b ORDER BY cnt DESC
výsledek vrátí pouze jeden článek a to ten nejčtenější.
Editoval Fyasko (24. 3. 2016 23:02)
- leninzprahy
- Člen | 150
Koukám, že ty ten výsledek obaluješ ještě třídou
ResultSet
která nevím co přesně dělá, ale když si to
vytáhneš:
$res = $this->repository->createQuery("
SELECT a, COUNT(b) AS cnt
FROM App\Entity\Article a
JOIN a.readers b
ODER BY cnt DESC")->getResult();
mělo by to $res
obsahovat pole
[
0 => [
0 => Article,
cnt => 10
],
1 => [
0 => Article,
cnt => 8
],
...
]
Fyasko napsal(a):
Používám verzi „kdyby/doctrine“: „^3.0“. No původní účel byl pouze najít např 10 nejčtenějších článků, ale z hlavy vymyslím dalších xy případů, kdy se ten COUNT hodí vytáhnout už v dotazu. Proto bych rád došel řešení proč to nejde :)
Btw pokud použiju
SELECT a, COUNT(b) AS HIDDEN cnt FROM App\Entity\Article a JOIN a.readers b ORDER BY cnt DESC
výsledek vrátí pouze jeden článek a to ten nejčtenější.
Editoval leninzprahy (29. 3. 2016 13:09)