<ac:macro ac:name="note"><ac:parameter ac:name="title">Under Construction</ac:parameter><ac:rich-text-body>
<p>This proposal is under construction and is not ready for review.</p></ac:rich-text-body></ac:macro>
<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[
<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[
Zend_Db_ActiveRecord is an implementation of the ActiveRecord pattern based on the Patterns of Enterprise Application Architecture book by Martin Fowler. It also has similar functionality as the Ruby on Rails ActiveRecord implementation. This implementation relies on PHP 5.3's late static binding capability (currently not in stable yet). An implementation of ActiveRecord according to PoEAA (Fowler, 161) should have the following characteristics:
In the Zend Framework context, here are the requirements:Zend Framework: Zend_Db_ActiveRecord Component Proposal
Proposed Component Name
Zend_Db_ActiveRecord
Developer Notes
http://framework.zend.com/wiki/display/ZFDEV/Zend_Db_ActiveRecord
Proposers
Ken Chau
Revision
1.0 - 03/05/2008: Initial draft (wiki revision: 25)
Table of Contents
1. Overview
2. References
3. Component Requirements, Constraints, and Acceptance Criteria
4. Dependencies on Other Framework Components
- Zend_Exception
- Zend_Db
- Zend_Db_Select
5. Theory of Operation
6. Milestones / Tasks
- Milestone 1: design notes will be published here
- Milestone 2: Working prototype checked into the incubator supporting use cases #1, #2, ...
- Milestone 3: Working prototype checked into the incubator supporting use cases #3 and #4.
- Milestone 4: Unit tests exist, work, and are checked into SVN.
- Milestone 5: Initial documentation exists.
7. Class Index
- Zend_Db_ActiveRecord_Abstract
8. Use Cases
| UC-01 |
|---|
Declaring an ActiveRecord Model, defining Relationships
| UC-02 |
|---|
Create, Update, Delete
| UC-03 |
|---|
Find a record in the table by ID and by where clause
| UC-04 |
|---|
Find records in the table by a custom SQL
| UC-05 |
|---|
One-to-one relationship
In this example use case, a Driver owns a Car and only one Car. Note that the foreign key field exists on the owned item.
| UC-06 |
|---|
One-to-many relationship
| UC-07 |
|---|
Many-to-many relationship
23 Comments
comments.show.hideMar 06, 2008
Matthew Ratzloff
<p>Woohoo!</p>
Mar 09, 2008
Lars Strojny
<p>How to you plan to implement the typical static find-calls? Have you thought about __callStatic()?</p>
Mar 09, 2008
Ken Chau
<p>That's exactly how I expect to have find calls to be implemented. PHP 5.3 constructs used will be:</p>
<ul class="alternate">
<li>the static::$properties</li>
<li>get_called_class()</li>
<li>__callStatic($method, $argument)</li>
</ul>
Mar 09, 2008
Superbiji
<p>I love this.........<br />
haha just like ruby on rail...</p>
<p>but why must using php 5.3? </p>
Mar 09, 2008
Ken Chau
<p>Late static binding. I updated the proposal to clarify this.</p>
Mar 13, 2008
Gauthier Delamarre
<p>I personnaly do love this pattern (ActiveRecord) ; anyhow, I'm wondering if two so close but so different patterns (ActiveRecord / DB Table Row Gateway) implemented in the same framework is not too much...</p>
<p>Still, I would love such a component <ac:emoticon ac:name="wink" /></p>
Jun 01, 2008
Jani Hartikainen
<p>This looks quite good... but... I don't want to sound rude or anything, but wouldn't it be more beneficial for everyone to concentrate efforts on a single ORM library, like Doctrine?</p>
Jun 20, 2008
Benjamin Eberlei
<p>Wouldn't it be better to handle the relationsships in an protected variable $_relations, $_relationsships or something alike, rather than an initialization function (maybe making init function optional).</p>
<p>Relationsships are more an description of an object rather than something that has to be "initialized" in a function.</p>
<p>But maybe this is just the request of a nitpicker...</p>
<p>Also there is currently no UseCase for the integration of Validators on certain ActiveRecord fields, I would like to see how that might be integrated and configured.</p>
Jun 21, 2008
Aldemar Bernal
<p>Hi Ken, if you want to start working with this before 5.3, I've found an alternative solution for those static calls:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
class Person extends Zend_Db_ActiveRecord_Abstract
{
public static function init()
}
$person = Person::init()->find(1);
...
]]></ac:plain-text-body></ac:macro>
<p>Hope it helps,</p>
<p>Aldemar</p>
Jun 21, 2008
Ken Chau
<p>The problem is in how you can get the class name in a static method from the parent. So, get_static_class() is the functionality that is really truly missing here.</p>
Jun 21, 2008
Aldemar Bernal
<p>Ken, this is exactly what I'm using right now in my active record approach and works perfect. Since the init method returns already an instance of Person and not Zend_Db_ActiveRecord_Abstract, calling from the parent any function using $this (meaning not static call) will use Person and then Zend_Db_ActiveRecord_Abstract.</p>
Jun 21, 2008
Ken Chau
<p>The truly viable way to do this is to do something like this:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
class Zend_Db_ActiveRecord_Abstract
{
public static factory($class)
public function find(...)
{
}
}
class Person extends Zend_Db_ActiveRecord_Abstract
{
}
$p = Zend_Db_ActiveRecord_Abstract::factory('Person')->find(...)
]]></ac:plain-text-body></ac:macro>
<p>I guess I can create something like this for < 5.3 as well.</p>
Jun 21, 2008
Aldemar Bernal
<p>IMHO, I prefer:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
$person = Person::init()->find(...)
]]></ac:plain-text-body></ac:macro>
<p>instead of:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
$person = Zend_Db_ActiveRecord_Abstract::factory('Person')->find(...)
]]></ac:plain-text-body></ac:macro>
<p>The first one will reflect better how it's actually going to work, btw, in my implementation I have an interface with that init() method defined, so, that ensures that every class you create has the init() method.</p>
Jul 23, 2008
Harro van der Klauw
<p>You don't need an interface for that, simply make the class you are extending abstract and define it as an abstract method.</p>
Jul 29, 2008
Fernando Chucre
<p>I wanna that you think about inheritance. Hibernate have 3 way to make it, for 3 different environment. The Joined inheritance is most common. The way consist in 2 classes in your project and you have 2 tables in database scheme. I wanna a code like this:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
create table person(
id int,
name varchar(255_,
id_father int,
) and teacher(id int(pk), id_person int(fk), school varchar).
]]></ac:plain-text-body></ac:macro>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
class Person extends Zend_Db_ActiveRecord_Abstrac
{
protected $_nameTable = "person";
public static function initRelationships()
{
Person::hasOne('Person as Father', array('local'=>'id_father', 'foreign'=>'id');
}
class Teacher extends Person
{
protected $_nameTable = "teacher";
protected $_someAttributeToRelationship = array('local'=>'id_person', 'foreign'=>'id');
}
$teacher_father = new Person();
$teacher_father->name = "Father's Name";
$teacher_father->save();
$teacher = new Teacher();
$teacher->name = "Teacher's Name";
$teacher->school = "School's Name";
$teacher->Father = $teacher_father;
$teacher->save();
]]></ac:plain-text-body></ac:macro>
<p>This code reflect my intention. So think about this.</p>
<p>Regards </p>
Jul 29, 2008
Fernando Chucre
<p>I wanna that you think about inheritance. Hibernate have 3 way to make it, for 3 different environment. The Joined inheritance is most common. The way consist in 2 classes in your project and you have 2 tables in database scheme. I wanna a code like this:</p>
<p>SQL create table scheme.</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
create table person(
id int auto_increment,
name varchar(255_,
id_father int,
primary key(id)
);
create table teacher(
id int auto_increment,
id_person int,
school varchar,
primary key(id)
)
]]></ac:plain-text-body></ac:macro>
<p>PHP code wanted</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
class Person extends Zend_Db_ActiveRecord_Abstrac
{
protected $_nameTable = "person";
public static function initRelationships()
{
Person::hasOne('Person as Father', array('local'=>'id_father', 'foreign'=>'id');
}
class Teacher extends Person
{
protected $_nameTable = "teacher";
protected $_someAttributeToRelationship = array('local'=>'id_person', 'foreign'=>'id');
}
$teacher_father = new Person();
$teacher_father->name = "Father's Name";
$teacher_father->save();
$teacher = new Teacher();
$teacher->name = "Teacher's Name";
$teacher->school = "School's Name";
$teacher->Father = $teacher_father;
$teacher->save();
]]></ac:plain-text-body></ac:macro>
<p>This code reflect my intention. So think about this.</p>
<p>Regards </p>
Jun 22, 2009
sawan ruparel
<p>Hi Ken,</p>
<p>I have implemented similar thing in my project, and it is a a huge help for new programmers. It is so easy for them to do the regular operations.</p>
<p>I have created table classes and used setters and getters, and a base class that mimics the active record from ruby on rails as you have indicated.</p>
<p>Let me know if I can help in anyway to improvise this component or if you would like to see how I have done it.</p>
<p>Regards,<br />
Sawan</p>
Dec 07, 2010
Alex Kachayev
<p>Hi Ken! Are there some news about this proposal? Do you work now on it's implementation?</p>
<p>Regards, Alex.</p>
Dec 08, 2010
Matthew Ratzloff
<p>Alex,</p>
<p>This proposal is dead; it is not actively being developed. It can safely be archived.</p>
<p>-Matt (works with Ken)</p>
Dec 08, 2010
Alex Kachayev
<p>Sadly... What reasons are there (tech, architect, or just spare time)?</p>
Jan 19, 2011
Chris Roth
<p>I know this is dead right now but I personally hope it gets implemented. I have been researching the benefits of different database access patterns for my web app and I would REALLY like to use the Active Record model. I am going to write my own abstract class to make it work, but it would have been so much nicer if ZF supported this.</p>
<p>I've also been researching a bunch on RoR and what I've realized is that one of RoR's strongest features is the Active Record support. In other words, I feel that ZF should invest in this in order to compete with RoR. In my opinion the ZF is so good and widely used because it is so extendable. RoR's strong points are speed. ZF needs to continue with its extendibility and implement the ActiveRecord pattern.</p>
Jan 20, 2011
Goran Juric
<p>If you want Active Record use Doctrine 1. Doctrine 2 on the other hand uses a data mapper pattern, maybe you would want to look at that one too.</p>
Feb 05, 2011
Dolf Schimmel (Freeaqingme)
<p>Archiving this proposal, feel free to recover it when you want to work on it again. For more details see <a href="http://framework.zend.com/wiki/display/ZFDEV/Archiving+of+abandoned+proposals+(Feb+5+2011)">this email</a>.</p>