The alpha3 version of the Solar Framework for PHP5 has been released; you can get it from the usual locations. Of note, this will be the last alpha release of Solar; I expect to have a beta released within the next 8 weeks or so.

This entry is cross-posted from the Solar blog.

I can't believe that almost a whole year has passed since alpha2 was released. In that time we have made some significant changes to how some major Solar components work. You can read the class-by-class change notes if you like, but after a year, they are quite extensive. To point out the highlights, I'll give a broad overview in this post.

Before I do that, I would like to thank one person in particular who made this release what it is: Jeff Moore of Mashery. Jeff has done more on this release than any other contributor, making huge strides in the Model and other packages through his code, reporting, revisions, and (admittedly) nagging of me to make things better. Thank you, Jeff, for everything you have done to make this release possible.

There are lots of others who contributed in important ways, most of whom are noted in the change log with their specific achievements:

  • Jon Elofson
  • Anthony Gentile
  • Robert Gonzalez
  • Tomasz Holeksa
  • Antti Holvikari
  • Ray Kolbe
  • Kalkin
  • Dmytro Konstantinov
  • Clay Loveless
  • Rodrigo Moraes
  • Nicholas Sloan
  • Jeff Surgeson
  • Richard Thomas
  • Matthew Turland
  • Robert Treat
  • Kevin Wagner

Thanks, guys, for all your effort and attention. The project is better for your having been involved. :-)

Model Changes

Nothing has been lost. Solar models still:

  • recognize has-one, belongs-to, and has-many relationships;
  • allow eager- and lazy-fetching of related records;
  • support SingleTableInheritance;
  • save only the changed data, not the whole record;
  • perform data filtering at save() time; and
  • generate automatic form hints from the table columns.

However, much has been added, including performance enhancements across the board. Below are only a few of the highlights; for a full rundown, please review the change notes.

Less-Active Table, More-Active Record

Previously, the table-based Solar_Sql_Model class retained a lot of TableModule-like behavior from its predecessors (Solar_Sql_Table, Solar_Sql_Entity, PEAR DB_Table, etc). When combined with the Solar_Sql_Model_Record logic for inserts and updates, it became difficult to track which parts were doing what.

To remedy this, the Model class has had most of the manipulation logic stripped out of its insert/update/etc methods, and all of that special logic has been placed in the Record class. That makes the Model more like a TableDataGateway, in that it will insert and update the data you give it without attempt to massage it; as a corollary, the Record becomes more like an ActiveRecord implementation.


We have added "has-many-through" relationship descriptors. This means that models now recognize many-to-many relationships through an explicit association model.

Saving Related Records

When you save a record, it now wires up all the related record IDs for you, setting all the necessary primary key information automatically. In partcular, saving a "has-many-through" will wire up not only the related records on the foreign side of the association table, but also the related records on the association table itself.

For the "has" relationships, it then saves each of the related records and collections for you:

  • has-one records are saved as they are;
  • has-many collections are saved as they are; and
  • has-many-through collections are checked for additions and
    removals against the association table, and are saved or deleted
    as necessary; this includes saving the records on the foreign side
    of the association table

Note that automatic saving of related records does not occur on "belongs-to" relationships. You still have to save those on your own; they are necessarily precursors to the existence of the current record or collection.

Eager Fetching

Eager fetching performance has been improved in many common cases. We now have dual strategies for relating back to native record sets (using a "WHERE ... IN (...)" clause for smaller sets, or using an "INNER JOIN (SELECT ...)" strategy for larger sets). As before, eager fetching avoids the 1+N pitfall, generating only one additional query per relationship (not one per record in the native result set).

Additionally, it is now possible to chain eager fetches. That is, eager-fetched records can themselves eager-fetch their own related records, all with a single call to the Model fetch*() method.

XML-Struct Columns

Solar models support automatic application of serialize() and unserialize() to columns in the $_serialize_cols model property. We now add to this the ability to serialize and unserialize basic XML-formatted data as well, through the use of the new Solar_Struct_Xml class. (N.b.: XML structs do not support attributes.)

Among other things, this means that you can store simplified XML data in a column, and database engines capable of searching it, can search it. You can manipulate that data as XML data in PHP as well via the XML-struct mechanisms.

Non-Model Changes


The Solar arch-class has fewer static methods in it; collections of related methods have been grouped into their own classes (e.g., [Solar_Config][]).


The Solar_Base class, from which all other Solar classes extend, now has a more pluggable construction and configuration process. Hooks include:

  • _preConfig() to set up the object before configuration
  • _postConfig() to modify the object after configuration
  • _postConstruct() to complete object construction

This means that you never need to override a Solar constructor; instead, place your construction logic in the applicable hook method.

Page Controllers

The Solar_Controller_Page class now comes with a default layout and views, along with added error handling methods, making it more useful as a base page controller class in its own right. (Previously, one had to extend Solar_App_Base, or create a base app of one's own, to get these basic defaults.)

One thing has been removed: recognition of page-level view helpers. In theory, these seemed like they might be useful. However, in practice, they were rarely if ever needed. Vendor-level helpers are now the first place the views will look.

Lazy Sessions

The Solar_Session class now supports "lazy" sessions. Previously, it would start a sesssion automatically at instantiation time. Now, it starts a session only when ...

  1. A PHP session cookie already exists, or
  2. You call one of the set*() methods to store a value

This means that the session object can be available at any time, but won't invoke any session-based overhead until it is actually needed.

Make-Vendor and Model-Based Apps

The make-vendor command now generates a special page controller called {Vendor}_Controller_Model, which houses all the code for a minimal BREAD-S (browse, read, edit, add, delete, and search) application based on a model.

Previously, make-app would generate the BREAD code fresh in each new class, but when you build mutiple model-based apps, you would end up with a lot of code duplication. The new approach removes that duplication entirely. This means that make-app --model-name will now create app classes that extend from {Vendor}_Controller_Model.

Compound Selects

Solar_Sql_Adapter and Solar_Sql_Select now support UNION and UNION ALL query construction, with the related LIMIT and ORDER components of those kinds of queries.


The Solar_View_Helper_Form view helper for forms now supports different kinds of decoration: as definition list, as a table, or as "plain" (no surrounding markup). The helper itself has been significantly refactored so that the internal logic is easier to follow, and support logic has been extracted into separate classes when possible.

Much More

There is a lot more to be had. Take a look at the Getting Started documentation, then spend some time with these blog entries from Solar users:

Are you stuck with a legacy PHP application? You should buy my book because it gives you a step-by-step guide to improving you codebase, all while keeping it running the whole time.