Why active record sucks
First published at Tuesday 28 August 2007
Warning: This blog post is more then 17 years old – read and use with care.
Why active record sucks
Table of Contents
It is not really Active Record (AR) which sucks but the implied, perhaps just misinterpreted, common usage as an ORM (object relational mapping). To summarize the following blog post in one sentence, so that you may skip reading it:
Active Record may be used to implement ORM, but it should never be used as an ORM.
What is Active Record again?
Active Record (AR), Table Row Gateway, Table Data Gateway ... let's not difference between them, but just consider the concept of plain mapping of a row to an object with properties representing the columns of a table.
Of course you always have some mechanism which enables you to fetch the related contents depending on your ERM (entity relationship model). This may happen with explicit calls to fetch, let's say, the author of a news post, or a more advanced implementation of AR may even construct JOINS in the initial query to fetch all requested related data.
This sounds perfect to map my business objects to the database, or?
The basic model
Considering a very simple DB model AR may work for you. Let's consider the following structure for something like a very simple news system:
+-----------+
| Article |
+-----------+
| id | +--------+
| author_id | ---> | Author |
| title | +--------+
| text | | id |
+-----------+ | name |
| email |
+--------+
For such a structure even AR fulfills all basic requirements for an ORM, when you extend the basic classes with some validations, which are not topic of this blog post.
Causing some trouble
Having a model and an easy to use interface which provide full access to the data, and abstracts away the SQL by generating the queries still seems a quite perfect solution - so let's introduce some requirements which are not properly realizable with Active Record. This is - of course - not a complete list, but very basic and quite common requirements for a data model.
Translation, Versioning and Status
A quite common requirement is translation of contents. In this case you want to add some key to your table containing the contents of your application which somehow maps to a language. The logical consequence is, that you get more then one article with the same value in the column 'id' and need to define a multi column index on the columns 'id' and '~language'.
If somebody is able to edit contents, which commonly will be true for articles managed by some web interface, you should introduce content versioning in your application, so that no content is lost, if somebody accidentally deleted some text or somebody abuses his rights to do bad stuff.
Here the same applies as for translation - you need an additional column representing the version and you get a three column primary index for your data.
I am not really sure if there are an AR implementation which handle the case of multi column indexes properly - if you know some please point me to them, but even if it is supported you end up with a messy table containing not normalized data, with duplicate titles, which are not required to store, if they did not change between two versions.
You may also have some other attributes like states ("published", "draft", ...) for your content which will pollute your table even more. State changes on one version of an article / in one row will result in the loss of change histories - and otherwise you might just need to copy the complete the contents of an article, because it has been published by the editor without any changes in an article draft...
Variants
Think of the case you do not only want to show articles on your website, but some other contents, like blog posts which also contain a list of tags or categories, perhaps you want to include project news which also contain some release information...
This will either mess up you basic table by adding optional attributes which destroys the semantic meaning of the table by containing completely different stuff, or you would need to add several new tables which will be aggregated into one list, sorted by some common criteria and handled by different views.
Now think of a online shop, or some other complex website, where you do not only have three types of contents, but hundreds or thousands - you may come up with the idea of serializing the content specific data in some way (XML, PHP specific stuff, JSON, ...), but you are not serious about that, are you? This would lead to a whole bunch of other problems like the requirement for specialized search engines, unnecessary parsing, using semantical information from the DB view...
Relations
A different requirement where AR fails totally used as an ORM are n:m relations with associated metadata. To stay with model introduced above you could imagine that you want to add references to existing articles in a new article you write - of course it should be a potentially finite count of article references. The metadata could be a description why you add this article as a reference, some date and / or link title - a table like this would be the result:
+----------------+
| reference |
+----------------+
| source_id |
| destination_id |
| title |
| description |
| date |
+----------------+
In the optimal cases - the AR implementation automagically fetches the right articles for you - you would end up with an article object containing a bunch of objects with the reference metadata, each containing the destination article object.
But, from a business object point of view, there are two things wrong now with your data structure. You normally just some reference objects to render in a defined way in your views, and the articles of course should not be fetched multiple times, if one article references another one multiple times.
You can work with this case, you may be able to handle it properly in your views, but this won't be the data structure you probably would design when not having the database scheme in your mind - and letting the abstraction layer define you business object structure just is the wrong way to go.
Conclusion
The conclusion is simple:
You either destroy your business objects or your DB model.
This "OR" is not a "XOR" - you may even destroy both, just because you used the wrong tool for the right job - ORM per se is nothing bad. The above described examples force you to use hacks of a model which originally were thought to clean up your data storage system and offer a nice model. You may reach the opposite.
Proper ORM
As usually, doing something the proper way, it gets harder. I am sorry for this ;). And as always, there is no magic store, where you may just put your data, without thinking about your application and hope that everything works perfectly...
A trivial model
Let's take a look at one model which can map the above described problems - for now ignoring the relations. This is of course not the ultimate solution, but just an example. I will mention some of its weaknesses later.
The model is structured in four table clusters.
Content class
The content class is the equivalence to some class definition in your object orientated code. It defines the structure of some content, which has been done in the AR example above by the SQL table. To define the content class for an article you create an entry in the table content_class with a well chosen name and create entries in the table content_class_attribute with the properties of your content class - title and text in the example above. Those attributes are of some attribute type which may be anything from string, text, date, integer up to complex data types like (multi) select boxes, geo information, models, images or something completely different.
Obviously you are then able to automagically create forms using various widgets (combinations) - but this is not really relevant when it comes to the data model.
Instance
Of course you should be able to have a finite count of instances (articles) of your content class (article). Those are stored once , with an optional name and a reference to the defining content class in the table content_object.
The real instances, beside the identifier, are the versions - if you want language and / or status aware - in the table content_object_version. The attributes data, which actually somehow defines the object, is stored content_object_data with the obvious references to the obvious tables. The version and object data tables are using a multi column index on version, language and id here.
Metadata
You see very few essential metadata in the example, like the language, status, creator and the creation date. The last two ones probably would better fir in some abstracted metadata storage extended by tags, ratings or whatever you want to add here. This is not really relevant.
Attributes
As written earlier you can easily generate forms (not only for (X)HTML) from those content class definitions, but you can also easily include descriptions, configurations of data types (with some default configuration options in the table attribute_type), which may define valid value ranges, limit the host for some URL or whatever you imagine.
If an attribute has not been changed in a new version of a content object you may automatically fetch it from earlier versions of the content objects without any real drawbacks, but this may result in more complex queries. It is up to you to find the proper balance for your application - as always.
And the n:m relations?
Until now nothing is defined for the code basis you use. You just may define a common n:m relation with some metadata. In the case of busimess.org, for example, the relation data again is defined by a structure like the one above.
Considerations
This model only eliminates the drawbacks on the DB model side, no possible drawback on the application side, like mentioned above with relations in AR. Implementing this model as a backend in your application you should do the mapping or use some content management framework which already implements a model like this.
Enhancements to the model
eZ Publish, for example does not only versions and translate the content objects, but also the content classes - you may imagine that this makes some of the queries even a bit more complex, but when good caching comes in place here, this shouldn't be such a big deal with common requirements - and if you have very special performance requirements you still may use views, another model or more caching ;). And - as written earlier - this is not meant being the optional model for each use case. Something like this obviously does not exist.
Including model in your application
The earlier mentioned relations between objects are one way to include such a model in your application, if you have data only structured by some graph, as known from computer science. This is true for wikipedia, for example, where the only structure is given by references between articles - hard to brows for the visitor and not a very common access method.
Tree
Far more common are trees which put the data into a hierarchic structure - this can be read as some navigation, or maybe you also want to structure the data not displayed on your website in a tree and only display a subtree.
This can be done easily by using some extra table defining the hierarchic structure using some of the common algorithms to map trees into a database like parent child relations, or nested sets where the nodes relate to some object. You may want to consider being able to connect one object to multiple nodes...
eZ Publish
In eZ Publish you get one tree which contains objects, similar to the ones described above, connected to one or more nodes of the tree (where one is the main node). Additionally you get the possibility to add relations between the objects (so that you don't have a tree any more in theory, but this does not really matter anywhere).
Each object in eZ Publish is connect to at least one node, and nearly everything is such an content object. Even users, for example, are only sub content objects of a subtree which is an instance of the content class user group.
Of course you may also add user content objects to other nodes, you may define permissions on parent content class, define which content class / object may have childdren at all, or which children it may have, for users or groups, or complete sub trees, either by sub tree or section. Going into detail here obviously won't fit any blog post. ;)
Other ORMs
There are complete different ways to define your ORM. You may use an arbitrary table structure and define some random mapping using some XML definitions, or even a mapping in your database. Both ways can make the mapping completely independent from your business objects and your database schema.
Then ... why does AR exist at all?
AR still may be used for accessing the tables in the model described above. If this makes sense again depends on your use case, and - for example - may be useful as an abstraction layer of the used relational database management system.
Also you may try using some AR framework to just do rapid prototyping. But you should know the limited scope of this approach - and hope your boss will not come into your office and request something which may not be implemented using AR - or you can just do a quick hack, of course. ;)
Conclusion
As shown, AR is just a wrapper for database access and not appropriate as an ORM. Used carefully, or with very simple applications it really may proof useful.
But there are other ways to abstract the access to your database like query construction using some object orientated interface, like it is done in the database component in eZ Components. The classes then may create SQL which work with the currently used RDBMS. Another (slow) way is parsing the query given by the user and restructuring for the current relational database management system.
The possibilities for object relational mapping described in this blog post are initially more complicate to use, but also may offer great extensibility, real mapping with future proof concepts. You won't run in the discussed problems. But, as always, higher abstraction cause more complex code and may bring you a performance impact - which could be solved by proper caching.
And, there is no perfect system to solve all your needs, which some people think Active Record was, but you should review your modelling concepts.
Other solutions
There are completely different solutions which may work better with your object structures like CouchDB - something Jan blogged about and is a really cool solution which does not force any relational database structures and still are ACID.
Subscribe to updates
There are multiple ways to stay updated with new posts on my blog:
Comments
Les at Tuesday, 28.8. 2007
This is why I loathe Ruby on Rails; Those that use it have little, if any real experience developing complex or task/user heavy applications, and are dependent on a complete solution.
Ruby on Rails has been touted as a web development framework, and yet it is just not ready for what is required of us developers today's market. To get something done, you have to jump through hoops, and as you say, break something along the way.
I just cannot imagine the -beep- nightmare second generation developers are going to face when it comes to maintaining Ruby on Rails based applications tomorrow. If you want a complete solution, develop your own, otherwise pray that you've chosen wisely!
Daniel Spiewak at Thursday, 30.8. 2007
What you've pointed out are really a generic series of problems with any ORM/ERM/whatever-you-want-to-call-it. It's really the same problem in any framework you may choose: it's too generic. You have a specific use case you need to satisfy, and AR is absolutely the wrong tool to accomplish this. For something where you have really crazy requirements or a complex set of non-standard mappings, something like Hibernate will really do much better.
Hibernate is about the most flexible ORM possible. The problem with this of course is an increase in complexity. AR trades flexibility for simplicity. Thus, for 90% of use cases, AR will perform the task and do it in a much more intuitive way than Hibernate. For the remaining 10% of scenarios, AR will fail to work at all, and you'll have to fall back to something more complex. It's just the nature of generic libraries.
Kore at Thursday, 30.8. 2007
@Daniel: You are basically right, and this trade off is of course well known.
To boil it down to one single point: I don't think AR fits 90% of the use cases. The issues I described above are so general, that nearly each web application is required to solve it somehow - and I think more developers should be aware of the issues, and that this will results in ugly hacks when AR is used.
As said in the blog post, AR works for very simple projects ... but where you don't need states, versions OR translations - same for the variants...
Mark Thomas at Friday, 31.8. 2007
This article is talking about Active Record the design pattern, not ActiveRecord the Ruby ORM. The Ruby ORM, despite the name, actually provides more capability than the design pattern covers. But Kore is correct--sometimes in Rails you have to bypass AR and roll your own. But this can be done in rails, so it's no reason to loathe it.
Mor at Saturday, 1.9. 2007
@Les: You don't really know what you're talking about, do you? I have over 10 years of experience developing complex "user-heavy" applications. I've been using Rails for 6 months building an app used by thousands of people daily and growing. I can truthfully say, since I actually have the requisite experience, that Rails is ready for developers in today's market for a lot of (the majority of) applications without jumping through hoops or breaking something.
There are cases where you will have to jump through hoops, but what framework covers every case out of the box? If you can name one, you're delusional at best.
Mike Seth at Sunday, 2.9. 2007
Hi Kore,
I agree and disagree with you at the same time. Here is my detailed followup:
http://blog.mikeseth.com/index.php?/archives/4-ActiveRecord-sucks,-but-Kore-Nordmann-is-wrong.html#extended
Dante at Sunday, 2.9. 2007
Hi Kore,
You should really have a look into Ruby on Rails Active Record implementation and put it into use. Or if you prefer its new PHP version Akelos (http://www.akelos.org).
What they have covers more than what the Active Record pattern specifies, but as Thomas said you can do about everything using them.
Can you tell us the hoops you can't jump with one of those?
Steve Molitor at Sunday, 2.9. 2007
Kore,
You might want to make it clear that you are talking about the generic Active Record pattern, not the Rails ORM of the same name. Some people reading this (like Les) might assume you're slamming Rails, but based on your article I assume you have no knowledge of the Rails ActiveRecord library. True, Rails AR is built on the AR pattern, but it adds (in some cases with plugins) all the ORM features missing from the base pattern -- support for versioning, localization, auditing, optimistic locking, mapping tree sructures, yada yada. As best I can tell it can address all of the prolems you mention and more. It's quite sophisticated. To paraphrase your one line summary of your article, Rails AR implements an ORM on top of the AR pattern. Try it, you might like it.
Steve
Tim Harper at Wednesday, 17.10. 2007
I haven't yet run into a problem that was unsolvable by ActiveRecord - It's not really meant to be an "end all solution" and do everything for you - it's a base starting point, and a really great one.
If you haven't looked into it, you can pass in your own includes (joins auto generated by the models, a really REALLY handy feature), custom joins, custom selects, aggregation, etc.
Then, if ActiveRecord still doesn't cut it for you for those more advanced cases, you can skip straight to the database connection, and use select_all.
I smell FUD
Daniel Kerr at Sunday, 4.11. 2007
I have one problem with active record when creating apps.
Some tables require a date_added field. Since all the active record patterns I have seen add quotes around each value how are you soposed to add date/times set to now().
Art Hundiak at Monday, 5.11. 2007
Daniel Kerr, Which active record patterns (libraries?) have you looked at? In PHP: propel, Doctrine and the Zend_Db framework all handle dates just fine. Especially since they all rely on prepared statements.
Cory Kaufman at Tuesday, 6.11. 2007
I am working on a project with tables structured similar to yours. Was your table structure inspired completely by ezpublish, as mine was, or did you have other inspirations? I'd love to read up on something that isn't quite as complex as ezpublish, to make sure I'm headed in the right direction.
ggiunta at Friday, 9.11. 2007
A good example of the leakiness of the AR mapping can be found in this blog post: http://www.xml.lt/Blog/2007/10/22/Eager+fetching+and+SELECT+N%2B1+problem
I do not like very much the proposed solution, as it looks quite not general enough, and somehow keeps the data layout filtering to the above layers...
hello at Friday, 18.1. 2008
HELLO!!!
kicherhexe at Monday, 17.3. 2008
1000 bussies to ernie!
David Griffiths at Monday, 5.5. 2008
Aren't you at risk of being too sweeping? You admit that AR can be useful in some circumstances. Does it cover every circumstance? No. Does anything? No. Are you ideas over-engineered for some circumstances? Yes. So by your own logic, do your ideas suck?
I think you need to be very careful in immediately going for large up-front designs to solve problems you don't have yet. If you need to solve the problems you describe here, then your solutions are very clever. But if you are trying to solve simpler problems, then they are not.
Simple problems should be solved simply. That what ActiveRecord is good at. Whether it is an "ORM" (is there a full, formal definition of what that is, by the way?) or not is irrelevant.
Sam at Saturday, 26.7. 2008
@Les. So why do you take a crap on Rails just because the big apps you've worked on would require you to break the "Rails Way" so to say? So what? The creator of Rails has said, in public, that a pure Rails implementation would obviously not be sufficient a Google, Amazon, etc. How many web apps are going to be that big anyway? Many of the people I met building web apps with Rails were doing so for universities that don't have the money to hire a professional Java developers....so they are doing it with Rails!
Are you offended that some young hacker from 37signals is richer than you are?
dwlnetnl at Sunday, 27.7. 2008
To all of your ActiveRecord people, please look on this article: http://www.qcodo.com/documentation/article.php/6
That's build on the 'legacy' ActiveRecord in stead of an fuzzy definition-like mess.
Thank you.
Snouty Hound at Wednesday, 13.8. 2008
Please see the Wikipedia material on the so-called Object-Relational Impedance Mismatch. SQL is basically a given, but its philosophies are fundamentally incompatible with OOP. In the OOP world, the database is merely a persistence mechanism; in the database world, objects in the process space are just temporary data. Rails (with Mongrel) is basically a combination of three things: a very decent HTTP/object mapper, ActiveRecord, and a bunch of miscellany. The way to get things done in Rails: abandon OOP and ActiveRecord (except for the simplest one-table queries), and write procedure-oriented code that will interface very well with SQL databases.
dmx at Tuesday, 7.10. 2008
I've got bit of a stunt I use with Active record. I hook it together with database views and ignore the object relational stuff.
All queries get built as database views, or stored procedures, and kept on the DB side, then I can just peel em off with the AR implementation and treat it as a dumb table with nice syntax.
Works a charm and avoids the impedence mismatch.
Mark at Saturday, 25.10. 2008
Relying on ORM is a cruch. It enables poor performance application by being greedy in its selection and updating of records.
Let's say I have a record with 50 fields.
I need to access only Firstname, Lastname and Email. WHy select all 50 fields?
I need to update only email... again, why write all 50 fields?
These are just two scenarios where blindly relying on ORM to do the work for you is bad.
Aaron at Tuesday, 18.11. 2008
Kore-
I'm not weighing in on ActiveRecord, but saying thanks for your description of the the content problem and a proposed model. It has helped me understand how versioned documents with variable attributes can be efficiently stored in a database, something that you don't see from many applications out there. I'll have to give ezPublish another look.
Les at Sunday, 25.1. 2009
Offended?
Yes and no. No because someone got rich, and yes because RoR was in the beginning touted around the community as the perfect solution and now today it has been proven to be inadequate, a number of times I might add so my earlier comments do in fact stand.
As to the other comment made to my original comment, do you still today believe that RoR is a credable solution? A number of Python frameworks have got a lot more going for them than what RoR has to offer.
RoR is really only suitable for personal sites such as blogs and home businesses where there is very few users and minimum amount of data in use.
Basically, RoR sucks and you can bang on about how great it [RoR] is but facts speak for themselves.
Enough said then.
Josh Ribakoff at Tuesday, 17.2. 2009
Thanks for the great article, helped explaining the difference between the DA patterns to a client. If any PHPers are reading this they might be interested in the library I'm working on
JRiddy at Thursday, 13.8. 2009
Just nit pickin':
"You either destroy your business objects or your DB model."
The sentence that immediately follows this states that this "OR" is not an "XOR." If that's the case, please don't say "either." "Either A or B" is the English equivalent of logical "A xor B." Just plain "or" in English can be ambiguous, but that can be helped. Try this:
"You could destroy your business objects or your DB model, or both."
Okay, I'm a grammar Nazi, but this is the kind of thing that would cause a potentially hard-to-spot logical error if it were in code. I guess I'm just trying to apply the same care to speech as I do to code. ;)
ToKaM at Tuesday, 22.9. 2009
private static $tanslations = array (); /** * @param integer $id * @param Sql_Language $language * @param integer $joinOnInit * * @return Sql_Translation */ public static function getTranslation($id, $language,$joinOnInit=0) { $id = intval($id); if(is_numeric($language)){$language=Sql_Language::getLanguage($language);} if (self::$tanslations [$id][$language->getId()] === null) { self::$tanslations [$id][$language->getId()] = new Sql_Translation($id, $language); } $ret = self::$tanslations [$id][$language->getId()]; $ret->addJoin($joinOnInit); return $ret; } //__construct is private!
ToKaM at Tuesday, 22.9. 2009
This is an excerpt of my ORM for the class Sql_Translation. I have a multifield primarykey (id|language). The variable $joinOnInit is used to decide in the init() method, which is called when a getter is called for a non-set member variable. the addJoin method is public and it connects the existing $joinOnInit information with an logical or to the binary flag passed as param. here you see an exmaple for the flags for an other class.
Kirk Bushell at Saturday, 16.1. 2010
Les - you say:
RoR is really only suitable for personal sites such as blogs and home businesses where there is very few users and minimum amount of data in use.
Basically, RoR sucks and you can bang on about how great it [RoR] is but facts speak for themselves.
I couldn't disagree more. I haven't built sites that serve billions of page views (how many of us have?) but I have built applications and sites that serve well over 20mil+ visits/month across an application built on ruby on rails. RoR doesn't suck, it's just that the community itself got swept along by it's own enthusiasm, which blindsided them and allowed greener developers to be swept along with it.
RoR, although not the be-all-end-all solution, is still very good for rapid development, which is really what it's all about. It was the first real step in industrializing application development. You can easily add more hardware (and might I add - cheaply), but developer time is always far more expensive. Therefore, the tradeoff is worth it.
Also, I'd like to add to this discussion that there has not been a single, complex query that I've had to create (sometimes collecting data from as many as 7 tables) using RoR's built-in AR functionality.
I'm no RoR evangelist, but I do think it has it's place, and it's also helped PHP salaries go up as more and more devs move to RoR =P
stizi at Saturday, 30.1. 2010
@Kirk Bushell AR lacks of stardard. When queries getting more complex, each of these framework(ROR, Zend, Doctrine...) try to resolve in their own way. Now as developers you have to master each of them in order to use these frameworks. Why NOT just learning one language - SQL?
alex at Sunday, 7.2. 2010
@stizi if you want to write sql queries that fits two pages don't ask yourself why you broken your leg when other webdev came to work after you
and... at Sunday, 7.2. 2010
@kore you are stupid
Kirk Bushell at Monday, 15.2. 2010
@stizi
You are, obviously - correct. However, why worry about how other frameworks implement things? Different are always going to be different - everyone has their own ideals as to how something should be done. I can guarantee you that if I were to create a framework, it would again be different. There are high-level standards, they're called design patterns. That's about as much as you can hope for :P
SQL is great, and certainly has it's place - I still work with it heavily on various projects. However - writing and testing SQL is slow. If you have a more efficient way of utilizing it, a way that saves your company money - why would you ignore it?
kostyl at Wednesday, 3.3. 2010
May be you don't understand how to use Active Records, Mappers, Query Objects, Lazy Loaders and other patterns together with little tricks and corrections?
T at Thursday, 8.4. 2010
You sir are an idiot. Basically, you're complaining that your car sucks because you can't drive from Europe to Australia.
beberlei at Saturday, 7.8. 2010
Thanks kore! your reference example got me inspired to finally take up the rather complex issue of allowing composite primary keys that are foreign keys also and implement it in Doctrine 2:
/** * @Entity */ class DDC117Reference { /** @Id @ManyToOne(targetEntity="DDC117Article", inversedBy="references") */ private $source; /** @Id @ManyToOne(targetEntity="DDC117Article", inversedBy="references") */ private $target; /** @column(type="string") */ private $description; public function __construct($source, $target, $description) { $this->source = $source; $this->target = $target; $this->description = $description; } } $ref = new DDC117Reference($article1, $article2, "Some description");
Mctaco at Wednesday, 29.9. 2010
hey alter, great article to distinguish between AR and actual ORM. At the beginning it was confusing because Doctrine for instance presents itself as an ORM when it is actually an AR library. Machs jut!
Gregory Magarshak at Sunday, 24.10. 2010
I think you're pretty wrong about ORMs.
First of all, ORM itself basically just means ... fill objects instead of arrays. So instead of writing Users::method($array), you would write $user->method().
Secondly, your criticism that not many ORMs support multi-column indexes used to be valid, but not any longer. Doctrine and other ORMs can now handle multi-column indexes.
You said to let you know if there's a good ORM implementation. My framework (PHP On Pie) had it from the very beginning, and in fact can handle multi-column joins and even use table relationships to come up with intelligent stuff like create optimal queries for "fetch all the items that this $user placed on this $tag"
Now, regarding fetching too many or too few fields from a row -- this is a problem of modular app design in general. If you don't know ahead of time which components will be on a page (and consequently what fields of a row they will use) you may as well fetch all the fields once, since you spent all that time finding the row. Unless the fields are huge TEXT or BLOB fields.
Finally, the question of issuing queries more than once. I'm not sure exactly what situations would lead to this, but most web scripts are designed to be executed "very fast", meaning you get a request, you service it and the script ends. Thus, 99% of the time you are perfectly justified in caching the results of a query in a hash containing $sql => $results pairs. If you happen to issue the same query to the database multiple times, just consult the cache first.
The result is a very pleasant experience that lets you CRUD out of the box and write pleasant code. Moreover, it's way more maintainable, because you can hook into central locations such as the save() function in order to do something during each save (such as update a timestamp, log a query, or do sharding).
That's my take on it. Check out PHP On Pie if you want to see a viable implementation for MySQL.
Assurance Vie at Tuesday, 7.12. 2010
Even Doctrine are switching from AR to a Data Mapper pattern...
Stephen Blackstone at Wednesday, 26.1. 2011
Theres alot of people talking alot of ignorance about Rails in here.
I wrote a rails app on top of active record that scales to 20MM Hits/Month just fine using activerecord..
I'm a PHP dev now and I miss how easy AR makes day-to-day tasks. I've not read one complaint in here that isn't already addressed by RoR..
Eager Loading? Check Minimizing selected fields? Check Internationalization? Easily implementable by overriding accessors. Eager Loading? Check. SQL ReUse? Named Scopes!
qwerty at Monday, 31.1. 2011
It seems to me that the author thinks that the "relational" in relational database has something to do with table associations. Hint: it does not. Dig into set and graph theory a little.
This is one of the many reasons why true computing professionals(read CS and CE) take a lot of math.
http://en.wikipedia.org/wiki/Binary_relation
rencontre at Wednesday, 16.3. 2011
Even Doctrine are switching from AR to a Data Mapper pattern...
JJ at Thursday, 14.7. 2011
I'm sorry... I don't buy it. Versioning is a problem for you?? Normalize your database! Multi-column primary keys are a hack in and of themselves. if you feel like you have to hack AR to get it to work with it, you're right, but it's not because AR is flawed. Create your articles tables, then create the article_contents sub-tables. article_contents contains multiple versions of your article's contents. problem solved and AR loves it.
Chas at Thursday, 3.5. 2012
Oh Brother...
Just write some SQL. It's easier to amintain than all this XML.
emmess at Monday, 20.8. 2012
Wow... I am always amazed by the number of people who comment on things, and in their comments make clear they are not qualified to comment on the subject matter.
For instance: " ORM itself basically just means ... fill objects instead of arrays." No, ORM implies more than simply returning an object instead of an array... there is an object, it's relationships, and mapping them in one result, hence O-R-M.
For those that say just learn SQL and don't use an ORM, or "I need to access only Firstname, Lastname and Email. Why select all 50 fields?": ORMs do not require you to select all 50 fields if you only need 3 of them. That statement indicates you've never used an ORM, or if you did, you didn't know how to use it properly.
There's just a lot of gibberish being spouted both in the article and in the comments, and my suggestion would be - try reading, learning, and understanding before writing.