Blog: Propel, PHP 5.3, and Namespaces: They Love Each Other

The Propel Team – 09 June 2010

Propel was originally a PHP4 port of the Java Torque library - that was a long time ago. It was ported to PHP5 quite early - about five years ago. Since then, Propel has been compatible with every stable PHP release. Propel 1.5 requires PHP 5.2, but also works seamlessly with PHP 5.3. That means that if PHP 5.3 is your version of choice, you can use Propel right now - no need to wait for a new version.

But “working” doesn’t mean “taking the best advantage of”. By maintaining backwards compatibility with PHP versions less than 5.3, Propel can’t take advantage of the greatest advances of PHP 5.3 - late static binding, anonymous functions, namespaces, closures, phar, to name only a few. Or can it?

Code generation allows to modify the model classes code based on configuration. If a developer wants to use PHP 5.3 only, then why not enable some of the PHP 5.3 features in the model classes?

This is getting real with the recent introduction of namespaces in Propel 1.5. That’s right, even though Propel 1.5 requires only PHP 5.2, it can generate model classes using namespaces only supported since PHP 5.3. And this is very easy to enable: just add a namespace attribute in the <database> tag of the XML schema, rebuild the object model, and the generated classes now use the namespace:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<database name="bookstore" namespace="Bookstore" defaultIdMethod="native">
  <table name="book">
    <!-- -->
  </table>
  <table name="author">
    <!-- -->
  </table>
</database>

Now you can use the namespaced model classes by using the fully qualified name, or by aliasing the class name. The Propel runtime autoloading works as usual:

<?php
// use fully qualified name
$book = new \Bookstore\Book();

// or use an alias
use Bookstore\Book;
$book = new Book();
// remember to use the \ namespace for core Propel classes in this case
$con = \Propel::getConnection();
$book->save($con);

The namespace is used for the ActiveRecord class, but also for the Query and Peer classes. Just remember that when you use relation names in a query, the namespace should not appear:

<?php
$author = \Bookstore\AuthorQuery::create()
  ->useBookQuery()
    ->filterByPrice(array('max' => 10))
  ->endUse()
  ->findOne();

You can extend the database namespace in a given table by setting a namespace attribute of the <table> tag:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<database name="bookstore" namespace="Bookstore" defaultIdMethod="native">
  <!-- -->
  <table name="publisher" namespace="Book">
    <!-- -->
  </table>
</database>

The corresponding object model objects will use the table namespace as a subnamespace of the database namespace:

<?php
$publisher = new \Bookstore\Book\Publisher();
$publisher->save();

That’s as simple as this. You can mix classes with various namespaces in the same schema, and these classes can share relations regardless of their namespaces. All the features you love and use in Propel 1.5 - behaviors, many-to-many relationships, joined hydration - work the same for namespaced models.

The new namespace feature is available in the 1.5 branch, and soon in the stable 1.5.2 release. It is already documented, as usual - and ready for you to use it.