Note: This wiki is an enlargement and clarification for the original instructions in zcho's forum post.
Replacing Propel with ezPDO
Quick Pros & Cons
It is not within the scope of this document to extensively review the advantages and disadvantages of using ezPDO instead of Propel. The last known review extensive enough to compare the two is the June 2005 PHP Architect article, Cross The Divide, and ezPDO made a response to this article soon after: Comments on Cross The Divide. Both are now outdated and a rigorous comparison has not been made since. So, if you are interested in using ezPDO, know that you are treading lesser known territory. For those of you who are lazy, here is a quick review of the differences, but please look at the ezPDO website for a full list of their features.
Advantages of ezPDO
Easy Object Oriented ORM: Instead of a schema.xml, you create classes and class properties. ezPDO discovers their database characteristics through a simple @orm PHPDoc tag. It has a secondary advantage of encouraging you to document your database model. You are able to make base classes, use inheritance and exploit polymorphism just like the rest of your application. ezPDO discovers aggregration, composition and other patterns intuitively. In other words, no more table definitions which are the same except one or two columns. Just make a base class.
OQL: If you have special relationships you want to eek out of your Propel object model, you most likely do it with a custom SQL statement. OQL is a SQL-like language which understands object relations but has similar flexibility as SQL. ezPDO's version, EZOQL, takes full advantage of this concept and makes it easier for you to define custom statements without using messy or complicated SQL.
More efficient type handling: Propel is very loose with its data types (e.g. BOOLEAN = INTEGER for MySQL 4.1). You can't use ENUM or other custom types very easily (though apparently this functionality is coming soon). ezPDO allows more customised data types to appear in your object model and so allows you to optimise your database model to a greater degree.
Automatic Compile & Update: This is just nifty. Sick of regenerating your models and hand-editing a live database? ezPDO does it all for you when there's a change to your object models, so the only changes to your database you need to make are to your object model classes.
Small Memory Footprint: Because it does not create redundant peer and object files for every table, the only libraries loaded are the generic accessors, mutators, connection handling, database abstraction layer and compiler (if needed). Propel loads most of that 2MB or more of redundant material in your project's lib/model directory, a terrifying prospect if you have a very high traffic site or a 8MB memory restriction (default distribution php.ini).
Problems with ezPDO
DB Performance: One of the first differences you will see between Propel and ezPDO is that the latter uses more queries to accomplish the same task as Propel. Although it no longer has critically large query counts, it needs more optimisation. The ezPDO team is actively working on this problem. The overall performance of ezPDO is noticably better than Propel's because it has a centralised core of generic accessors and mutators (which Propel needs to generate for each table), but this means methods like doSelectJoinContact will need to be hand-written with EZOQL.
PDO Compatibility: At the time of writing, ezPDO's support for PDO is in beta and included with the latest release. You are welcome to play with it, but it is recommended that you use ADODB or ADODB_Lite for your ezPDO installation until they have ironed out all the problems with their PDO implementation.
Maturity: While both Propel and ezPDO deal with M:N relationships, the more explicit approach by Propel may lead you to the conclusion that it is the more mature of the two. In the end, Propel boasts more features with less hassle. You deal with objects directly and if you need to make a transaction, you can create a special case of it. ezPDO's transactional support is still shaky because it does not yet allow you to specify, for MySQL particularly, the table type (it defaults to MyISAM). So, foreign keys, indexes, etc. are either not supported or emulated through additional tables and therefore additional queries.
Not integrated into Symfony: This is the primary reason you may be encouraged to drop ezPDO. You must get the epManager instance each time you want to access your database and this pollutes your application with unnecessary clutter. Later in this wiki, we describe a way to make ezPDO a little more integrated.
You will need to have a little knowledge about your symfony installation to get ezPDO working. Gather up the following details before proceeding with the installation:
- the base directory for your PEAR packages. It should be something like /usr/share/php (for Debian 3.1) or /usr/local/php5/lib/php (entropy.ch 5.1 for Mac OS X).
- SF_SYMFONY_LIB_DIR = the base directory of your symfony package. This should in PEAR_DIR/symfony.
- SF_SYMFONY_DATA_DIR = the base directory of symfony data files. This should be in PEAR_DIR/data/symfony.
- SF_ROOT_DIR = the base directory for your symfony project, such as /home/user/myproj.
- SF_LIB_DIR = the library directory for your symfony project, such as /home/user/myproj/lib.
Tip: These constants correspond directly to the sfConfig::get() constants except PEAR_DIR. If you are unsure, just create a script in symfony which dumps out these variables. Also, you can set these constants in your shell (if using bash) while following this installation tutorial.
1. Downloading ezPDO
You need to download the latest stable release directly from the ezPDO website: ezPDO releases.
And install the sfEzpdo plugin:
symfony plugin-install global symfony/sfEzpdo OR sudo pear install symfony/sfEzpdo
2. Unpack ezPDO
To be consistent with the current symfony approach of placing its dependent packages inside its own library, we put ezPDO in the same base directory as the Propel installation:
cd $SF_SYMFONY_LIB_DIR/vendor tar -zxvf ~/downloads/ezpdo.1.1.0rc3.tar.gz ln -s ezpdo.1.1.0rc3 ezpdo
If you are on Windows, just change the name of the directory to ezpdo.
3. Autoloading ezPDO
For ezPDO to load in your application, you need to tell symfony where it is. The sfEzpdo plugin comes with two files, which you can find in SF_SYMFONY_LIB_DIR/plugins/sfEzpdo. We need to make a minor adjustment to sfEzpdoAutoload.class.php:
- sfConfig::get('sf_symfony_lib_dir').'/symfony/ezpdo', + sfConfig::get('sf_symfony_lib_dir').'/vendor/ezpdo',
You also need to edit SF_SYMFONY_DATA_DIR/config/autoload.yml:
symfony_orm: name: symfony orm classes files: Propel: %SF_SYMFONY_LIB_DIR%/addon/propel/sfPropelAutoload.php Criteria: %SF_SYMFONY_LIB_DIR%/vendor/propel/util/Criteria.php SQLException: %SF_SYMFONY_LIB_DIR%/vendor/creole/SQLException.php DatabaseMap: %SF_SYMFONY_LIB_DIR%/vendor/propel/map/DatabaseMap.php + epManager: %SF_SYMFONY_LIB_DIR%/plugins/sfEzpdo/sfEzpdoAutoload.php
4. Set Configuration
In SF_ROOT_DIR/apps/frontend/config/databases.yml, put the following lines:
default: class: sfEzpdoDatabase param: dsn: mysql://ezpdo:ezpdo@localhost/ezpdo_dev db_lib: adodb auto_flush: true autoload: true source_dirs: ../lib/ezpdo-model
This will replace your Propel database configuration, which should be renamed to something else.
Note: Examine SF_SYMFONY_LIB_DIR/plugins/sfEzpdo/sfEzpdoDatabase.class.php to see what the default configurations are. You can and should set practically all of ezPDO's options through databases.yml.
5. ezPDO INI file
Now copy the ezpdo.ini file from one of the example cases in the ezPDO distribution. The XML version is also supported, but you will need to change sfEzpdoAutoload to use ezpdo.xml rather than ezpdo.ini.
cp $SF_SYMFONY_LIB_DIR/vendor/ezpdo/examples/book/config.ini $SF_ROOT_DIR/config/ezpdo.ini
Check the variables set in this file. There are some problems with the sfEzpdo 1.0.0 handling of configuration which means that these values can be overridden by the defaults in sfEzpdoDatabase::getConfig(). The configuration file is really there for completeness and forward compatibility.
You should create some example object models in SF_ROOT_DIR/lib/ezpdo-model. Follow the ezPDO simple and advanced tutorials on their website for some good pointers in the right direction and have a peak at SF_SYMFONY_LIB_DIR/vendor/ezpdo/examples. You should get a good idea of how you will be using this fantastic little library.