Enhanced Database Joins
This week's new feature is way down at the framework level. The InnerJoin class has been around for years, but until now there was no support for other database joins. Well now there is.
The InnerJoin class has been refactored into an abstract base class AbstractJoin and
a concrete implementation class, which keeps the name InnerJoin. You still use it the same way as before:
$join = new InnerJoin();
$join->add(Employee);
$join->add(Office);
$results = $join->query("WHERE salary < 40000");
This would return an inner join across the two tables, meaning that employees that were not assigned to an office would not be returned in the result set. The only difference (behind the scenes) is that the result objects being returned are now of class JoinResult rather than InnerJoinResult as was previously the case. This is just a renaming to more correctly describe the class, since there is now more than one type of join.
So, how would we get a result returning the Employees not assigned to an Office? Simple:
$join = new LeftOuterJoin();
$join->add(Employee);
$join->add(Office);
$results = $join->query("WHERE salary < 40000");
For employees with no related office an empty Office object is included in the returned JoinResult. And the nicest thing about this is that because InnerJoin and LeftOuterJoin both share the same base class, they can be used interchangeably. For instance, the custom reporting module in Fakoli now has an option "Include Incomplete Matches in Results" which swaps the search mode. The implementation of this is nice and easy:
$mode = $_GET["join_mode"]);
$joinClass = ($mode == "outer") ? LeftOuterJoin : InnerJoin;
$join = new $joinClass();
$join->add(Employee);
$join->add(Office);
$results = $join->query("WHERE salary < 40000");
How about other database joins?" I hear all you database theorists cry. Well, in practical terms if you have Inner and Left Outer Joins, you have the most common use cases covered. Right Outer Joins are just Left Outer Joins backwards, so you can almost always rewrite them as such. Cross Joins (Cartesian Joins) are mostly useful as set-theoretic constructs used within a database view - NEVER use them in application logic. Full Outer Joins might be useful, but for now we will follow the Fakoli mantra of not building things until you need them.
If you need a quick reference to the specifics of different joins, look here:
http://en.wikipedia.org/wiki/Join_%28SQL%29
A couple of format() improvements » « Component upgrade dependency resolution
