= Basic Relationships = Propel support for relationships between objects maps directly to the way that databases support relationships between tables using foreign keys. Relationship support in Propel is therefore easy to understand, but it also inherits some of the simplicity of this model; for example, Propel doesn't hide the fact that you must use a cross-reference table for many-to-many relationships (see the [wiki:Documentation/1.3/ManyToManyRelationships Many-to-Many Relationships] page for more on that topic). == Defining Relationships == Relationships are specified by creating foreign keys in the related '''' sections of your {{{schema.xml}}} file. You use the '''' tag to create a relationship between one table and another, using the same basic principle that you would use in relating one table to another at the database level. {{{ #!xml
}}} Propel will use this information to: * Generate native FOREIGN KEY creation SQL in your DDL file (e.g. {{{schema.sql}}}) and * Create getter & setter methods in your generated objects (e.g. ''Book'' will have a ''getAuthor()'' and ''setAuthor()'' method) === One-to-One Relationships === Propel 1.3 supports special case one-to-one relationships (see ticket:279). One-to-one relationships are defined when the primary key is also a foreign key. For example (simplified from bookstore schema.xml): {{{ #!xml
}}} Because the primary key of the ''bookstore_employee_account'' is also a foreign key to the ''bookstore_employee'' table, Propel interprets this as a one-to-one relationship and will generate singular methods for both sides of the relationship -- e.g. '''!BookstoreEmployee->getBookstoreEmployeeAccount()''' and '''!BookstoreEmployeeAccount->getBookstoreEmployee()'''. == Fetching Related Objects == Using the example above (based on provided bookstore schema), you would have a ''Book->getAuthor()'' that would return an ''Author'' object using the specified foreign key. {{{ #!php getAuthor(); } }}} The above code would result in the execution of 1+n SQL statements, where n is the number of books (and hence number of iterations of the ''foreach'' loop): 1. 1 x SELECT * FROM book 1. n x SELECT * FROM author WHERE author_id = ''$book->getAuthorId()'' While clearly this method works, it is not optimal to execute that second query for each iteration. Propel also generates methods in your base peer class to fetch both book and author information in a single query using a left join^*^. {{{ #!php getAuthor(); } }}} In the above case only a single query is performed: 1. SELECT * FROM book LEFT JOIN author ON author.author_id = book.author_id Continue reading the [wiki:Documentation/1.3/ManyToManyRelationships Many-to-Many Relationships] page for a treatment of this more-advanced realtionship topic. ^*^ Note that in Propel 1.3 the behavior changed from performing INNER JOIN to using LEFT JOIN by default. Please see wiki:Documentation/1.3/Upgrading for more information and instructions on how to keep the original INNER JOIN behavior if your application depends on this. == Using Relationships in Criteria == You can create queries that use relationships using the '''doSelectJoin*()''' methods or by explicitly specifying joins in the Criteria object (see [wiki:Documentation/1.3/Criteria]). In either case, you can add expressions for any of the joined tables to the Criteria object: {{{ #!php addJoin(AuthorPeer::ID, BookPeer::AUTHOR_ID, Criteria::INNER_JOIN); $c->addJoin(BookPeer::PUBLISHER_ID, PublisherPeer::ID, Criteria::INNER_JOIN); $c->add(PublisherPeer::NAME, 'Some Name'); $authors = AuthorPeer::doSelect($c); }}} ... would be equivalent to: {{{ #!sql SELECT * FROM author INNER JOIN book ON book.author_id = author.id INNER JOIN publisher ON publisher.id = book.publisher_id WHERE publisher.name = 'Some Name' }}} == Overriding PHP Names for Relationship Getters/Setters == As of Propel 1.3 (see ticket:23), it is possible to provide PHP names for the methods that are created for fetching related foreign key objects. You can specify foreign key ''phpName'' and ''refPhpName'' attributes in the element. Hopefully an example will make the implementation (and motivation for this feature) clear: {{{ #!xml
}}} This is an example from a self-referencing table in bookstore schema.xml. The ''phpName'' attribute affects naming of methods like '''setSupervisor()''', while the ''refPhpName'' attribute affects naming of methods that work with the referencing foreign keys -- e.g. '''addSubordinate()''', '''getSubordinates()'''. == On-Update and On-Delete Triggers == Propel also supports the ''ON UPDATE'' and ''ON DELETE'' aspect of foreign keys. These properties can be specified in the '''' tag using the ''onUpdate'' and ''onDelete'' attributes. Propel supports values of 'CASCADE', 'SETNULL', and 'RESTRICT' for these attributes. For databases that have native foreign key support, these trigger events will be specified at the datbase level when the foreign keys are created. For databases that do not support foreign keys, this functionality will be emulated by Propel. {{{ #!xml
}}} In the example above, the ''review'' rows will be automatically removed if the related ''book'' row is deleted.