Wall of text warning! (I like this subject 😛)
An ORM is a series of tools (loosely or tightly integrated depends) which maps database rows to objects in the application.
Active Record is one type of ORM pattern, the other (somewhat) widely known type is the DataMapper pattern (not to be confused with Datamapper ORM for CI, it uses the Active Record pattern).
Active Record:
In the Active Record pattern the data objects themselves has a single static connection to the database which they share, but each object is responsible for the direct interaction.
So if you call save() on an object, then that objects collects its data and constructs a query from that and calls the database.
If you print_r() an Active Record object, it will show you all the internal properties which handles the database connection, column assignment, relation handling etc. This is quite an annoyance if you debug something and get a large dump (it can be similar with tightly tied data objects in the Data Mapper pattern, but there it is only one property to ignore).
The other downside with this approach is that you have duplicate data in the form of all the settings in the Active Record objects.
The name Active Record comes from that the records (objects which maps to a row, ie. data objects) are “active” and interacts directly with the database. Data Mapper data objects are “passive” objects, instead letting another object interact for them.
Pros:
- Easy to start with (usually)
- Data objects are decoupled from other data objects
- Easier to implement
Cons:
- Bloated objects
- Duplicate data
- The data objects store both the data and the logic to fetch it
- No central point in the interaction chain
Data Mapper:
In the Data Mapper pattern, the data objects do not know anything about SQL or database connections. Instead they have a mapper which they send themselves to.
The mapper constructs sql (or whatever) and also handles the database connection (can also be handled statically as in AR).
So when you call save() on an object, it calls the mapper which receives the object and then saves it.
But there are different types of Data Mapper implementations, where the objects are in some cases just normal StdClass objects and in other types (my IgnitedRecord included) they are special classes which redirect the limited data object functionality to the mapper (model in the case of IgnitedRecord).
There are also two kinds of mappers, the hidden and the visible mapper. The hidden mapper is automatically instantiated by data objects and interacts with the database behind the scenes - you can actually never really call it in other cases than db settings management (if it is made properly)
The visible mapper can you interact with directly, making the data objects less like Active Record objects and more of data-only objects - this kind of mapper is more like CI’s models.
Pros:
- The data and the logic is separated
- The data objects does only contain the data, making them small
- The mapper is the central point in the database interaction
Cons:
- More classes
- Architecturally harder to implement, because of the different roles of the objects
- Harder to get the grips of when starting (depends on the implementation)
Examples:
// Active Record
$user = new User();
$user->name = 'Martin';
$user->save();
$user2 = new User(array('name' => 'Chris')); // fetch user with the name Chris
// ...
// Data Mapper, hidden mapper
$user = new User(); // connects to a mapper instance
$user->name = 'Martin';
$user->save(); // calls the mapper with the data of this object
$user2 = new User(array('name' => 'Chris')); // same as AR, but it calls the mapper with the filtering data
// ...
// Data Mapper, visible mapper
$user = $mapper->create_user(); // or whatever method the mapper has for object creation
$user->name = 'Martin';
$user->save(); // calls mapper
// or
$mapper->save($user); // a variant, with this variant the data object don't need to have a link to the mapper and can be a StdClass
$user2 = $mapper->fetch_by(array('name' => 'Chris'));
CodeIgniter’s ActiveRecord
CI’s AR is strictly a SQL-string builder, nothing more nothing less. It is NOT an ORM because it does not map a specific object to a row or table in the database.
Instead it helps the user to construct the sql, making it easier to create an ORM.
So, to put it bluntly, CI’s AR doesn’t have anything to do in this thread other than as a SQL-builder.
Summary:
Both Active Record and the Data Mapper patterns are patterns for Object-Relational-Mapping.
This makes the difference between an ORM and AR none, because AR is a type of ORM.