[Solar-talk] Changes afoot: a new Model class
Paul M Jones
pmjones at ciaweb.net
Wed Feb 7 15:58:17 PST 2007
Hi Andreas,
> This is very interesting, especially since I'm used to working with
> the
> active record pattern through PEAR::DB_DataObject. Though, it's not
> completely clear to me though how one should work with your
> implementation. Here's a repaste of your code example:
>
> // object to work with the Nodes model
> $nodes = Solar::factory('Solar_Model_Nodes');
>
> // get a single record from the model
> $node = $nodes->fetchOne();
>
> This is slightly confusing to me - if I understand this correctly, the
> domain model is $nodes (well, domain model if it has been
> subclassed and
> extended as to such), and a row (record) with data is represented by
> $node. To insert/update a single row, you call $nodes->save($data).
That's the plan.
> This implies that to add business logic to the domain model
> ($nodes) the
> logic would (very often) need a param such as a primary key, and then
> conditionally ask itself for row(s) to work with. Something like this:
>
> // object to work with blog posts
> $posts = Solar::factory('EnterpriseCompany_Models_Blog_Post');
>
> // Set new title on a single post, first param is primkey of
> post to
> alter
> $posts->setTitle(1, 'Solar pwns the competition again');
Not quite what I had in mind; I'm thinking more along these lines:
// model for all blog posts
$posts = Solar::factory('EnterpriseCompany_Model_Blog_Posts');
// get a single post by its primary key
$post = $posts->fetch(1);
// set a title on it
$post->title = 'Solar pwns the competition again';
// save it
$post->save();
To more closely match Rails, you would do something like this:
// model for all blog posts
Solar::loadClass('EnterpriseCompany_Model_Blog_Posts');
// get a single blog post by its primary key
$post = EnterpriseCompany_Model_Blog::fetch(1);
// set a title on it
$post->title = 'Solar pwns the competition again';
// save it
$post->save();
We have the modified step for getting an instance of the "master"
model object, because ROR's ActiveRecord doubles as the TableModule
*and* the DomainModel. PHP can't pull that off yet, because static
methods don't have access to things like the extended class name.
The Record object returned by fetch() carries the all the needed
data, and has a tie back to the Model class that generated it. That
means it knows which data key is the primary key, which is the
inheritance type, etc. Record::save() passes its data back to the
bound Model::save() method, which does all the heavy lifting
(including domain logic) and reports results back to the Record.
In many ways, it's like the current Table/Row/Rowset interactions,
but with better/more-extensible filtering, relationships, etc.
Does that make sense at all?
Incidentally, this is another of the kinds of things I'm working
toward (seems like it works right now, even) ...
class EnterpriseCompany_Model_Blog_Posts extends Solar_Sql_Model {
protected function _setup()
{
$this->_hasMany('comments');
}
}
class EnterpriseCompany_Model_Blog_Comments extends
Solar_Sql_Model {
protected function _setup()
{
$this->_belongsTo('post');
}
}
// model for all blog posts
$posts = Solar::factory('EnterpriseCompany_Model_Blog_Posts');
// get a single post by its primary key
$post = $posts->fetch(1);
// see all the comments
foreach ($post->comments) {
$comment->dump();
echo "I belong to " . $comment->post->title;
}
Note how they talk back and forth to each other automatically, with
lazy-loading of to-many relationships and eager loading of to-one
relationships.
--
Paul M. Jones <http://paul-m-jones.com>
Solar: Simple Object Library and Application Repository
for PHP5. <http://solarphp.com>
Join the Solar community wiki! <http://solarphp.org>
Savant: The simple, elegant, and powerful solution for
templates in PHP. <http://phpsavant.com>
More information about the solar-talk
mailing list