Symfony 2 Override Entity and add extra properties - symfony

I have entity A and entity B which extend entity A.
Entity A - in vendor bundle.
Entity B - in /src bundle.
I search a lot of time and only solution works for me. It's using ClassMetadataListener on Doctrine Event loadClassMetadata.
But extending on entity B not works. I need add all properties form entity A to entity B.
I can't understand why.

You cannot simply extend a class like normally when using Doctrine2.
Check the documentation on chapter 6. Inheritance Mapping on how to implement inheritance on your entity classes.
You are probably interested in chapter 6.1. Mapped Superclasses.
A mapped superclass is an abstract or concrete class that provides persistent entity state and mapping information for its subclasses, but which is not itself an entity. Typically, the purpose of such a mapped superclass is to define state and mapping information that is common to multiple entity classes.
For this to work you have to use the #MappedSuperclass annotation to your entity base class.

Add #MappedSuperclass annotation in top of A. That would be enough :)

Related

Using one entity in multiple controllers

The situations' setup is like this:
1) I have two bundles in which I would like to use the same entity. So as suggested in this question and then in this article, I created the CommonEntitiesBundle where the desired Entity lives.
2) Then I described the model interface in both bundles I want to use the Entity in. So far so good.
Now I would like to use the interfaced Entity, just like I would use a 'bundle-native' one like this:
$clientData = new Client(); // the Entity class
$client->setName('Greg');
How should I approach it when there is only the interface available?
I used the interface in this controller.
In the Symfony's example there is only a use of the class via the ORM annotations.
An interface is not a class. it is instead a list of minimal necessary methods a class with 'implements [interfaceName]' must have.
Instead you could provide a example class with your bundle and use that one by default. Add configuration in app/config.yml where you can change the classname. each derived class must implement the interface for consistence.

Keep my symfony2 bundles decoupled

I have two different bundle:
first bundle, OrderBundle , has core logic and functionalities and contains the Order entity.
second bundle, CustomerBundle depends on OrderBundle and contains the Customer entity.
I need to create a oneToMany relation between Customers and Orders (obviously one Customer do many Orders) but I need to keep the first bundle OrderBundle decoupled from the second, because OrderBundle is intended to be reused for other stuff.
I think the correct way could be something like this http://symfony.com/doc/current/cookbook/doctrine/resolve_target_entity.html but I can't figure out how to have a concrete implementation.
How to implement the relation between Order and Customer, if I can't specifically use Customer like targetEntity in the ManyToOne doctrine mapping?
Many thanks, in advance.
UPDATE
I write down the involved code, for better explanation.
\\ Order\Bundle\Entity\Order.php
class Order {
/**
* #ORM\ManyToOne(targetEntity="Order\Bundle\Model\OrderSubjectInterface", inversedBy="orders")
* #var SourceSubjectInterface
*/
protected $subject; // How to define getter ans setter for $subject ? Do I
have to use php app/console doctrine:generate:entities command?
...
\\ Customer\Bundle\Entity\Customer.php
use Order\Bundle\Model\OrderSubjectInterface;
class Customer implements OrderSubjectInterface{
/**
* #ORM\OneToMany(targetEntity="Order\Bundle\Entity\Order", mappedBy="subject")
*/
private $orders;
How to define getters, setters and the interface?
Yes, this is the right way.
As shown in the documentation you mentioned, you can specify something like OrderSubjectInterface as a targetEntity in the ManyToOne mapping.
This way, you know that your Order is related to subjects. Those subjects are, in your case, the Customers, as defined in app/config/config.yml.
It's quite hard to entirely decouple the bundles if you have entity definitions all over the place. The problem is, the Doctrine doesn't allow by default for a related entity to be missing. Let's start from the beginning.
If you want to decouple only Order entity, what you have to do is create interfaces for all its related entities (they need to implement them) and then use the ResolveTargetEntity. So instead of referencing the full entities you reference the interfaces (when you define the relations in your entities). Lastly, you can then set which interface maps to which entity in the configuration.
What this does is it allows you to pick up the Order bundle and put it in an environment which has entirely different entity structure. The important thing is that the entities related to Order must not be missing in the new environment (They can be entirely different, but they must implement the same interfaces as the originals). Then you change the settings so that the interfaces point to the entities from the new environment.
So as you see, this is not "entirely decoupled" code. I can't help you much more without some details. Is the relation bidirectional or unidirectional? What do you exactly mean by "reused for other stuff", can you be more detailed?

Symfony PageEntity->getByPath() or PageController->getByPath()?

I would like to return the page Entity from the method: getByPath($path). I just would like to know where this method should be in the script. Inside the controller or inside the entity class?
In my opinion the entity "Page" shouldn't have a function called "getByPath()" since an entity should only contain database information of one entity, which can be get or set by getters and setters. And this "getByPath" function is not just a getter or setter it requires me to run the entitymanager within the entity. Am I right?
So am I right that I should make a PageController and create the "getByPath()" (which will return the page object) function there? Or would anyone create that function inside the entity class?
I would like to know what the nicest way is to accomplish this.
Thanks in advance.
You should put that function inside a custom repository for the Page entity
While the Entities are the objects you are storing, the Repository is the class that provides methods to access/load those objects, eg when you call $em->getRepository('Entities\Page')->find($page_id);, you call the find() method on your Page repository and it's its job to find it for you.
Doctrine provides a default repository for each entity (with the various find*() methods, ...), but you can provide a custom one where you can add your own method, such as getByPath().
Symfony 2 - Database and Doctrine - Custom Repository Classes
Doctrine 2 - Custom repository

Doctrine2 many repositories for the same entity

For specific needs, I have to create 2 repositories for the same Entity.
The first repository are in the same bundle with the entity and the second, I have to create it in an other bundle but i want to use the same entity with different methodes.
Any idea how can I do that ?
Can't say I see the point, but try this: Symfony 2: Creating a service from a Repository
Create 2 services which extend EntityRepository, construct them correctly and give them the entity reference.
Obviously $em->getRepository('Entity') won't work.
But $this->container->get('repository_service_1') will.
Why do you need this?

Generic comment system in Symfony2

I have in my Symfony 2.1 RC app a simple Comment model (using Doctrine 2). Every comment has a user and a message.
Currently, the CommentBundle manages comments on articles. I'd like it to be more generic to be able to comment any kind of entity without copying code across different bundles dedicated to comments...
For this to work, I also need a way to reference any entity from the comment one. I think having two fields entity_type and entity_id can be a nice solution. However, I can't get the object from these without mapping entity_type to classes manually and using the find method.
So how do I reference an entity from a comment ? And how can I create generic behavior working on several entities ?
You can create a abstract base class entity called Commentable and create entities that inherit Commentable such as Document or Post.
Since Document and Post are derived from Commentable, you can create a one to many relationship between the entities Commentable and Comment respectively.
Make sure to include in your base class ORM annotations for inheritance:
#InheritanceType
#DiscriminatorColumn
#DiscriminatorMap
Examples can be found on Doctrine Project Inheritance Documentation

Resources