开发者

How to self-initialize Doctrine_Record (as if Doctrine_Query would)?

I have models that extend Doctrine_Record, and are directly mapped to one specific record from the database (that is, one record with given a given id, hardcoded statically in the class).

Now, I want the specific record class to initialize itself as if Doctrine_Query would. So, this would be the normal procedure:

$query = new Doctrine_Query();
$model = $query->from('Model o')->where('id = ?', 123)->fetchOne();

I would like to do something like this

$model = new Model();

And in the Model:

const ID = 123;

//note that __construct() is used by Doctrine_Record so we need construct() without the __
public function construct()
{
    $this->id = self::ID;
    //wh开发者_如何转开发at here??
    $this->initialize('?????');
}

So for clarity's sake: I would like the object to be exactly the same as if it would be received from a query (same state, same attributes and relations and such).

Any help would be greatly appreciated: thank you.


The first thing I need to say is I'd put the constant in the class. So like this:

class Application_Model_Person
{
    const ID = 1234;
}

Then, a Doctrine method like Doctrine_Record::fetchOne() is always returning a (new) instance of the model and never merges the data with the record you're calling fetchOne() to. Doctrine is nevertheless able to merge a retreived record with another class, so it rather simple to do:

class Application_Model_Person extends Doctrine_Record_Abstract
{
    const ID = 1234;

    public function __construct($table = null, $isNewEntry = false)
    {
        // Calling Doctrine_Record::__construct
        parent::__construct($table, $isNewEntry);

        // Fetch the record from database with the id self::ID
        $record = $this->getTable()->fetchOne(self::ID);
        $this->merge($record);
    }
}

Then you're able to do:

$model = new Application_Model_Person;
echo $model->id; // 1234


Although having multiple classes for the same data type (i.e. table) is really not what ORM should be like, what you want can be done in Doctrine using Column aggregation inheritance. Assuming you are using Doctrine 1.2.x, you can write the following YML:

Vehicle:
  columns:
    brand: string(100)
    fuelType: string(100)

Car:
  inheritance:
    extends: Entity
    type: column_aggregation
    keyField: type
    keyValue: 1

Bicycle:
  inheritance:
    extends: Entity
    type: column_aggregation
    keyField: type
    keyValue: 2

Now, the Vehicle table will have a 'type' column, that determines the class that Doctrine will instantiate when you select a vehicle. You will have three classes: Vehicle, Car and Bicycle. You can give every class their own methods etc, while the records their instances represent reside in the same database table. If you use $a = new Bicycle, Doctrine automatically sets the type for you so you don't have to take care of that.


I don't think a model instance could decide to hang on a certain database entry after it has been initialized. That said, you can do something like this:

<?php
class Model extends baseModel {
  public static function create($id = null)
  {
    if ($id === null) return new Model;
    return Doctrine::getTable('Model')->findeOneById($id);
  }
}

And then, you can either use

$newModel = Model::create();

Or fetch an existing one having ID 14 (for example) using

$newModel = Model::create(14);

Or, if you want your 123 to be default instead of a new item, declare the function like this:

  public static function create($id = 123)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜