PHP, Query Object Pattern


This continues the discussion of Martin Fowler’s Object Query pattern from the book Patterns of Enterprise Application Architecture. The previous discussion about the Metadata mapper pattern talked about how to map domain objects to database results.

These discussion are really a brief overview of Microsoft’s Repository Factory and how they use Fowler’s patterns with a quick consideration on how to apply the technique to PHP.

Query Object pattern is defined by Fowler as …

A Query Object is an interpreter [Gang of Four], that is, a structure of objects that can form itself into a SQL query. You can create this query by referring to classes and fields rather than tables and columns. In this way those who write the queries can do so independently of the database schema and changes to the schema can be localized in a single place.

In the repository factory these query objects are defined with interfaces representing all the CRUD methods. These interfaces include ISelectFactory<TDomainObject>, IInsertFactory<TDomainObject>, IDeleteFactory<TDomainObject>, and IUpdateFactory<TDomainObject>. These interfaces extend the IDbToBusinessEntityNameMapper interface discussed in the metadata mapper post. As you can see C# generics are also used as part of the interface. The interfaces require their implementing classes to implement a “Construct Command” method. For example the IInsertFactory requires the implementation of the method ConstructInsertCommand(Database db, TDomainObject domainObj) where the database object is passed in with the domain object. The ‘construct’ methods return a DbCommand object (defined in the Enterprise Library’s Data Access Application Block). This command represents the SQL call, in the case of the Repository Factory this is a call to a CRUD stored procedure. Because the Query Object interfaces also implement IDbToBusinessEntityNameMapper each implementing class must also implement MapDbParameterToBusinessEntityProperty method which accepts a string representing the queries parameter name and it returns the associated domain object string name. This is used by the repository class (to be discussed in another post) to map the domain object into the Query Object.

Because I am covering the Repository Factory this does not mean that this is the only way to implement the Query Object. In the book Fowler takes a different approach in creating a Query Object that builds a SQL query through calling methods on the object. From one of his examples (in Java) …

class Criteria…

1
2
3
4
5
6
7
8
9
10
11
   public static Criteria greaterThan(String fieldName, int value) {
       return Criteria.greaterThan(fieldName, new Integer(value));
   }
   public static Criteria greaterThan(String fieldName, Object value) {
       return new Criteria(" > ", fieldName, value);
   }
   private Criteria(String sql, String field, Object value) {
       this.sqlOperator = sql;
       this.field = field;
       this.value = value;
   }

Which could be used in the following manor …

1
2
      QueryObject query = new QueryObject(Person.class);
      query.addCriteria(Criteria.greaterThan("numberOfDependents", 0));

Though he himself admits this works fine with simple statements but once the statement is required to have more complexity this approach can get messy. I think Microsofts approach toward stored procedures was a good compromise that would ensure a simple interface for the Query Objects and would allow for complexity to be hidden in the stored procedures themselves.

It is interesting to know that Microsoft has discontinued support for the Repository Factory in favor of their new EntityFramework (ORM solution) which makes the dependency on stored procedures less desirable.

How could we apply this to a PHP persistence layer using code generation? I think the generics would not be necessary due to the fact the PHP is not strongly typed. More intelligence would had to be added since Microsoft uses the DbCommand classes (which in themselves or query objects). One would certainly implement Fowler’s example and build parametrized query builders, or the use of the build in PHP query functions could be used and encapsulated by the factory interfaces. I have not honestly had enough exposure to PHP at this point to truly make a suggestion. The danger here would be to implement the same pattern that Microsoft came up with in PHP and probably miss the mark due to the fact that Microsoft made decisions that suited features and limitation in the .NET framework that may or may not be necessary or correct in PHP. I am certainly open for suggestions.

Share on Facebook Share on Facebook


Write a Comment

Take a moment to comment and tell us what you think. Some basic HTML is allowed for formatting.

Reader Comments

good tutorial , really helpful for me…