back
PHP 5.4 is so nifty. And traits are mad cool.

And you might be in the same situation as me: Big product with a huge amount of customer benefit built on Symfony 1.4 with years yet to maintain it and expand on it.

So you might want to start using traits, just like me. The first thing to do was, of course, to just do it:

To which the feedback was very clear:
Fatal error: Trait 'ImageUpload' not found in /path/to/project/lib/MyClass.php
Symfony was not autoloading traits. Which is good. Symfony autoloads selectively, and you might not want to autoload every stray php file a stray programmer might have forgotten inside lib. (kidding) I found by poking around in the Symfony 1.4 sources that the method actually selecting which files get autoloaded and cached is sfAutoloadConfigHandler::parseFile. It contains a regex that filters files to contain a line that starts with nothing or whitespace, followed by the words final or abstract, and then class or interface. So a quick and dirty way to get traits autoloaded is to include a commented out mock class or interface definition in the trait file. Of course this is not pretty, but it will do if you need to autoload a couple of traits now and worry about clean code later. To clean things up you can customize sfAutoloadConfigHandler by customizing configuration files. First, create a custom configuration handler: // in lib/myAutoloadConfigHandler.php class myAutoloadConfigHandler extends sfAutoloadConfigHandler { // This method an exact duplicate of sfAutoloadConfigHandler::parseFile in Symfony 1.4.18, // with only the regex modified from (class|interface) to (class|interface|trait) static public function parseFile($path, $file, $prefix) { $mapping = array(); preg_match_all('~^\s*(?:abstract\s+|final\s+)?(?:class|interface|trait)\s+(\w+)~mi', file_get_contents($file), $classes); foreach ($classes[1] as $class) { $localPrefix = ''; if ($prefix) { // FIXME: does not work for plugins installed with a symlink preg_match('~^'.str_replace('\*', '(.+?)', preg_quote(str_replace('/', DIRECTORY_SEPARATOR, $path), '~')).'~', str_replace('/', DIRECTORY_SEPARATOR, $file), $match); if (isset($match[$prefix])) { $localPrefix = $match[$prefix].'/'; } } $mapping[$localPrefix.strtolower($class)] = $file; } return $mapping; } } Then start using it by creating or adding to your existing config/config_handlers.yml # in config/config_handlers.yml config/autoload.yml: class: myAutoloadConfigHandler file: %SF_LIB_DIR%/myAutoloadConfigHandler.php

Then clear the cache, and your trait should be autoloaded and cached by symfony, in just the same way interfaces and classes are.

To stay on the really really safe side, it is a good idea to monitor possible Symfony 1.4 maintenance releases for changes to lib/config/sfAutoloadConfigHandler before upgrading. It's unlikely to happen, but it might.

And this is how to get using a really powerful PHP 5.4 feature with your existing Symfony 1.4 project. Yay!