Skip to content

Class table inheritance #40

Closed
guilhermeaiolfi opened this Issue Aug 15, 2011 · 14 comments

5 participants

@guilhermeaiolfi

Hi,

currently Propel has 2 types of inheritances: single table and concrete.

But the most common inheritance and the one I would like to use is the inheritance that uses join in its children tables.

E.g:

User { id, name } //parent
Company { user_id, slogan } //child
Person { user_id, sex } //child

That's the normalized version of the schema. It similar to the concrete table, but it won't copy all the parent's field to its children nor the parent fields to its children. Instead it will "join" those tables to access the data.

I had already talked about it in the IRC with others (Jarda mostly) and it seems that it's not just me that want that. Francois didn't really understand what I was asking when we talked, I think I didn't know how to explain it because it is recommended approach in most of the cases when dealing with inheritance.

For reference: http://www.doctrine-project.org/docs/orm/2.0/en/reference/inheritance-mapping.html#class-table-inheritance

@fzaninotto
Propel member

What you describe (Company inherits from User) is not inheritance, it's a relationship. Propel supports relationships already. I still don't see the point.

@guilhermeaiolfi

Company is one type of User in this case. It is considered inheritance in every other place. And it's not just a relationship. It is a relationship the same way other inheritances are, but there are some things you need to do to make it easier to deal with them. For example, I was hoping to do that:

$company->setName("X corp");

but as it is today I have to do this instead:

$company->getUser()->setName("X Corp");

A behavior that does that is what I'm asking.

@guilhermeaiolfi

Here is another link to help understanding: http://martinfowler.com/eaaCatalog/classTableInheritance.html

Maybe my example wasn't clear enough, warui gave another example in the IRC channel

staying in the person example a bit... juristic_person is parent model and company is a child... as well as a registered charity
association.... one has yearly revenue, taxes and number of employees, the other one has number of members,
name of president, etc.

@fzaninotto
Propel member

This is what I call a "polymorphic" behavior. It's not inheritance, either, but I agree there is a need for it.

@IcyT
IcyT commented Aug 16, 2011

So you argue that Martin Fowler is wrong? :P

@fzaninotto
Propel member
@IcyT
IcyT commented Aug 16, 2011

I think it's inheritance in the object oriented world. The class diagram clearly shows it.
How this inheritance is mapped to the database is another issue and this issue is what guilhermeaiolfi is referring to.

@guilhermeaiolfi

Is the delegate behavior an attempt to fix this?

I saw your message in the commit: Introducing Delegate behavior, for class table inheritance fans

So it seems so. But you commented:

This is not really class table inheritance because you manipulate Player objects rather than Basketballer objects.
However, it allows an object to have several active delegates - in that case, a player who can play both soccer and
basketball."

And that's true. Not really class table inheritance. Class table inheritance is the other way around, the reference to the delegate class would be in the children and not in the parent. So my question is if that's going to work:

<table name="player">
    <column name="id" type="INTEGER" primaryKey="true" autoIncrement="true"/>
    <column name="first_name" type="VARCHAR" size="100"/>
    <column name="last_name" type="VARCHAR" size="100"/>
</table>

<table name="footballer">
   <column name="goals_scored" type="INTEGER" />
   <column name="fouls_committed" type="INTEGER" />
   <column name="yellow_cards" type="INTEGER" />
   <column name="red_cards" type="INTEGER" />
    <behavior name="delegate">
       <parameter name="to" value="player" />
    </behavior>
</table>

<table name="basketballer">
   <column name="points" type="INTEGER" />
   <column name="field_goals" type="INTEGER" />
   <column name="three_points_field_goals" type="INTEGER" />
    <behavior name="delegate">
       <parameter name="to" value="player" />
    </behavior>
</table>

to be used as:

$basktballer = new Basktballer();
$basktballer->setFirstName("John");
$basktballer->setPoints(10);
$baskballer->save(); // that would create the player row and the basktballer row and the references between them

Because that IS class table inheritance and if that works you created a behavior that can do two things. Extremely flexible and useful :)

@fzaninotto
Propel member

That would work if the footballer and basketballer had a fkey to player. You're welcome to try and test it ;)

But I'm not sure delegation should be used to mimic class inheritance. I still haven't found a good use case for it. But I think the behavior allows you to do so.

@fzaninotto
Propel member

By the way, I love how a smart concept developped in the right way can allow more than what it's been designed for. Sorry, just congratulating myself there.

@guilhermeaiolfi

But I'm not sure delegation should be used to mimic class inheritance.

Why is that? I'm considering to use it right now, It would be nice to see your point of view in this case. The behavior will be exactly the same, just the name seems to be different ;p

A good use case for class inheritance? I think it should be the default behavior for inheritance, and single and concrete tables are the ones to find good user cases for.

@fzaninotto fzaninotto added a commit to fzaninotto/Propel that referenced this issue Aug 19, 2011
@fzaninotto fzaninotto [delegate behavior] Changed class table inheritance examples to show …
…that the behavior is much more powerful than previously thought.

Refs #40
8290ed5
@willdurand
Propel member

Can we close this issue as the wonderful DelegateBehavior does the work ?

@fzaninotto
Propel member

Indeed.

@fzaninotto fzaninotto closed this Aug 22, 2011
@miklcct
miklcct commented Aug 24, 2015

DelegateBehavior cannot perform proper PHP inheritance in the generated classes (i.e. using "instanceof" test for a child class on an object generated by a parent query). I think a proper one using PHP extends should be made.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.