The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

The problem is that Rails doesn't use static calls, it uses Ruby's class methods, which are dynamic calls to the class object. The subtle differences between the two means that this approach is a fair bit easier in rails than in php. Still, there's nothing wrong with using ActiveRecord along with finder objects, which is an approach suggested in Fowler's PoEAA, and a good fit for PHP's abilities.

I second that. I always found it really counter-intuitive to have the record and the finder in the same class.

That has been my traditional take on it as well; more recently I discovered that it is actually rather convenient to have both in the same class as it means fewer application objects to deal with and gives a more complete encapsulation for an area of responsibility. So far, I'm quite happy with this refactorization in my codebase.

Maybe using __autoload you can make a hack to work-around this problem. Here is some code in theory that may help (completetly untested in the sense that it is completely unrun, no PHP interpetator immediately handy at the moment).

Now, I can envision possible problems here already (i.e. if there is a chain of classes inheriting from ActiveRecord), and I don't now if even works (never tried it), but it is just an idea.

For people who a) already use __autoload and b) want to use ActiveRecord as described, adding this in may allow them to do so, then when (and if) the syntax is supported, all they will have to do is change __autoload.

The question is, though, does it work? I'll try it out myself when I get a chance.

I wanted to do exactly what you are doing but that was the only thing I couldn't figure out. I decided to go with an "ActiveRecordFinder" class. Having finder methods in a model always seemed a bit bloatalcious anyway.

That's kinda the point of AR - encaspulate both the values and the logic of a type/object.

My understanding of ActiveRecord is that a DataMapper becomes an ActiveRecord when you add business logic to it. Conversely, a domain object becomes an ActiveRecord when you add database logic to it.

Where you put the finder logic doesn't really matter; static find methods or a separate finder are both fine. Of course, I could be wrong

Not sure why you feel a need to defend yourself, I was just pointing out (for those unfamiliar with ruby) the reason why the finder-in-the-same-class approach works better in ruby than in php.

Originally Posted by jayboots

That has been my traditional take on it as well; more recently I discovered that it is actually rather convenient to have both in the same class as it means fewer application objects to deal with and gives a more complete encapsulation for an area of responsibility. So far, I'm quite happy with this refactorization in my codebase.

Fewer objects is definitely a concern of mine; domain models can get pretty complicated, and doubling the number of objects by implementing finder classes for each one seems like an inefficient approach to me.

Fewer objects is definitely a concern of mine; domain models can get pretty complicated, and doubling the number of objects by implementing finder classes for each one seems like an inefficient approach to me.

It's clearly two separate responsibilities, so stuffing them into one place, makes things more complicated than needed. It's bad enough to put persistance and applicationlogic in one place.
You could have a generic finder, which can be used for the majority of classes, and just write specific finders for thoose special cases.

Or perhaps it would be a better approach to think the other way around. Have a generic record-class, and just implement a gateway (finder+attributes metadata) for each type. That's not the activerecord ofcourse, but if you want simplicity ?

It's clearly two separate responsibilities, so stuffing them into one place, makes things more complicated than needed.

Doesn't that depend entirely on how its implemented? To take the Ruby example, I wouldn't call it complicated at all because the entire ActiveRecord implementation is 99% transparent because all you have to do is extend the ActiveRecord class. This means you can still focus fully on your business logic without cluttering up your class.

Doesn't that depend entirely on how its implemented? To take the Ruby example, I wouldn't call it complicated at all because the entire ActiveRecord implementation is 99% transparent because all you have to do is extend the ActiveRecord class. This means you can still focus fully on your business logic without cluttering up your class.

You're right inasmuch that the userland code extending the baseclass is simpler for the all-in-one solution. I was refering to the usage though. Aslong as the record and the gateway are used close to eachother, there's no problem, but if you have to pass the gateway around, it can easily become rather confusing. From the method's signature you won't be able to tell whether you're getting a finder or an actual record, since they share the same classtype.

It's clearly two separate responsibilities, so stuffing them into one place, makes things more complicated than needed. It's bad enough to put persistance and applicationlogic in one place.

I agree that the responisibilities are seperate, but not that it neccesarily makes things more complicated; the implementation may be more complicated, but on the other hand it's easier to use. That's the appeal of the ActiveRecord approach. Single responsibility for objects is an worthy goal, but I think it's a rule that can be broken in certain cases.

Originally Posted by kyberfabrikken

You could have a generic finder, which can be used for the majority of classes, and just write specific finders for thoose special cases.

That's the approach I'm currently considering, combined with some form of metadata mapping.

Originally Posted by kyberfabrikken

Or perhaps it would be a better approach to think the other way around. Have a generic record-class, and just implement a gateway (finder+attributes metadata) for each type. That's not the activerecord ofcourse, but if you want simplicity ?

In reality, I think the ideal approach lies somewhere in between active record and data mapper, combining the simplicity of the former with the flexibility of the latter. One possibility would be to place persitance logic in a seperate object, but keep that object inside the data class. Something like:

You're right inasmuch that the userland code extending the baseclass is simpler for the all-in-one solution. I was refering to the usage though. Aslong as the record and the gateway are used close to eachother, there's no problem, but if you have to pass the gateway around, it can easily become rather confusing. From the method's signature you won't be able to tell whether you're getting a finder or an actual record, since they share the same classtype.

In Rails the finder is the class itself, and records are instances of the class, so there's no confusion between the two; and since the finder is essentially a singleton, there's no reason to pass it around.

I agree that the responisibilities are seperate, but not that it neccesarily makes things more complicated; the implementation may be more complicated, but on the other hand it's easier to use. That's the appeal of the ActiveRecord approach. Single responsibility for objects is an worthy goal, but I think it's a rule that can be broken in certain cases.

Agreed although I don't even see different responsibilities from the point of view of the application. Say we have a User AR class -- why shouldn't that single class alone be responsible for all access to "User" data? Sure, internally it can be implemented as several distinct and more generalized types but to the application I think it makes sense to unify the interface for data access. Kyb makes a good point, but I find that the general case is to use the two "close-by".

Originally Posted by 33degrees

That's the approach I'm currently considering, combined with some form of metadata mapping.

In reality, I think the ideal approach lies somewhere in between active record and data mapper, combining the simplicity of the former with the flexibility of the latter. One possibility would be to place persitance logic in a seperate object, but keep that object inside the data class.

More agreement. In fact, my implementation does something very nearly like that and is similarly constructed by model-driven meta-data (both the crud and the available available finders are entirely described that way). So far, I have yet to need to actually make a custom extension of my AR class -- I just need to update my metadata for a given class type and my autoloader automatically extends the AR class for me. Furthermore, this allows me to define transformations, validations and other criteria declaratively, which I find appealing.

In Rails the finder is the class itself, and records are instances of the class, so there's no confusion between the two; and since the finder is essentially a singleton, there's no reason to pass it around.

Originally Posted by jayboots

Kyb makes a good point, but I find that the general case is to use the two "close-by".

I wouldn't say it's that far-fetched.

Say I have a class ListController, which produce a table of records from a datasource. The natural approach for me would be something like this :

PHP Code:

$lister =& new ListController($gateway);
echo $lister->execute();

See the ambiguity if $gateway is an all-in-one type activerecord ?
I know that I could pass the classname rather than an actual object, and let the ListController instantiate the class itself (or pull it through a static factory/singleton), but that really makes me uncomfortable.

I think I do it a little differently -- my finders return recordsets (plain arrays), not collections of or singular ARs.

$user = new ADC_User;
$all_users = $user->findAll();

If I need a specific user:

$user->find(array('id'=>'foo'));

I also have a few reflection methods on the AR class to let me inspect the requirements of the specific AR instance based on the model it is derived from.

The upshot is that if I had a Lister component, it wouldn't be responsible for acquiring the data -- it gets passed a normal recordset. I'll definately be using some of the arguments in this thread as input when I go to reevaluate my implementation, but so far I find it satisfactory for my needs

The upshot is that if I had a Lister component, it wouldn't be responsible for acquiring the data -- it gets passed a normal recordset. I'll definately be using some of the arguments in this thread as input when I go to reevaluate my implementation, but so far I find it satisfactory for my needs

ORDER BY and LIMIT ?

Anyway - The point is not as much if such a widget is the best possible implementation, but rather that the ambigouity may cause confusion.

From the method's signature you won't be able to tell whether you're getting a finder or an actual record, since they share the same classtype.

Well in the case of Ruby's ActiveRecord, the finders are class methods, so you wouldn't need to pass around any objects to use them, you'd just call them against the appropriate class. There would never be any need to pass round a finder. Records, on the other hands, would be instantiated instances of this class.

Say I have a class ListController, which produce a table of records from a datasource. The natural approach for me would be something like this :

PHP Code:

$lister =& new ListController($gateway);
echo $lister->execute();

See the ambiguity if $gateway is an all-in-one type activerecord ?
I know that I could pass the classname rather than an actual object, and let the ListController instantiate the class itself (or pull it through a static factory/singleton), but that really makes me uncomfortable.

Wouldn't it be better to pass the ListController an array of records/AR objects therefore you aren't binding the ListController directly to any gateway/AR class. In Ruby:

Wouldn't it be better to pass the ListController an array of records/AR objects therefore you aren't binding the ListController directly to any gateway/AR class.

That depends entirely on what the purpose of the component is. The above example isn't all made-up. I have one such class in an application I'm working on currently. It's basically a specialized controller, for handling pagination/sorting of results from a gateway. The component will read the request for page-offset, column to sort by and direction, and will use theese as arguments when calling the findAll method of the gateway. Since I'm reusing the component for multiple gateways (~finders), I need the gateway to be dynamic - A classmethod would tie the class into working with just one gateway.

There is no ambiguity because finders are called against the class itself, not against objects of that class.

In short the problem boils down to this; To distinguish between the finder and the instance, classmethods are used for the former, while instance methods are used for the latter. Classmethods are static calls, and static calls give tight coupling. I like loose coupling.

In short the problem boils down to this; To distinguish between the finder and the instance, classmethods are used for the former, while instance methods are used for the latter. Classmethods are static calls, and static calls give tight coupling. I like loose coupling.

Except that in Ruby, class methods are NOT static calls, they are dynamic, so they're inherited by subclasses, and they can be mixed in from other modules. The coupling is in fact quite loose.

In any case, it's possible to have your cake and eat it, too. Ergo:

PHP Code:

class ActiveRecord {

function find() {
$args = func_get_args();

$finder = new Finder();

return call_user_func_array(array($finder, 'find'), $args);

}

}

Of course, this is ignoring the "knowing which class the static call was made on" issue...

I've just finished a project at work in which I've used a dynamic ActiveRecord in this way. The AR provides insert, update and delete methods, finder methods are handled by the subclass of AR. The subclass passes some meta data to the AR method, which can generate the queries from the protected properties of the subclass.

This was a passable solution until objects started using multiple tables, and the need to create sets of objects appeared. Now it feels like a big kludge. - the AR subclass passes a resource back to the client in the case of multiple records. Time to refactor. I've started writing a generic mapper - I'd be interested to see where you go with this idea 33degrees.