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.

Hard coding the properties into the model as public members doesn't make for a very flexible system. Especially if you start to consider the need to overload a single ActiveRecord with other ActiveRecords

Can you give me an example of overloading a single ActiveRecord with other ActiveRecords?

or overload calculated columns.

That's what I mentioned in my previous post that it's very rare that I want to overload columns - I don't want to abstract too much from db structure and have different field values in the db and different (=calculated, modified, translated, etc.) in my application. I think it makes things simpler if I try not to overload columns too much - then when I look straight at db data I see more or less what my application sees. However, sometimes I use overloading for data types like date, datetime, etc. when I want to translate the value to a timestamp for example, but in most other cases I don't need it and plain properties are sufficient. Do you think using both direct properties and getters will make things difficult? Personally I haven't noticed that yet.

For instance, to create a aggregate calculation when finding data.

I prefer to use db aggregate functions for such calculations, it's the most efficient way. However, I can create methods for my active records to do that if I want - I don't see how public properties will prevent me from doing that?

A fundamental advantage of the active record is the flexibility of dynamic properties.

So I still keep this advantage, it's just that for most db fields I don't find the need for that and I use this advantage optionally. If I need a dynamic property then I create a specific getter and use it. Otherwise I simply use the property directly and then I am aware I'm accessing raw data from db. I haven't found any problem with that in practice.

For efficiencies sake the previous code also be written as shown to below which would only run one query and return the same data. This is because the users table would joined and the appropriate data related to the user would be redistributed to a new instance of User. The data would be the same as above without the added trip to the database.

PHP Code:

$blog =BlogEntry::find('one',array('include'=>'user','id'=>10));

That is a simple example of how useful being able to overload a model instance can be. Without dynamic properties each association would also need to be defined as a public member to accomplish a similar functionality.

Originally Posted by Lemon Juice

I prefer to use db aggregate functions for such calculations, it's the most efficient way. However, I can create methods for my active records to do that if I want - I don't see how public properties will prevent me from doing that?

In the previous scenario how would one easily count the number of blogs per a user?

The solution is to overload the already overloaded model using dynamic fields. In this case a dynamic field named blogs_per_user will be overloaded as a property that contains the aggregate data. That result set data could then be accessible through the dynamic property blogs_per_user on a BlogEntry object. Something that wouldn't be possible at all without dynamic properties because the name and calculation is determined at run time.

A small sample of output. Notice how even though the BlogEntry model doesn't contain a native field named blogs_per_user it has been overloaded and contains the aggregate data - number of blogs per user.
So using dynamic properties it is possible to overload any model with more data say for aggregate calculations as in the previous scenario.

In that case all users are being joined with their blog entries and then using a group calculating a aggregate count based on how many blogs each user has. Information that would now be accessible directly through the user and its dynamic blogs_per_user property:

The former is just a more convenient way of accomplishing the same thing since all collections implement arrayaccess.

Laslty, non of this logic is handled inside the model class files. All ActiveRecord functionality is managed through the class which all models extend. The Model files themselves are dormant of any logic besides configuration type info for the model - table name, field, etc. This leads to a very scalable, reusable and lightweight code base then if all logic were to be hard coded into individual model files.

These are things that I've found make the ActiveRecord system incredibly flexible, easy to use and powerful. I wrote my own implementation based on desire to always use it. Therefore, it supports almost all circumstances which I can think of including subqueries.

At the same time though I've also broke certain "rules" pertaining to a ActiveRecord to accomplish functionality that would otherwise be almost impossible to implement. So if you believe breaking with tradition will lead to a more useful system then I won't stare you away. ActiveRecord, Gateway, etc all that really matters in the end is what the thing does in my opinion and how efficient, scalable and reusable the solution is. Call it whatever you may if succeeds in those areas pattern or not.

Thanks for taking the time for writeing the detailed explanation, a few comments from me:

Originally Posted by oddz

The below would fetch a blog entry then separetly fetch the blog entries user into a dynamic property called user. This can be seen below with the XML that represents the dynamic property hierarchy.

PHP Code:

$blog = new BlogEntry(10);$blog->user;$blog->toXML();

Sure this looks very nice. But all I'm saying is that dynamic properties are not necessary to achieve this functionality. While you do:

PHP Code:

$blog->user;

In my system I would write:

PHP Code:

$blog->getUser();

which would basically do the same thing. Having public properties does not prevent me from doing this, only I use direct getters while you use getters hidden behind dynamic properties.

PHP Code:

$blog =BlogEntry::find('one',array('include'=>'user','id'=>10));

That is a simple example of how useful being able to overload a model instance can be. Without dynamic properties each association would also need to be defined as a public member to accomplish a similar functionality.

I see what you mean - you have this functionality built into a single base class from which all active records extend, right? My approach is a bit different - indeed I use public members to achieve this but I don't see it as a problem because they are auto-generated, they don't add to execution time at all if you have opcode cache, actually they are faster because the base class needs to have some universal functionality to be able to serve all of the active records while the public method (getter) is written (generated) specifically for this active record (table) and can go straight to execution what is necessary. But perhaps the speed difference is not that big depending on your implementation.

In the previous scenario how would one easily count the number of blogs per a user?

I simply define a method $blog->countUsers() or setup my generator to generate it for me. Or, I fetch the user object using a join sql like in the example later on.

The solution is to overload the already overloaded model using dynamic fields. In this case a dynamic field named blogs_per_user will be overloaded as a property that contains the aggregate data. That result set data could then be accessible through the dynamic property blogs_per_user on a BlogEntry object. Something that wouldn't be possible at all without dynamic properties because the name and calculation is determined at run time.

Again, it's very possible and I do it all the time with methods(). Perhaps dynamic properties will lead to less code in the active record classes but at the expense of slower execution compared to separate methods. But I think I see your point and it doesn't look like a bad system at all.

Using a join the system can be even more flexible by getting the number of blogs per user even if the user doesn't have any blogs.

This is what I wanted to avoid in my own implementation because for my liking this User::find() abstracts too much from the db and sql and uses a completely different method of accessing data. Why learn and support 2 ways of accessing the same thing? I prefer a more direct approach:

This is just my preference and I understand you may like your code better. I'm not really fond of sending complicated criteria to a class so that it can build the right sql for me - it's not really clearer for me because I feel comfortable with sql and I like to see what is being sent to the db and this makes db optimization way easier e.g. when I need to create indexes or optimize queries in some other way. Not to say that direct sql is much faster. But again, I don't need to work with multiple database systems so this is not an issue for me. I would certainly write the proper sql several times faster than the kind of code you showed above - not to say how much easier it would be for me to correct any errors in case I make a mistake.

The code above may look scary as it allows me to load any data to the $users object with sql, even data from other tables which shouldn't normally be loaded there. While this allows me to abuse the active record by supplying wrong sql I am not going to shoot myself in the foot but use this freedom for something useful.

These are things that I've found make the ActiveRecord system incredibly flexible, easy to use and powerful. I wrote my own implementation based on desire to always use it. Therefore, it supports almost all circumstances which I can think of including subqueries.

At the same time though I've also broke certain "rules" pertaining to a ActiveRecord to accomplish functionality that would otherwise be almost impossible to implement. So if you believe breaking with tradition will lead to a more useful system then I won't stare you away. ActiveRecord, Gateway, etc all that really matters in the end is what the thing does in my opinion and how efficient, scalable and reusable the solution is. Call it whatever you may if succeeds in those areas pattern or not.

I agree with you on this. I certainly broke many rules designing my (semi-?)active record because I felt constrained by too many strict rules of the ones I knew. And besides I wanted something quite fast so I had a bit of efficiency in mind. But it all comes down to coding preferences, I feel comfortable with public properties and plain sql and while I don't need to use them I feel more freedom when they are available. I create public members if I need a dynamic functionality and it works.

It doesn't seem like your trying to write a reusable code base. I've been providing recommendations and examples based on writing a reusable library not hard coding everything. My library is based on the idea that anything that extends the ActiveRecord class inherits the same functionality as all other ActiveRecord(s) – nothing is hard wired. So it seems you have a different goal mind in which case you should probably ignore everything I've said.

Here is another simple use for overloading. This would not be possible without overloading because the release_day,release_year and release_month are calculated at run time. These fields are not native to the MusicAlbum model.

I think that feature is well worth the use of dynamic properties. I'm sure there has come a time when you or anyone else for that matter have needed access to fields that were not native to the model. Using overloading makes that partly possible. Otherwise that exception would need to be hard coded into class. However, by making everything dynamic and generic the model files never need to be touched.

This is what I wanted to avoid in my own implementation because for my liking this User::find() abstracts too much from the db and sql and uses a completely different method of accessing data. Why learn and support 2 ways of accessing the same thing? I prefer a more direct approach:

There are two main problems I've come to realize when moving information from the database to the domain. Those two problems are creating the query and collecting the result into meaningful structure. In a one to many or many to many relationship the result set will always have repeating data. Collecting that data into a meaningful hierarchical structure while eliminating repeating data on the application level requires a way to know what depth each table/model refers to and a way to identify a unique row. This requires that the query be built dynamically because the collection object needs to know how to recreate a tree like structure from a one-dimensional result set.

So for simple queries this isn't really needed. However, you can only get by with that one dimensional relationship for so long. besides its very restrictive. Only being able to manage one model at a time just doesn't cut my requirements and seems like laziness. Its very easy to make a ActiveRecord or ORM that only manages one relational table. However, its practical use doesn't travel very far in my opinion and experience.