Doctrine is a product of the work of many people. Not just the people who have coded and documented this software are the only ones responsible for this great framework. Other ORMs in other languages are a major resource for us as we can learn from what they have already done.
Doctrine has also borrowed pieces of code from other open
source projects instead of re-inventing the wheel. Two of the
projects borrowed from are symfony
and the Zend Framework. The relevant
license information can be found in the root of Doctrine when you
download it in a file named
Doctrine is divided into three main packages: CORE, ORM and DBAL. Below is a list of some of the main classes that make up each of the packages.
Doctrine DBAL is also divided into driver packages.
Other miscellaneous packages.
There are also behaviors for Doctrine:
GoF (Gang of Four) design patterns used:
- Singleton, for forcing only one instance of Doctrine_Manager
- Composite, for leveled configuration
- Factory, for connection driver loading and many other things
- Observer, for event listening
- Flyweight, for efficient usage of validators
- Iterator, for iterating through components (Tables, Connections, Records etc.)
- State, for state-wise connections
- Strategy, for algorithm strategies
Enterprise application design patterns used:
- Active Record, Doctrine is an implementation of this pattern
- UnitOfWork, for maintaining a list of objects affected in a transaction
- Identity Field, for maintaining the identity between record and database row
- Metadata Mapping, for Doctrine DataDict
- Dependent Mapping, for mapping in general, since all records extend Doctrine_Record which performs all mappings
- Foreign Key Mapping, for one-to-one, one-to-many and many-to-one relationships
- Association Table Mapping, for association table mapping (most commonly many-to-many relationships)
- Lazy Load, for lazy loading of objects and object properties
- Query Object, DQL API is actually an extension to the basic idea of Query Object pattern
- Lazy initialization - For collection elements
- Subselect fetching - Doctrine knows how to fetch collections efficiently using a subselect.
- Executing SQL statements later, when needed : The connection never issues an INSERT or UPDATE until it is actually needed. So if an exception occurs and you need to abort the transaction, some statements will never actually be issued. Furthermore, this keeps lock times in the database as short as possible (from the late UPDATE to the transaction end).
- Join fetching - Doctrine knows how to fetch complex object graphs using joins and subselects
- Multiple collection fetching strategies - Doctrine has multiple collection fetching strategies for performance tuning.
- Dynamic mixing of fetching strategies - Fetching strategies can be mixed and for example users can be fetched in a batch collection while users' phonenumbers are loaded in offset collection using only one query.
- Driver specific optimizations - Doctrine knows things like bulk-insert on mysql.
- Transactional single-shot delete - Doctrine knows how to gather all the primary keys of the pending objects in delete list and performs only one sql delete statement per table.
- Updating only the modified columns. - Doctrine always knows which columns have been changed.
- Never inserting/updating unmodified objects. - Doctrine knows if the the state of the record has changed.
- PDO for database abstraction - PDO is by far the fastest availible database abstraction layer for php.
This chapter should have given you a complete birds eye view of all the components of Doctrine and how they are organized. Up until now you have seen them all used a part from each other but the separate lists of the three main packages should have made things very clear for you if it was not already.
Now we are ready to move on and learn about how to deal with Doctrine throwing exceptions in the Exceptions and Warnings chapter.