Query builder cannot associate with category entity - php

I have 2 entities, MyItem and MyItemCategory. When I try to create a query with query builder I get the following error:
Error: Class App\Entity\MyItem has no
field or association named myitem_category_id (500 Internal Server Error)
This is the where part of my query builder:
$queryBuilder = $this->getDoctrine()
->getRepository('App\Entity\MyItem')
->createQueryBuilder('m');
// adds where for category_id:
$queryBuilder->where('m.myitem_category_id = :category_id')->setParameter('category_id',$category_id);
Here're first entities:
/**
* #ManyToOne(targetEntity="MyItemCategory")
* #JoinColumn(name="myitem_category_id", referencedColumnName="id")
*/
private $myItemCategory;
...and my category entity:
/**
* #ORM\OneToMany(targetEntity="MyItem", mappedBy="myItemCategory")
*/
private $myItemCategories;

The querybuilder actually doesn't care about database fields, but instead uses the object mapper, so there is no field my_item_category_id on your Entity, but instead a field myItemCategory
So, you can either do:
$querybuilder
->where('m.myItemCategory = :category')
->setParameter('category', $category) // <-- an actual MyItemCategory object
or you can join it in and check for the id:
$querybuilder
->leftJoin('m.myItemCategory', 'mic')
->where('mic.id = :micid')
->setParameter('micid', $category_id)
(I actually don't know if m.myItemCategory.id = :micid might work ........ you could try ;o))

Related

Doctrine building querybuilder

I'm trying to make topic / comment system with symfony and I have some question about doctrine's querybuilder.
if I have two entities connected:
/**
* #ORM\ManyToOne(targetEntity="Topicit", inversedBy="comments")
* #ORM\JoinColumn(name="topic_id", referencedColumnName="id")
*/
protected $topicit;
and
/**
* #ORM\OneToMany(targetEntity="Comment", mappedBy="topicit")
*/
protected $comments;
Currently I have builder (getting every column):
$repository = $this -> getDoctrine() -> getRepository('FTFairyBundle:Comment');
$query = $repository->createQueryBuilder('p')
->orderBy('p.topicit', 'ASC')
->getQuery();
$comment = $query ->getResult();
How I make it get only wanted topic_id? Like if I open page with id #1 I wanna get comments connected to that id.
Thanks for your time
You don't need to use query builder for that kind of tasks, you can simply use a getter in your Topicit entity (that of course you need to retrieve from DB)
Something like ->getComments() *(of course that method needs to be defined in Topic class)
Doctrine will take care of load only "consistent" data from your Topic object
Method definition
public getComments()
{
return $this->comments;
}
If you want to query directly you can modify your code as follows
$topicit_id = ... //code to retrieve topicit_id
$repository = $this->getDoctrine()-> getRepository('FTFairyBundle:Comment');
$query = $repository->createQueryBuilder('p')
->where('p.topicit = :topicit_id')
->setParameter('topicit_id', $topicit_id)
->orderBy('p.topicit', 'ASC')
->getQuery();
$comment = $query ->getResult();

Symfony2 and Doctrine: how to sort entity collection by dependant entity field

In my sf2 project I access entity collection by calling:
$user_payment_info_datas = $user->getUserPaymentInfoDatas();
In the User entity there is:
/**
* #ORM\OneToMany(targetEntity="UserPaymentInfoData", mappedBy="user")
* #ORM\OrderBy({"payment_info" = "ASC", "payment_info_data" = "ASC"})
*/
private $user_payment_info_datas;
So it's 1:n relation and user has many UserPaymentInfoData's. However, there is another entity called PaymentInfoData that contains the actually values for UserPaymentInfoData's. So the relation is
User -> UserPaymentInfoData -> PaymentInfoData.
So in terms of annotations in UserPaymentInfoData it is:
/**
* #ORM\ManyToOne(targetEntity="PaymentInfoData", inversedBy="user_payment_info_datas")
* #ORM\JoinColumn(name="payment_info_id", referencedColumnName="id")
* #ORM\OrderBy({"title"="ASC"})
*/
private $payment_info_data;
I need to sort the collection returned by
$user_payment_info_datas = $user->getUserPaymentInfoDatas();
ascending by a field from PaymentInfoData (let's call it 'title') and NOT UserPaymentInfoData.
Can I do this with Doctrine annotations? Or without writing DQL?
I know I can do it with:
$user_payment_info_datas = $em->getRepository('STMainBundle:UserPaymentInfoData')
->createQueryBuilder('upid')
->innerJoin ('upid.payment_info_data', 'pid')
->where('upid.user = :user')
->addOrderBy('upid.payment_info', 'ASC')
->addOrderBy('pid.title', 'ASC')
->setParameter('user', $user)
->getQuery()
->getResult();
but the question is, whether it's possible to stay with only annotations as I need to fix it in a few places and it would be convenient to just change annotations and not create query builder in two places.

Symfony2/Doctrine joined query

I need to create a simple query that produces a result set of a database entry plus the username of the person that posted it.
I've tried to setup the associations properly but I'm not sure if that's right either. I'm finding the whole idea of using these small string identifiers quite confusing. Surely there must be a simpler way of doing a join?
My two entities:
class Users
{
// ...
/**
* #ORM\Column(type="string")
* #ORM\OneToMany(targetEntity="Titles", mappedBy="addedBy")
*/
protected $username;
// ..
}
and
class Titles
{
// ....
/**
* #ORM\Column(type="string")
* #ORM\ManyToOne(targetEntity="Users", inversedBy="username")
*/
protected $addedBy;
// ....
}
with the following in the controller:
$titles = $em->createQueryBuilder()
->select('t.*', 'u.*')
->from('dvdLoggerdvdBundle:Titles', 't')
->leftJoin('t.addedBy', 'u')
->addOrderBy('t.title', 'DESC')
->getQuery()
->getResult();
I'm getting the following error:
[Semantical Error] line 0, col 69 near 'u ORDER BY t.title': Error: Class
dvdLogger\dvdBundle\Entity\Titles has no association named addedBy `
Update 1
I made all the changes suggested by Tom and did lots of reading!
It appears that in order to overcome the lazy loading feature I need to carry out a leftJoin. I have rewritten my query as follows:
public function getAllTitles()
{
// view all records in db
$titles = $this->createQueryBuilder('t')
->select('t, u')
->leftJoin('t.addedBy', 'u')
->addOrderBy('t.title', 'DESC');
return $titles->getQuery()->getResult();
}
I am getting a result set, but the addedBy is returning NULL when I dump the result set. As far as I'm aware shouldn't this pull the associated field in from the other table?
Best practice is to reference the entity by its id, you are trying to reference it using the username. The inversed field should also be a specific field not an existing one that holds data. And keep it mind this field is optional and defines the associations as bidirectional, for the specified use case you don't actually need it as you are joining from the Titles entity. I would advice reading the doc here http://symfony.com/doc/current/book/doctrine.html#entity-relationships-associations as well as here http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html
Bidirectional association (w/ inversed field)
First get rid of that line:
#ORM\Column(type="string")
In your $addedBy annotations and change inverseBy="username" to inversedBy="titles" (note the typo)
You optionaly could add
#ORM\JoinColumn(name="user_id", referencedColumnName="id")
Then in your Users Entity add
/**
*
* #ORM\OneToMany(targetEntity="Titles", mappedBy="addedBy")
*/
protected $titles;
And get rid of
* #ORM\OneToMany(targetEntity="Titles", mappedBy="addedBy")
In your $username annotations
Last make sure you update the database schema
Then your query should return the expected result.
Unidirectional association (w/out inversed field)
Get rid of
* #ORM\OneToMany(targetEntity="Titles", mappedBy="addedBy")
In your $username annotations
Then get rid of that line in your $addedBy annotations:
#ORM\Column(type="string")
As well as inverseBy="username"
You optionaly could add
#ORM\JoinColumn(name="user_id", referencedColumnName="id")
Last make sure you update the database schema
Then your query should return the expected result.

Symfony2 error while display entity related ManyToOne

I am trying to display a "CategorieActivite" in an activite.html twig page.
I have 2 entities. The first one is Activite. The second one is CategorieActivite.
I have put annotations in the Activite.
I have prepared my query with join in ActiviteRepository.
It's ok in my database (foreign key).
BUT i get this error :
Method "CategorieActivite" for object "AssoFranceRussie\MainBundle\Entity\Activite" does not exist in (in my twig page)
Do I have to do something else to get some entity data from another entity?
Thanks
EB
The code :
class Activite
{
// $categorieActiviteId lié à l'entité CategorieActivite
// ManyToOne
/**
* #ORM\ManyToOne(targetEntity="AssoFranceRussie\MainBundle\Entity\CategorieActivite")
* #ORM\JoinColumn(name="categorie_activite_id", referencedColumnName="id")
*/
private $categorieActiviteId;
...
}
ActiviteRepository :
public function getAllActivites()
{
$query = $this->getEntityManager()->createQuery(
'SELECT a,c,n
FROM AssoFranceRussieMainBundle:Activite a
JOIN a.categorieActiviteId c
JOIN a.niveauActiviteId n
ORDER BY a.nom ASC '
);
return $query->getResult();
}
And in the twig html:
<p><strong>{{activite.CategorieActivite.libelle}}</strong></p>
You should create getter for $categorieActiviteId property.
So in Activite class you should have
public function getCategorieActivite() {
return $this->categorieActiviteId;
}
and in twig you should have:
<p><strong>{{activite.getCategorieActivite.libelle}}</strong></p>
Dont forget libelle have to be public method or property
Thank you for your help. It works now.
Actually i had already the getter with annotation in the class Activite. So, I should have write in twig {{activite.categorieActiviteId.libelle}} instead of {{activite.categorieActivite.libelle}}. The 2 ways to access the data work.
the getter in Activite class:
/**
* Get categorieActiviteId
*
* #return \AssoFranceRussie\MainBundle\Entity\CategorieActivite
*/
public function getCategorieActiviteId()
{
return $this->categorieActiviteId;
}

using querybuilder and DQL to pull specific attributes of entity

I have the following query:
$query = $em->createQueryBuilder()->select('p.id, p.name, p.price, p.cover')
->from("SiteMainBundle:Product", 'p')
->innerJoin('p.category', 'c')
->innerJoin('p.shop', 'shop')
;
And inside my product entity the cover is actually another entity, which looks like this:
/**
* #Accessor(getter="getCover")
*/
private $cover;
public function getCover()
{
if($this->pictures->count() > 0) {
return $this->pictures[0];
}
return new ProductPicture();
}
However when I do this it gives me an error:
"[Semantical Error] line 0, col 32 near 'cover FROM SiteMainBundle:Product': Error: Class Site\\MainBundle\\Entity\\Product has no field or association named cover"
I know this is because it is declared as private, but can I call the method getCover from the query builder?
If you want to load only specific fields, instead of the whole entity, you need to use the partial object syntax:
$em->createQueryBuilder()->select('p.{id,name,price,cover}')
This will select only the 4 specific columns you want.
It's not because of private visibility, but because cover is not defined as an entity field.
/**
* #ORM\Column(type="string")
*
* #Accessor(getter="getCover")
*/
private $cover;

Categories