If you need capabilities provided by a third-party class, and if you don't want to copy this class in one of the symfony lib/
dirs, you will probably install it outside of the usual places where symfony looks for files. In that case, using this class will imply a manual require
in your code, unless you use the symfony spl autoload integration to take advantage of the autoloading.
Symfony doesn't (yet) provide tools for everything. If you need a PDF generator, an API to Google Maps, or a PHP implementation of the Lucene search engine, you will probably need a few libraries from the Zend Framework. If you want to manipulate images directly in PHP, connect to a POP3 account to read e-mails, or design a console interface, you might choose the libraries from eZcomponents. Fortunately, if you define the right settings, the components from both these libraries will work out of the box in symfony.
First, you need to declare (unless you installed the third-party libraries via PEAR) the path to the root directory of the libraries in the application's app.yml
:
all:
zend_lib_dir: /usr/local/zend/library/
ez_lib_dir: /usr/local/ezcomponents/
swift_lib_dir: /usr/local/swiftmailer/
Then, extend the PHP autoload system by specifying which library to consider when the autoloading fails with symfony. You can do this by registering the autoload classes in the application configuration class (see Chapter 19 for more information), as in Listing 17-9.
Listing 17-9 - Extending the Autoloading System To Enable Third Party Components, in apps/frontend/config/ApplicationConfiguration.class.php
class frontendConfiguration extends sfApplicationConfiguration
{
public function initialize()
{
parent::initialize(); // load symfony autoloading first
// Integrate Zend Framework
if ($sf_zend_lib_dir = sfConfig::get('app_zend_lib_dir'))
{
set_include_path($sf_zend_lib_dir.PATH_SEPARATOR.get_include_path());
require_once($sf_zend_lib_dir.'/Zend/Loader.php');
spl_autoload_register(array('Zend_Loader', 'autoload'));
}
// Integrate eZ Components
if ($sf_ez_lib_dir = sfConfig::get('app_ez_lib_dir'))
{
set_include_path($sf_ez_lib_dir.PATH_SEPARATOR.get_include_path());
require_once($sf_ez_lib_dir.'/Base/base.php');
spl_autoload_register(array('ezcBase', 'autoload'));
}
// Integrate Swift Mailer
if ($sf_swift_lib_dir = sfConfig::get('app_swift_lib_dir'))
{
set_include_path($sf_swift_lib_dir.PATH_SEPARATOR.get_include_path());
require_once($sf_swift_lib_dir.'/Swift/ClassLoader.php');
spl_autoload_register(array('Swift_ClassLoader', 'load'));
}
}
}
What happens when you create a new object of an unloaded class is simple:
- The symfony autoloading function first looks for a class in the paths declared in the
autoload.yml
file. - If no class path is found, the callback methods registered by
spl_autoload_register()
calls will be called one after the other, until one of them returnstrue
. So each ofZend_Loader::autoload()
,ezcBase::autoload()
, andSwift_ClassLoader::load()
are called until one finds the class. - If these also return
false
, PHP will generate an error.
This means that the other framework components benefit from the autoload mechanism, and you can use them even more easily than within their own environment. For instance, if you want to use the Zend_Search
component in the Zend Framework to implement an equivalent of the Lucene search engine in PHP, you usually need a require
statement:
require_once 'Zend/Search/Lucene.php';
$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl));
// ...
With symfony and spl autoloading, it is simpler. You can omit the require
statement and stop worrying about include paths and class locations:
$doc = new Zend_Search_Lucene_Document(); // The class is autoloaded
$doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl));
// ...