DDC-143: Add @MappedClass #179

Closed
opened 2026-01-22 12:29:43 +01:00 by admin · 4 comments
Owner

Originally created by @doctrinebot on GitHub (Nov 13, 2009).

Jira issue originally created by user reinier.kip:

At this moment Doctrine already knows the mapped superclass. 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. I'd like to see something called the mapped class (or however you want to name it). For example, this means that when using class table inheritance classes that only provide (re)implementation of one or more methods they need not be stored in the database. They still, however, need to be mapped.

class Construct { $id; $property; }

// This class doesn't add any properties and it's no use to store only the IDs in a table. (In fact, inserting a
// class without any additional properties doesn't even work, on which I will post another issue.)
// This class needs only mapping!
abstract class Expression extends Construct { abstract method(); }

// This class implements method() and provides an additional field to the hierarchy.
class Operand extends Expression { $value; method(); }

Another example is the inversion of the above: the subclasses only have a different implementation and do not have additional properties that need to be stored.

class StringChanger { $id; $string; changeString(); }

// This class only overrides changeString(). It does not need storage, only mapping.
class AnotherStringChanger { override changeString(); }

I hope this all makes sense.

Originally created by @doctrinebot on GitHub (Nov 13, 2009). Jira issue originally created by user reinier.kip: At this moment Doctrine already knows the mapped superclass. 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. I'd like to see something called the mapped class (or however you want to name it). For example, this means that when using class table inheritance classes that only provide (re)implementation of one or more methods they need not be stored in the database. They still, however, need to be mapped. ``` class Construct { $id; $property; } // This class doesn't add any properties and it's no use to store only the IDs in a table. (In fact, inserting a // class without any additional properties doesn't even work, on which I will post another issue.) // This class needs only mapping! abstract class Expression extends Construct { abstract method(); } // This class implements method() and provides an additional field to the hierarchy. class Operand extends Expression { $value; method(); } ``` Another example is the inversion of the above: the subclasses only have a different implementation and do not have additional properties that need to be stored. ``` class StringChanger { $id; $string; changeString(); } // This class only overrides changeString(). It does not need storage, only mapping. class AnotherStringChanger { override changeString(); } ``` I hope this all makes sense.
admin added the New Feature label 2026-01-22 12:29:43 +01:00
admin closed this issue 2026-01-22 12:29:44 +01:00
Author
Owner

@doctrinebot commented on GitHub (Dec 18, 2009):

Comment created by romanb:

"they need not be stored in the database. They still, however, need to be mapped"

Can you elaborate on that? As seen in the other ticket, it is well possible to have transient classes in a class table inheritance hierarchy.

And if you need classes in the middle of the hierarchy that are not mapped themselves but have mapping information for their children, a mapped superclass can be used in the middle of a hierarchy.

@doctrinebot commented on GitHub (Dec 18, 2009): Comment created by romanb: "they need not be stored in the database. They still, however, need to be mapped" Can you elaborate on that? As seen in the other ticket, it is well possible to have transient classes in a class table inheritance hierarchy. And if you need classes in the middle of the hierarchy that are not mapped themselves but have mapping information for their children, a mapped superclass can be used in the middle of a hierarchy.
Author
Owner

@doctrinebot commented on GitHub (Dec 18, 2009):

Comment created by reinier.kip:

We started this discussion in http://groups.google.com/group/doctrine-user/browse_thread/thread/9df8b3171968971d/7d42679d0d6e7c32 from post 5.

An simple example is the second example in the issue description.

'StringChanger' (whatever) has $string, which contains e.g. 'my first string!'. StringChanger#changeString()'s implementation replaces 'first' with 'second' and turns it into 'my second string!'.
AnotherStringChanger's implementation reverses the string instead of replacing 'first' with 'second'.

When stored in the database, a StringChanger would be stored like:

0 | 'my first string!' | StringChanger

where StringChanger is the discriminator value

An AnotherStringChanger would be stored like:

1 | 'my first string!' | AnotherStringChanger

So AnotherStringChanger does not add state, and is not stored in an additional table or in additional columns, it's only mapped.

If I recall correctly, this cannot be done with a mapped superclass. Am I right?

@doctrinebot commented on GitHub (Dec 18, 2009): Comment created by reinier.kip: We started this discussion in http://groups.google.com/group/doctrine-user/browse_thread/thread/9df8b3171968971d/7d42679d0d6e7c32 from post 5. An simple example is the second example in the issue description. 'StringChanger' (whatever) has $string, which contains e.g. 'my first string!'. StringChanger#changeString()'s implementation replaces 'first' with 'second' and turns it into 'my second string!'. AnotherStringChanger's implementation reverses the string instead of replacing 'first' with 'second'. When stored in the database, a StringChanger would be stored like: ``` 0 | 'my first string!' | StringChanger ``` where StringChanger is the discriminator value An AnotherStringChanger would be stored like: ``` 1 | 'my first string!' | AnotherStringChanger ``` So AnotherStringChanger does not add state, and is not stored in an additional table or in additional columns, it's only mapped. If I recall correctly, this cannot be done with a mapped superclass. Am I right?
Author
Owner

@doctrinebot commented on GitHub (Feb 28, 2010):

Comment created by @beberlei:

You can easily solve this by aggregation:

class StringChanger
{
    function changeString($tring);
}
class AnotherStringChanger
{
    function changeString($tring);
}

Now your Entity:

/****
 * @Entity
 * @HasLifecycleCallbacks
 */
class StringManipulator
{
    /*** @Id @Column(type="integer") @generatedValue **/
    private $id;
    /*** @Column **/
    private $string;
    /*** @Column **/
    private $manipulateStrategy;

    private $manipulateInstance;

    /****
     * @PostLoad
     */
    public function loadManipulateStrategy()
    {
        $this->manipulateInstance = new $this->manipulateStrategy();
    }

    public function setNewManipulateStrategy(ManipulateStrategy $strategy)
    {
        $this->manipulateInstance = $strategy;
        $this->manipulateStrategy = get_class($strategy);
    }
}
@doctrinebot commented on GitHub (Feb 28, 2010): Comment created by @beberlei: You can easily solve this by aggregation: ``` class StringChanger { function changeString($tring); } class AnotherStringChanger { function changeString($tring); } ``` Now your Entity: ``` /**** * @Entity * @HasLifecycleCallbacks */ class StringManipulator { /*** @Id @Column(type="integer") @generatedValue **/ private $id; /*** @Column **/ private $string; /*** @Column **/ private $manipulateStrategy; private $manipulateInstance; /**** * @PostLoad */ public function loadManipulateStrategy() { $this->manipulateInstance = new $this->manipulateStrategy(); } public function setNewManipulateStrategy(ManipulateStrategy $strategy) { $this->manipulateInstance = $strategy; $this->manipulateStrategy = get_class($strategy); } } ```
Author
Owner

@doctrinebot commented on GitHub (Feb 28, 2010):

Issue was closed with resolution "Won't Fix"

@doctrinebot commented on GitHub (Feb 28, 2010): Issue was closed with resolution "Won't Fix"
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#179