JMSSerializer and inheritance Class - php

I have got a problem with JMS Serializer and inheritance class. When I serialize my entities it doesn't take care of JMSSerializer Annotation because of inheritance class... So How could I set JMSSerializer Annocation with class inheritance ?
Example :
/**
* Class Category
*
* #Serializer\ExclusionPolicy("all")
*/
class Category extends BaseCategory
{
/**
* #var integer $id
*
* #Serializer\Expose
*/
protected $id;
}
/**
* Class BaseCategory
*/
class BaseCategory
{
/**
* #var Dish
*/
protected $dishs;
/**
* #var string
*/
protected $name;
}
When I serialize Category, the json returned looks like :[{"dishs":[{"name":"Salade","id":5}],"name":"...","id":1}]. The ExclusionPolicy annotation is not applied.
Do you have any ideas why ? If I set all fields in the same entity, it works good, but it breaks all my template ...
Thanks

You inherit from BaseCategory - you cannot expect this to work.
Set your ExclusionPolicy in your base class - in this case your extended class will inherit from BaseCategory.

Related

Doctrine criteria on subclasses of abstract entity

I have an abstract entity which is inherited by two subclasses. I'm using it in association with other entity and now I want to create criteria to filter out objects with the property set to some value.
My superclass:
/**
* #ORM\MappedSuperclass
* #ORM\Entity(repositoryClass="Foo\Bar\AddressRepository")
* #ORM\InheritanceType(value="SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="discriminator_type", type="string")
* #ORM\DiscriminatorMap({"homeaddress" = "HomeAddress", "companyaddress" = "CompanyAddress"})
*/
abstract class AbstractAddress
{
/**
* #var bool
* #ORM\Column(type="boolean", options={"default": 0})
*/
protected $active;
}
Subclasses:
/**
* #ORM\Entity(repositoryClass="Foo\Bar\AddressRepository")
*/
class HomeAddress extends AbstractAddress
{
}
/**
* #ORM\Entity(repositoryClass="Foo\Bar\AddressRepository")
*/
class CompanyAddress extends AbstractAddress
{
}
Entity with association:
/**
* #ORM\Entity(repositoryClass="Foo\Bar\CustomerRepository")
*/
class Customer
{
/**
* #var ArrayCollection
* #ORM\ManyToMany(targetEntity="Foo\Bar\AbstractAddress", cascade={"all"}, orphanRemoval=true)
*/
private $addresses;
/**
* #return Collection|null
*/
public function getAddresses(): ?Collection
{
return $this->addresses->matching(
Criteria::create()->where(Criteria::expr()->eq('active', true))
);
}
}
This setup produces exception:
ResultSetMapping builder does not currently support your inheritance scheme.
The problem is that it tries to instantiate AbstractAddress instead of one of the subclasses respectively.
Is there any way to achieve this filtering using Criteria API?
I know that I can use filter() instead, but this function doesn't impact SQL query, so I would rather have this solved used criteria.

Symfony doctrine many to many unique

I have to entity with manyToMany relation, that i have transform in two OneToMany. So I have create an other Entity called CollanaCollezionista into that i have some attribute.
I want that the couple collana/collezionista is unique, how can i do this on doctrine and symfony?
/**
* Collana
*/
class Collana
{
private $id;
private $titolo;
/**
* #MaxDepth(1)
* #ORM\OneToMany(targetEntity="CollezionistaCollana", mappedBy="collana")
*/
private $collezionisti;
}
/**
* Collezionista
*/
class Collezionista
{
private $id;
private $user;
/**
* #ORM\OneToMany(targetEntity="CollezionistaCollana", mappedBy="collezionista")
*/
private $collane;
}
So I have an other entity, called CollezionistaCollana. How can i set that the couple collezionista-collana is unique?
Answer:
#UniqueConstraint do the stuff.
use Doctrine\ORM\Mapping\UniqueConstraint as UniqueConstraint;
/**
* CollezionistaCollana
*
* #ORM\Table(name="collezionista_collana",uniqueConstraints={#‌UniqueConstraint(nam‌​e="unique_hold", columns={"idCollezionista", "idCollana"})})
* #ORM\Entity
*/
class CollezionistaCollana
{
// Class details
}

Symfony2 - extending entities, abstract entity

I have 2 entities with the same fields - parent, children, order. Actually it is a mechanism and this 3 fields not applicable to content of this entity - like name, title, category etc.
I want to set this fields to one place, one class and I'm considering where should I put it. Should it be an abstract class? Or should I make a trait?
I also can use ORM\Discriminator mechanism, but I think this is for something else, not for that what I want to do.
i would make an abstract class with doctrines #MappedSuperClass annotation and shared fields and the entities extend them
here is an example with a shared created_at field
namespace Your\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\MappedSuperclass;
/**
* Abstract base class to be extended by my entity classes with same fields
*
* #MappedSuperclass
*/
abstract class AbstractEntity {
/**
* #var integer
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* Get id
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Get createdAt
* #return \DateTime
*/
public function getCreatedAt() {
return $this->createdAt;
}
/**
* Set createdAt
*
* #param \DateTime $createdAt
*
* #return AbstractEntity
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
}
your entities both extend this class like:
class YourEntityClass extends AbstractEntity
{
in YourEntityClass the $id property must be "protected"
I had that issue some time ago. I also wanted to have nice abstraction for entities (or value objects, whatever) just to be a little lazy. But It is not the good way IMHO.
What if name from one entity has to have other length than the other? What if you want to add new field, add it to one entity, and some time later you wanted it in the other entity, but you forget to move it to abstraction?
I think entity is such autonomic thing that it is pointless and confusing to move some part of it to the abstraction.
Remember about KISS principle.

Doctrine 2 relationship is not working

I have Item entity:
/**
* Item
*
* #ORM\Table(name="item")
* #ORM\Entity
*/
class Item {
...
/**
* #var Unit
* #ORM\Column(name="unitId", type="integer")
* #ORM\ManyToOne(targetEntity="Unit", inversedBy="items")
* #ORM\JoinColumn(name="unitId", referencedColumnName="id")
*/
private $unit;
...
}
And Unit entity:
/**
* Unit
*
* #ORM\Table(name="unit")
* #ORM\Entity
*/
class Unit {
...
/**
* #var Item[]
* #ORM\OneToMany(targetEntity="Item", mappedBy="unit")
*/
private $items;
...
}
And a code like:
$item = $this->objectManager->getRepository('Application\Main\Entity\Item')->find($id);
$unitName = $item->getUnit()->getName();
Which produces error Fatal error: Call to a member function getName() on a non-object, what means that doctrine handles this field as simple field, not a relation field. What should I do to force Doctrine to use this field as a relationship? I have few entities with such issue, while other are working just fine. What is the reason?
vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDrive.php, lines 262-263:
// Field can only be annotated with one of:
// #Column, #OneToOne, #OneToMany, #ManyToOne, #ManyToMany
So, it seems that you cannot use relation annotations when using #Column and visa versa. I had to remove #Column annotation and add #JoinColumn annotation and it started to work as expected.

How to relate entities in Symfony 2 and Doctrine?

How can i create a relationship between entities with Symfony 2 and Doctrine? I'm only able to create standalone entities. Maybe someone can help me figure this out using the entity generator? I want to:
Create two entities: Post and Category. A Post is part of a Category.
Create a Tag entity: A Post can have many Tags.
A practical example is covered in Symfony2 docs here:
http://symfony.com/doc/current/book/doctrine.html#entity-relationships-associations
To elaborate, taking the first example, you need to create a OneToMany relationship between your Category object and your Post object:
Category.php:
<?php
namespace Your\CustomBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Table(name="category")
* #ORM\Entity()
*/
class Category
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Post", mappedBy="category")
*/
public $posts;
/**
* Constructor
*/
public function __construct()
{
$this->posts = new ArrayCollection();
}
/**
* #return integer
*/
public function getId()
{
return $this->id;
}
}
Post.php
<?php
namespace Your\CustomBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="post")
* #ORM\Entity()
*/
class Post
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="posts")
*/
public $category;
/**
* #return integer
*/
public function getId()
{
return $this->id;
}
}
This should get you started. I've just written this so there might be errors :s
I'm making properties $posts and $category public here for brevity; however you'd probably be advised to make these private and add setters/getters to your classes.
Also note that $posts is an array-like Doctrine ArrayObject class especially for arrgregating entities, with methods like $category->posts->add($post) etc.
For more detail look into association mapping in the Doctrine documentation. You'll probably need to set up a ManyToMany relationship between Posts and Tags.
Hope this helps :)
You don't create the relationships with the entity generator itself.
Once the entity classes themselves exist (created either with the entity generator or written by hand), you then edit them to add the relationships.
For example, with your Post having many Tags example
namespace Your\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Your\Bundle\Entity\Post
*
* #ORM\Table(name="post")
* #ORM\Entity
*/
class Post
{
/**
* #var \Doctrine\ORM\PersistentCollection
*
* #ORM\OneToMany(targetEntity="Tag", mappedBy="post", cascade={"persist"})
*/
private $tags;
}
See Doctrine's Documentation for more information about specifying relationships.

Categories