Atlas ORM 1.2.0 Released

The 1.2.0 release adds the ability to define WHERE conditions on relationships. (The 1.1.0 release added functionality to ignore foreign key string case when wiring up objects in memory, and 1.0.0 was released pretty quietly a couple of weeks ago.)

Try it out today, because you like keeping your persistence layer separate from your domain layer.

Now, read on for some history, if you care about that kind of thing.


Many years ago, we on the Solar project developed Solar_Sql_Model, an Active Record type of ORM. Overall I liked it well enough, though (as with anything) it had its strengths and weaknesses.

Since then, after extracting the Solar components to Aura libraries, I’ve mostly lived without ORMs. The majority of my legacy consulting work has not made use of them; where a legacy project did have an ORM of some sort, it was a custom in-house piece of work.

However, about three years ago, I hired on with a startup to build out their backend from scratch. At the time, I wanted to do “real” Domain-Driven Design, with entities and aggregates and value objects and everything else. That meant keeping the domain system separate from the persistence system, and that in turn meant Active Record was not an option. Doctrine, a domain model data mapper, was the next logical choice, but on review it was not to my liking. (The annotations, among other things about Doctrine, just rubbed me the wrong way.)

So instead of an Active Record implementation, or Doctrine, I figured that it would be enough to use a Table Data Gateway on top of Aura.Sql and Aura.SqlQuery to retrieve rows, then map the rows over to domain objects. This was fine, for as far as it went, but the problem was “relationships.” Oh dear Codd, the relationships.

Selecting one or many objects from a single table was no big deal, but doing multiple selections from multiple tables and building up the selection statements for those relationships was a tedious, tiresome, and time-consuming burden. (Wiring them up in memory once they’d been selected was not too bad, given Aura.Marshal, but it was still more effort than I’d’ve rather been expending.)

So it all “worked,” but it was just not satisfying at all. The DDD portions, for their part, worked out great, as did the separation of the domain layer from the persistence layer, so I was pretty sure I was on something like the right track.

Then I read this article from Mehdi Khalili. It’s fantastic and you should read the whole thing. In summary, Khalili points out that it is perfectly reasonable to use a persistence model in addition to a domain model. That is, you do not necessarily have to map directly from the database to domain objects; you can map from the database to persistence objects for the data, and then later compose or map the persistence model into the domain model for behaviors.

This was a revelation to me, something that I’d never considered, or even heard of before. It alleviates wide swaths of DDD-related burdens.

As a result of my relationship-related burdens at the startup, and after reading the Khalili article, I put together Atlas, a mapper for your persistence model. Like everything else I’ve been doing for the past several years, Atlas is built in discrete layers:

  • PDO at the very bottom;
  • Aura.Sql around that, to provide convenience methods for binding and fetching;
  • Aura.SqlQuery in parallel, to support query building;
  • all of those composed into a table data gateway system to emit Row objects from tables;
  • and finally a mapper system on top of that to emit Record objects composed of table Rows and their relationships

As such, each Record object is composed of a Row (from the “main” table) and its Related objects (themselves Records, each of which is composed of a Row and Relateds, and so on).

Atlas uses the term “Record” to indicate that the object is not a domain entity or aggregate. You can use Records directly for straightforward CRUD/BREAD operations, or you can map them over to your domain objects.

Fetching deep relationship structures is no big deal; see this article from Andrew Shell using 25 tables in different complex relationships. (Andrew’s project also shows how to keep the persistence and domain layers separate, and incorporates a debug bar implementation for Atlas.)

So, if you want a data mapper implementation that models your persistence layer, and the relationships therein, Atlas is just the thing for you. Try it out today!

If you inject a container into your class, you are using Service Locator, not Dependency Injection

A while ago I tweeted

ContainerAware is the new Singleton.

While many people agreed by retweeting and faving. I feel the need to elaborate some more on this statement and safe the explaination for the future.

TL;DR: No class of your application (except for factories) should know about the Dependency Injection Container (DIC).

The ContainerAware interface (actually ContainerAwareInterface, ContainerAware is a basic implementation of it) is part of the Symfony2 API, but a similar concept is known from many other frameworks and many applications rely on it. It defines only the one method setContainer(), which allows to inject the DIC into into an object so that it can directly retrieve services from it.

I wouldn’t call it “the new Singleton”, I’d call it “Service Location.” If you use a dependency injection container inside your class to bring dependencies into the object, you are using Service Locator, not Dependency Injection. Solar used SL, but when we started Aura (a collection of truly decoupled library packages, each with no dependencies) we switched over to DI proper. Real DI has been a huge win.

Via ContainerAware Considered Harmful – Qafoo GmbH – passion for software quality.

Aura for PHP 5.3+, aka Solar 2.0

Measuring from the first Subversion commit, Solar was 6 years old on 14 Feb 2011. The project has come a long way since then, and has evolved from a collection of library classes with some content domain models, to a general purpose framework.

Moore’s Law tells us computer power doubles about every 18 months; it’s how we measure generations for computers. 6 years is 4 generations, which makes Solar the equivalent of an 80 to 100 year old person. Just like with a mature person, there is a great deal of knowledge and craft embedded in Solar, but it also still shows its roots and carries the weight of decisions from early in its life.

With all that in mind, it’s time to start working on Solar version two, using the formal namespaces and other features of PHP 5.3. There are some other very significant changes on the way as well.

The first change is the name of the project. Even though Solar (the PHP 5 framework) came first, the name is too easy to confuse with Apache Solr (the search system). So, after some discussion with others, Solar v2 will be called Aura.

The second change is in the fundamental organization of the project. Solar became a full-stack framework very quickly, with all classes descending from a base class, and using and a service locator to manage dependencies. By comparison, Aura is a collection of independent library packages; it uses no base classes, and is oriented toward a dependency injection container proper to manage dependencies. Aura also has an additional “system” package that assembles those libraries into a cohesive framework (the way Solar is now). That way, those who want to use only one or two Aura packages can do so, and developers who want a full framework can also get what they need.

There are lots of other significant changes, and I expect I’ll write about those in the future. Until then, if the project sounds interesting, you can find the Github repos at https://github.com/auraphp. Aura also has a mailing list at https://groups.google.com/group/auraphp, and you can join the IRC room on Freenode at #auraphp.

Meanwhile, Solar will keep getting as much love and attention as it has over the past year or so. But I do expect, eventually, that we will be able to extract all the best Solar behaviors to Aura. Solar won’t ever really go away (software projects almost never do), but I expect it will be eclipsed by Aura at some point in the future.

You can see what Aura looks like by examining the various Aura packages already in place:

  • Aura.Autoload, an autoloader package
  • Aura.Di, a dependency injection container,
  • Aura.Router, a web routing system,
  • Aura.Signal, a signal slots / event handler implementation,
  • Aura.Cli, a collection of command-line tools, and
  • the system package that provides a framework around the libraries

Take a look around; I hope PHP 5.3+ developers who want independent library packages will like what they see.

Solar 1.1.1 Stable Released

On Thursday, I released version 1.1.0 of the Solar Framework for PHP. Due to a small but critical bug in the PostgreSQL adapter, I released version 1.1.1 with the necessary fix earlier today. Change notes are here for 1.1.0, and here for 1.1.1.

The single biggest new feature in this release of Solar is a Markdown plugin set for DocBook, along with a new make-docbook command to convertAPI documentation to DocBook files. Previously, the Solar API documentation was wiki-like; now, we take the Markdown-based comments in the codebase and convert them to DocBook, and render the DocBook files in to HTML using PhD. (Incidentally, I tried rendering with xsltproc; after three hours, the processing was less than one-third complete. With PhD, rendering takes under five minutes for the entire API documentation set.)

Also, the make-model command now recognizes a star at the end of the model name, indicating it should make one model class set for each table in the database. For example, this will make one model class from the table "foo_bar" …

./script/solar make-model Vendor_Model_FooBar

… but this will make a Vendor_Model class for each table in the database:

./script/solar make-model Vendor_Model_*

That kind of thing is helpful when getting started with an existing set of tables, or when you’re updating your models after schema changes.

Other highlights include a series of small fixes, better CLI output in non-TTY environments, improved automation of CSRF form elements.

Finally, we’ve added a new manual chapter on user authentication, roles, and access control. Find out how, with some config settings, you can instantiate a single object and let it automatically handle user login/logout, role discovery, and access permissions for you! And if you want more direct control over the process, browse on over to these blog entries from CoolGoose:

If you haven’t tried Solar yet, maybe now is the time: run through the Getting Started documentation and see how you like it!

(Cross-posted from the Solar blog.)

Solar 1.0.1 Stable Released

I just released version 1.0.1 (stable) of the Solar Framework for PHP 5. You can get it from the usual places. The change notes are here.

The most significant change is a bugfix to eager fetches in the model system. When eager conditions are present, and no join type is specified, eager fetches will use an ‘inner’ join by default. This means that the eager conditions now have the proper effect when using count_pages.

(Cross-posted from the Solar blog.)

Solar 1.0.0 Stable Released

Yesterday, I announced the release of the 1.0.0 stable version of the Solar Framework for PHP on our mailing list. (I tagged the release four days ago on Monday, but wanted to time the announcement to go along with my Solar presentation at ConFoo.)

You can see the change notes here. The highlights are:

  • Added automatic cross-site request forgery (CSRF) protections in various layers of the system.
  • Added support for named actions (aka "named routes") in the front-controller rewrite logic; this is the "bi-directional" routing that some have asked for.
  • Optimized queries for Model::countPages() and the native-by select strategy, so that unnecessary joins against related models are not used when counting the number of pages for the native model results.

The next major steps are to revise and extend the narrative documentation, and of course fix bugs and add features as needed.

Slashdot appears to have gotten to the mailing list announcement before I blogged the release. (The commenters there show the usual range of insight, depth, wisdom, and experience. 😉 The Solar site itself, deployed on a 512M SliceHost VPS instance, appears to be handling the load. However, my WordPress blog on a separate 512M instance is getting … a bit … … slow. Guess it’s time to add wp-super-cache.

This stable release is the culmination of about five years of development effort, with important contributions from several others in the PHP community. My many thanks to everyone who helped make this release, and all the previous releases, better than I could have made it on my own.

(Cross-posted from the Solar blog.)

Solar 1.0.0beta5 Released

This past Friday, I released verion 1.0.0beta5 of the Solar Framework for PHP. You can read the change notes here.

Overall, most of the work was related to the form helpers and making them even more flexible than they were previously. We’ve also added a new manual chapter on working with models and forms.

It is super-easy to build forms out of model records in Solar. In the controller, once you have a record object, call its newForm() method to get a Solar_Form object. In the view, pass that form object to the form view helper and add a submit-process button:

echo $this->form()
          ->auto($this->form_object)
          ->addProcess('save')
          ->fetch();

Those four lines of code will build a complete form for you based on the model record, including top-level feedback and individual element invaldation messages.

The form helper is smart enough to recognize the column types and validation filters on the model record, and will use the appropriate input types accordingly. For example, booleans get checkboxes, date fields get a series of month/day/year options, and columns using validateInList or validateInKeys become selects.

You can also further customize the form presentation using the fieldset and grouping methods on the form helper. Alternatively, you can the individual form element helpers to build forms by hand.

These features have been present in Solar for years.

Finally, and I’m not making promises, but I think this is the last or next-to-last beta release. I have some tickets about query optimization from the models that I want to complete. Once those are done, I expect to make Solar’s first official stable release.

(Cross-posted from the Solar blog at http://solarphp.com/blog/read/63-solar-100beta5-released.)