Symfony2 - 呈现作为超类实例引用的对象的子类属性

Here is the issue I have been dealing with all day...

I have got a superclass called Message :

class Message
{   

protected $id;

protected $body;

protected $sender;

protected $receiver;

// [...]

from which inherits my class Bill :

class Bill extends Message
{
protected $id;

protected $amount;

And I wanted to create a Dialogue class that gathers several messages (for instance bills) :

class Dialogue
{
protected $id;

protected $subject;

protected $messages = array();

And here is the corresponding mapping (YAML, Mongodb) :

Bundle\Document\Dialogue:
repositoryClass: Bundle\Repository\DialogueRepository
fields:
    id:
        id:  true
    subject:
        type: string
referenceMany:
    messages:
        targetDocument: Message
        cascade: [remove]

The problem is, when I try to render some attributes specific to Bill (for instance, in Twig : dialogue[0].messages.amount), I get this error :

Method "amount" for object "MongoDBODMProxies__CG__\Bundle\Document\Message" does not exist.

I think I have understood that my bill is considered as a Message, and not a Bill... Furthermore, I don't think it is possible tu typecast, in PHP, in order to make sure that dialogue.message[0] is considered as a Bill... What can I do to access these specific attributes ?

Help :(

PS : I may have a hint : this error occurs when I load dialogues objects from the corresponding repository. However, if I create a new Dialogue and a new Bill in a controller and render them directly, everything works correctly.

So I tried a $get_class($bill) before and after persisting a Bill object, and that is what I got back :

  • before persisting : Bundle\Document\Bill
  • after persisting + loading from the repo : MongoDBODMProxies__CG__\Bundle\Document\Message

My issue could come from here, don't you think ?

This is a design issue - your Dialogue holds a collection of Messages, which do not anything about being subclassed or not.

Either you provide all your Message types with a common Interface, that has all the accessible properties you need, either you explicitly provide your Dialogue entity with a separate relation for every type of Message you want to assign to it, e.g.:

Bundle\Document\Dialogue:
...
referenceMany:
    messages:
        targetDocument: Message
        cascade: [remove]
    bills:
        targetDocument: Bill
        cascade: [remove]
    ...

try

dialogue[0].messages[0].amount

As messages is an array, but you try to access it as an object, or

{% for message in dialogue[0].messages %}
    {{ message.amount }}
{% endfor %}