Skip to end of metadata
Go to start of metadata

<p>Let us start with a taxonomy of potential enhancements to Zend_Db_Table/Row/Rowset.</p>

<h1>Requirements</h1>

<p>Briefly, for the ZF approach to using modeling objects with data backed by a RDBMS, we'd like to:</p>
<ol>
<li>avoid auto-generating any code or configuration files,</li>
<li>avoid requiring the developer to write code specific to implementing an ActiveRecord, when the database schema can support a clean mapping of a table's rows to ActiveRecords ( <a class="external-link" href="http://www.martinfowler.com/eaaCatalog/activeRecord.html">http://www.martinfowler.com/eaaCatalog/activeRecord.html</a> )</li>
<li>avoid requiring developers to scatter their "code" across configuration files and PHP source files,</li>
<li>rely on database introspection,</li>
<li>automatically publish an extensible API providing access to underlying tables that follow naming and structural conventions (similar to most interpretations of ActiveRecord).</li>
</ol>

<p>Summary of the ZF's approach:</p>
<ol>
<li>Keep it simple! Why? So ZF developers can get their work done quickly with as little pain as possible.</li>
<li>Solve the 80% first. What? We need to first make the ZF solve the most frequent and common problems frameworks are supposed to solve first.</li>
<li>Interoperability. Why? The ZF should make extra efforts and smart compromises to create unusually flexible, well-integrated, and "pluggable" components that "play well" with each other, including mixing the use of "ActiveRecord" style access for some tables, and other access styles for other tables.</li>
</ol>

<h1>Investigating Ideas and Alternatives (please contribute)</h1>

<p>We are experimenting with mixing ActiveRecord and DAO patterns, as the latter better accommodate more complex object modeling needs when the underlying schema doesn't quite fit the desired object domain patterns.</p>

<p>Ok, so how does all that answer the question that was asked? I needed a little context and common understanding of terminology first ...</p>

<p>If the ZF supports an interpretation of ActiveRecord, yet allows some flexibility with DAO-like capabilities, then a ZF developer could design by creating an object domain and a supporting schema, relying on ActiveRecord-style tables/classes when there is naturally a close correspondence between tables and desired classes, but fall back to one of the other ZF mechanisms for working with other situations, all within the same application. Hint: Debate, suggestions, feedback, opinions, <br />
and more are most welcome.</p>

<h2>ORM Mapping</h2>

<p>Mappers live outside of the object model domain and database schema. They map the model domain onto a database schema. For non-trivial domain models, the underlying auto-generated database schema resulting can be quite complex. If not auto-generated / synchronized / maintained, then the effort required to specify, maintain, and enhance the configuration information (e.g. like propel) throughout an application's life cycle does not seem to fit the ZF's approach to solving the stated goals.</p>

<p>I found this person's experience ( <a class="external-link" href="http://www.kuro5hin.org/story/2006/3/11/1001/81803">http://www.kuro5hin.org/story/2006/3/11/1001/81803</a> ) with an ORM mapper roughly consistent with my experiences, including difficult to optimize inefficiencies arising from numerous SQL queries with overlapping result sets. Although long, the blog entry doesn't require the reader to possess a deep past experience with Java or ORMs, and uses humor to keep the read entertaining.</p>

<ul>
<li><a class="external-link" href="http://www.martinfowler.com/eaaCatalog/dataMapper.html">http://www.martinfowler.com/eaaCatalog/dataMapper.html</a></li>
</ul>

<h2>ORM Wrapping</h2>

<p>Wrapping solutions encapsulate database complexities and SQL code to provide simpler API's for retrieving and modifying the data store. The API's abstract the database schema, and the resulting, exposed model of data in the data store does not always match the desired object model domain. However, when a database schema closely parallels the object model domain (e.g. tables <==> classes), wrapping might yield excellent results. Regardless, the "model" part of MVC can be used to process results retrieved from a wrapping API into models fitting the business logic.</p>

<ul>
<li><a href="http://www-128.ibm.com/developerworks/java/library/j-cb03076/?ca=dgr-lnxw01ActiveRecord">Overview of Ruby's interpretation</a></li>
<li><a class="external-link" href="http://www.martinfowler.com/eaaCatalog/tableDataGateway.html">http://www.martinfowler.com/eaaCatalog/tableDataGateway.html</a></li>
<li><a class="external-link" href="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">http://www.martinfowler.com/eaaCatalog/rowDataGateway.html</a></li>
<li><a class="external-link" href="http://www.martinfowler.com/eaaCatalog/activeRecord.html">http://www.martinfowler.com/eaaCatalog/activeRecord.html</a></li>
<li><a href="http://java.sun.com/blueprints/patterns/DAO.html">Java/Sun-centric interpretation of DAO</a></li>
</ul>

<p>Using a framework, much/most of the business logic does not need to reside in DAOs, and can reside in classes that work with the data abstractions created by the DAOs. DAOs can provide a type of manual mapping of schemas to objects and vice-versa, such that objects need not exactly resemble the underlying schema (e.g. Class 1-to-1 Table). Thus, I consider DAO as something not identical to either the ORM mapping or Active-Record style wrapping approaches.</p>

<h1>Examples</h1>

<ul>
<li><a href="http://framework.zend.com/issues/browse/ZF-38">Zend_Db_Table with table-specific row objects</a></li>
<li><a href="http://www.nabble.com/need-advices-An-idea-to-build-a-KISS-ORM-system-upon-Zend_Db_Table-tf1926214.html#a5274924">KISS ORM</a></li>
<li><a href="http://blog.wolff-hamburg.de/archives/3-eZeAR_ActiveRecord-implementation.html">eZeAR_ActiveRecord</a></li>
<li><ac:link><ri:user ri:username="ralph" /></ac:link>'s <strong><a href="http://www.activemodel.org/wiki/index.php/Main_Page">ActiveModel</a></strong></li>
</ul>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Dec 14, 2006

    <p>As I have expressed on the mailing list earlier, I'm all for what's being said here, with the exception of relying on database introspection at runtime. Even if the information is being cached, instantiating the cache component and retrieving the cached information will add unneccessary overhead.</p>

    <p>Also, not having the table fields as physically declared properties in your table classes will make things like code completion in modern IDEs like Zend Studio very difficult, if not impossible.</p>

    <p>IMHO, code-generation absolutely is the way to go. In my own implementation (which you referenced as one of the examples) and other solutions, like Propel or DB_DataObject, this is done using a command line tool. This is rather unelegant, though. If you really want absolute simplicity and the developer should not even be required to lift a finger, you'd introduce a "development mode" that can be activated by setting static class property in the bootstrap script (or whereever).</p>

    <p>When in development mode, you'd do a database introspection at every request, and then regenerate the class files as needed. To avoid overwriting code altered by the user, you could either rely on a special section in the class containing the property-equivalents of table columns (as done by me and DB_DataObject), parsed out using RegEx, or you could have a base class for each table containing meta information and another class extending the base class, which can contain custom code (as seen in Propel).</p>

    <p>As the latter method introduces overhead again (because of the additional inheritance layer), I naturally prefer the block parsing solution <ac:emoticon ac:name="smile" /></p>

    <p>Regards,<br />
    Markus</p>

  2. Dec 14, 2006

    <p>Another thing that just came to mind: I'd really like it if we could agree on a standard interface for ActiveRecord objects, or data-accessing objects in general. Having that, it would be possible for other framework components to rely on a defined behaviour of the data component, but as a developer I would not be required to use the standard Zend_ActiveRecord (or whatever it will be called later), but could use an implementation specific to the use case at hand - for example, a performance-optimized data layer, or something that behaves like ActiveRecord, but really uses XML files in the background, etc....</p>

    <p>I've heard that in the latest version the Symphony framework now supports ORM layers other than Propel - haven't looked at their solution yet, but it sure would be interesting how they've pulled that off (I simply assume that they do not expect their developers to sacrifice functionality for choosing a different layer <ac:emoticon ac:name="smile" />).</p>

    <p>CU<br />
    Markus</p>