views:

285

answers:

1

Techniques: ORM, Doctrine 1.1.6, KohanaPHP

With Doctrine 1.1.6. How do I spread a model over different tables?

Detailed situation:

I have the class Entity which contains an ID, login and password and has one emailaddress, many addresses and some other relations. I have two other classes, Company and Person, which extend Entity. I want to extend them using Column aggregation so all login and password information is saved in one place. Now I want to add specific columns to my Person class (firstname, lastname, etc), but I can't find how to do this. The only example the documentation gives is one without extra columns.

Current classes

Entity class:

class Entity extends Doctrine_Record
{
    public function setTableDefinition() {
        $this->setTableName('entity');
        $this->hasColumn('id', 'integer', 4, array(
             'type' => 'integer',
             'length' => 4,
             'unsigned' => 0,
             'primary' => true,
             'autoincrement' => true,
             ));
        $this->hasColumn('login', 'string', 64, array(
             'type' => 'string',
             'length' => 64,
             'fixed' => false,
             'primary' => false,
             'notnull' => true,
             'autoincrement' => false,
             ));
        $this->hasColumn('password', 'string', 64, array(
             'type' => 'string',
             'length' => 64,
             'fixed' => false,
             'primary' => false,
             'notnull' => true,
             'autoincrement' => false,
             ));
        $this->hasColumn('created', 'date', null, array(
             'type' => 'date',
             'primary' => false,
             'notnull' => false,
             'autoincrement' => false,
             ));
        $this->hasColumn('modified', 'date', null, array(
             'type' => 'date',
             'primary' => false,
             'notnull' => false,
             'autoincrement' => false,
             ));

        $this->setSubclasses(array(
                'Person' => array("type" => 1)
            ));
    }
}

Person Class:

class Person extends Entity
{
    public function setTableDefinition() {
        $this->setTableName('person');
        $this->hasColumn('id', 'integer', 4, array(
             'type' => 'integer',
             'length' => 4,
             'unsigned' => 0,
             'primary' => true,
             'autoincrement' => true,
             ));
        $this->hasColumn('firstname', 'string', 255, array(
             'type' => 'string',
             'length' => 255,
             'fixed' => false,
             'primary' => false,
             'notnull' => true,
             'autoincrement' => false,
             ));
        $this->hasColumn('insertion', 'string', 64, array(
             'type' => 'string',
             'length' => 64,
             'fixed' => false,
             'primary' => false,
             'notnull' => false,
             'autoincrement' => false,
             ));
        $this->hasColumn('lastname', 'string', 255, array(
             'type' => 'string',
             'length' => 255,
             'fixed' => false,
             'primary' => false,
             'notnull' => true,
             'autoincrement' => false,
             ));
    }
}

SQL generated:

CREATE TABLE `person` (
    `id` INT AUTO_INCREMENT, 
    `firstname` VARCHAR(255) NOT NULL, 
    `insertion` VARCHAR(64), 
    `lastname` VARCHAR(255) NOT NULL, 
    PRIMARY KEY(`id`)
) ENGINE = INNODB

CREATE TABLE `entity` (`
    id` INT AUTO_INCREMENT, 
    `login` VARCHAR(64) NOT NULL, 
    `password` VARCHAR(64) NOT NULL, 
    `created` DATE, 
    `modified` DATE, 
    PRIMARY KEY(`id`)
) ENGINE = INNODB

Can somebody tell me how to accomplish this?

+1  A: 

You'll have to add these columns to the entity class since everything is basically stored in the same table. That means that these columns will be available to the company entries too, but maybe you can forbid using them there.

You can however use different tables and reference them with a foreign key. This will give you a layout like this:

  1. entity - stores basic information common to all entities. Furthermore you store the type of this entity (User, Company) as an id.
  2. entity_types - stores the coreesponding table for each entity type
  3. User - stores information specific to the users and a key to the corresponding entity.
  4. Company - same as User, may be nearly empty if there is no additional info (depending on how you implement this solution, you can still add one row just containing the entity id for simplicity)

This way you can alway (lazy) fetch additional information about your entities and the table itself remains slim. If you realize entity as an column aggregation Doctrine will take care of returning the right object. Then you can add your custom functions for fetching the additional information.

You can leave out the indirection in 2.

Larry_Croft
@Larry_Croft: So basically what I want is not possible? I have to put both my Person and Company information in one table?
Stegeman
Yes, at least with column aggregation. I'll add an alternative solution to my answer.
Larry_Croft
Thanks. You suggest my old situation (no offense, you couldn't know). I think I will try to extend your/mine/our idea. Thanks again for your help!
Stegeman