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)
精彩评论