![]() |
|
Snippets |
|
Let say you want to write a sub-select, and have a Propel object returned.
As an example, lets generate the following SQL:
SELECT orders.ID, orders.TYPE, orders.STATUS FROM orders WHERE orders.STATUS IN ( SELECT STATUS.NAME FROM STATUS WHERE STATUS.ORDER_TYPE = 'purchase' )
Propel does not natively handle this sort of SQL. There are however two ways to create this SQL or to get this data set and have Propel objects returned.
$c = new Criteria(); $subSelect = "orders.STATUS IN ( SELECT status.NAME FROM status WHERE status.ORDER_TYPE = 'purchase' )"; $c->add(StatusPeer.STATUS, $subSelect, Criteria::CUSTOM); $orders = StatusPeer::doSelect($c);
Example of the rewritten SQL:
SELECT orders.ID, orders.TYPE, orders.STATUS FROM orders, STATUS WHERE orders.STATUS = STATUS.NAME AND STATUS.ORDER_TYPE = 'purchase'
This can be written as follows in your action:
$c = new Criteria(); $c->addJoin (OrderPeer::STATUS, StatusPeer::NAME); $c->add(StatusPeer.ORDER_TYPE, 'purchase'); $orders = StatusPeer::doSelect($c);
Let us take the example of snipeet! :-) The function that selects snippets by tags is a custom SQL query. When filtering by tags there is no pager anymore.
Why is that? The problem is that sfPropelPaginate only works with a Criteria object, not with a raw query. As a result you cannot have pagination with raw SQL query which is a rather severe limitation.
The solution is to first encode the parameter of the query in the criteria (that's the tricky bit) and then to set up a custom peer method.
As i said earlier we will take a simplified version of snipeet as an example. We assume that we have a function that creates a sql statement from a list of tags.
Here we go about setting the dummy criteria that encodes an array of tags:
getCriteriaFromTags($tags) { $c = new Criteria(); for ($i = 1; $i <= count($tags); ++$i) { $prefix = 't'.$i; // note that that SnippetTagPeer::TABLE_NAME SnippetTagPeer::NAME are in fact arbitrary // any other table and table.column combination would work as well $c->addAlias($prefix.SnippetTagPeer::TABLE_NAME, SnippetTagPeer::TABLE_NAME); $c->add($prefix.SnippetTagPeer::NAME, $tags[$i-1]); } return $c; }
Now you can initialise a sfPropelPaginate object as usual with that Criteria object. When that is done you tell it to use your custom peer method:
$pager->setPeerMethod('doSelectByTags');
Next you code the doSelectByTags method that performs the actual selection from a criteria object:
function doSelectByTags($c) { // first you fetch the tags from the query $tags = array(); foreach($c->keys() as $key) $tags[] = $c->get($key); // here comes your custom sql query // it basically creates a $statement variable from the $tags array // ..... // now you have to add the limit and offset: $statement->setLimit($c->getLimit()); $statement->setOffset($c->getOffset()); // and the rest of the code is as usual }