Changeset 10540
- Timestamp:
- 07/31/08 15:22:53 (4 months ago)
- Files:
-
- plugins/sfPropelFinderPlugin/README (modified) (4 diffs)
- plugins/sfPropelFinderPlugin/lib/DbFinder.php (modified) (1 diff)
- plugins/sfPropelFinderPlugin/test/unit/DbFinderTest.php (modified) (2 diffs)
- plugins/sfPropelFinderPlugin/test/unit/sfPropelFinderRelationsTest.php (modified) (7 diffs)
- plugins/sfPropelFinderPlugin/test/unit/sfPropelFinderTest.php (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
plugins/sfPropelFinderPlugin/README
r10344 r10540 70 70 }}} 71 71 72 ''Tip'': When developing with the finder, you may prefer to have an array or string representation of the results rather than an array of objects. The finder objects provides three methods (`toArray()`, `__toString()` and `toHtml()`) that internally execute a `find()` and return something that you can output in your response. 73 72 74 === Adding WHERE clause === 73 75 … … 178 180 Compare it to the code required to get these `Comment` objects without `sfPropelFinder`, and you will understand all the benefits the `relatedTo()` method provide. 179 181 180 Tip: Alternatively, a finder can be initialized from an array of Propel object. The resulting SQL query contains a 'IN ()' clause, so use this possibility with caution.182 ''Tip'': Alternatively, a finder can be initialized from an array of Propel object. The resulting SQL query contains a 'IN ()' clause, so use this possibility with caution. 181 183 182 184 {{{ … … 591 593 592 594 * Allow i18n hydration of related objects (#3897) 595 * Allow `between` as a `where()` operator for simplicity 596 * Add a method returning a description of the conditions 597 * Add support for `withColumn()` in array/text output methods 598 * Bypass hydration in array/text output methods 593 599 * Handle self-referencing relationships (e.g. parent_id), especially in with() 594 600 * Handle multiple references to the same table (c.f. getFooRelatedByBarId()) 595 601 * Put as a parent class in the PeerBuilder so that every Peer class can be a finder 596 602 * Merge with sfPropelImpersonatorPlugin! 597 * Add a `__toString()` method which returns a var_export() of the results, or a description of the conditions if not yet executed598 603 * Implement iterator interface? That way, the query is only executed upon a foreach or an array access... And the finder can be seen as a collection 599 604 * Column finder, which provides an easy interface to Creole (and PDO) for retrieval of columns instead of objects? … … 601 606 == Changelog == 602 607 603 === 2008-07-17 | Trunk === 604 608 === 2008-07-31 | Trunk === 609 610 * francois: Implemented `DbFinder::toArray()`, `DbFinder::__toString()` and `DbFinder::toHtml()` 605 611 * francois: Implemented `sfDoctrineFinder::findBy()`, `findOneBy()`, `findPk()`, and initialized `where()` 606 612 * francois: Added preliminary support for table aliases (`from('Article a')`) in Doctrine and Propel finders plugins/sfPropelFinderPlugin/lib/DbFinder.php
r10344 r10540 196 196 return array($class, $alias); 197 197 } 198 199 // Finder Outputters 200 201 /** 202 * Array outputter 203 * Executes the finder and returns an array of results 204 * Each result being an associative array 205 * TODO: Bypass hydration for better performance 206 * 207 * @param $limit Integer Optional number of results to return 208 * 209 * @return Array the list of results as arrays 210 */ 211 public function toArray($limit = null) 212 { 213 $objects = $this->find($limit); 214 $res = array(); 215 foreach($objects as $object) 216 { 217 $res []= $object->toArray(); 218 } 219 220 return $res; 221 } 222 223 /** 224 * String outputter 225 * Executes the finder and returns a string (incidentally, YAML compliant) 226 * TODO: Bypass hydration for better performance 227 * 228 * @param $limit Integer Optional number of results to return 229 * 230 * @return String the list of results as YAML 231 */ 232 public function __toString($limit = null) 233 { 234 $objects = $this->find($limit); 235 $res = ''; 236 $i = 0; 237 foreach($objects as $object) 238 { 239 $res .= sprintf("%s_%d:\n", get_class($object), $i); 240 foreach ($object->toArray() as $key => $value) 241 { 242 $res .= sprintf(" %-10s %s\n", $key . ':', $value); 243 } 244 $i++; 245 } 246 247 return $res; 248 } 249 250 /** 251 * HTML outputter 252 * Executes the finder and returns a HTML table 253 * TODO: Bypass hydration for better performance 254 * 255 * @param $limit Integer Optional number of results to return 256 * 257 * @return String the list of results as an HTML table 258 */ 259 public function toHtml($limit = null) 260 { 261 $objects = $this->find($limit); 262 $res = "<table class=\"DbFinder\">\n"; 263 $isFirstLine = true; 264 foreach($objects as $object) 265 { 266 if($isFirstLine) 267 { 268 $res .= " <tr>\n"; 269 foreach ($object->toArray() as $key => $value) 270 { 271 $res .= sprintf(" <th>%s</th>\n", $key); 272 } 273 $res .= " </tr>\n"; 274 } 275 $res .= " <tr>\n"; 276 foreach ($object->toArray() as $value) 277 { 278 $res .= sprintf(" <td>%s</td>\n", $value); 279 } 280 $res .= " </tr>\n"; 281 $isFirstLine = false; 282 } 283 $res .= "</table>\n"; 284 285 return $res; 286 } 198 287 } plugins/sfPropelFinderPlugin/test/unit/DbFinderTest.php
r10344 r10540 61 61 ArticlePeer::doDeleteAll(); 62 62 63 $t = new lime_test( 4, new lime_output_color());63 $t = new lime_test(7, new lime_output_color()); 64 64 65 65 $t->diag('from()'); … … 82 82 $t->isa_ok($finder, 'sfPropelFinder', 'from() called with a Propel class name returns a sfPropelFinder'); 83 83 $t->ok($article instanceof BaseObject, 'A DbFinder initialized from a Propel class returns BaseObject objects'); 84 85 $finderAsArray = DbFinder::from('Article')->toArray(); 86 $t->is_deeply($finderAsArray, array(array('Id' => 1, 'Title' => 'foo', 'CategoryId' => null)), 'toArray() executes the finder and returns an array with column phpNames as keys'); 87 88 $finderAsString = (string) DbFinder::from('Article'); 89 $expected = <<<FOO 90 Article_0: 91 Id: 1 92 Title: foo 93 CategoryId: 94 95 FOO; 96 $t->is($finderAsString, $expected, '__toString() executes the finder and returns a string with column phpNames as keys'); 97 98 $finderAsHtml = DbFinder::from('Article')->toHtml(); 99 $expected = <<<FOO 100 <table class="DbFinder"> 101 <tr> 102 <th>Id</th> 103 <th>Title</th> 104 <th>CategoryId</th> 105 </tr> 106 <tr> 107 <td>1</td> 108 <td>foo</td> 109 <td></td> 110 </tr> 111 </table> 112 113 FOO; 114 $t->is($finderAsHtml, $expected, 'toHTML() executes the finder and returns a string with an HTML table with column phpNames as column headers'); 115 plugins/sfPropelFinderPlugin/test/unit/sfPropelFinderRelationsTest.php
r10342 r10540 297 297 $article1->setCategory($category1); 298 298 $article1->save(); 299 $sql = 'SELECT article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID, category.ID, category.NAME FROM article, category WHERE article.CATEGORY_ID=category.ID LIMIT 1';299 $sql = 'SELECT article.ID, article.TITLE, article.CATEGORY_ID, category.ID, category.NAME FROM article, category WHERE article.CATEGORY_ID=category.ID LIMIT 1'; 300 300 $finder = sfPropelFinder::from('Article')->join('Category')->with('Category'); 301 301 $article = $finder->findOne(); … … 328 328 $finder = sfPropelFinder::from('Comment')->with('Article')->with('Author'); 329 329 $comment = $finder->findOne(); 330 $sql = 'SELECT comment.ID, comment.CONTENT, comment.ARTICLE_ID, comment.AUTHOR_ID, article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID, author.ID, author.NAME FROM comment, article, author WHERE comment.ARTICLE_ID=article.ID AND comment.AUTHOR_ID=author.ID LIMIT 1';330 $sql = 'SELECT comment.ID, comment.CONTENT, comment.ARTICLE_ID, comment.AUTHOR_ID, article.ID, article.TITLE, article.CATEGORY_ID, author.ID, author.NAME FROM comment, article, author WHERE comment.ARTICLE_ID=article.ID AND comment.AUTHOR_ID=author.ID LIMIT 1'; 331 331 $t->is($finder->getLatestQuery(), $sql, 'you can call with() several times to hydrate more than one related object'); 332 332 $t->is($comment->getContent(), 'foo', 'you can call with() several times to hydrate more than one related object'); … … 337 337 $finder = sfPropelFinder::from('Comment')->with('Article')->with('Category'); 338 338 $comment = $finder->findOne(); 339 $t->is($finder->getLatestQuery(), 'SELECT comment.ID, comment.CONTENT, comment.ARTICLE_ID, comment.AUTHOR_ID, article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID, category.ID, category.NAME FROM comment, article, category WHERE comment.ARTICLE_ID=article.ID AND article.CATEGORY_ID=category.ID LIMIT 1', 'with() can even hydrate related objects via a related object');339 $t->is($finder->getLatestQuery(), 'SELECT comment.ID, comment.CONTENT, comment.ARTICLE_ID, comment.AUTHOR_ID, article.ID, article.TITLE, article.CATEGORY_ID, category.ID, category.NAME FROM comment, article, category WHERE comment.ARTICLE_ID=article.ID AND article.CATEGORY_ID=category.ID LIMIT 1', 'with() can even hydrate related objects via a related object'); 340 340 341 341 $finder = sfPropelFinder::from('Comment')->with('Article', 'Category'); 342 342 $comment = $finder->findOne(); 343 $t->is($finder->getLatestQuery(), 'SELECT comment.ID, comment.CONTENT, comment.ARTICLE_ID, comment.AUTHOR_ID, article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID, category.ID, category.NAME FROM comment, article, category WHERE comment.ARTICLE_ID=article.ID AND article.CATEGORY_ID=category.ID LIMIT 1', 'with() accepts several arguments, so you don\'t need to call it several times');343 $t->is($finder->getLatestQuery(), 'SELECT comment.ID, comment.CONTENT, comment.ARTICLE_ID, comment.AUTHOR_ID, article.ID, article.TITLE, article.CATEGORY_ID, category.ID, category.NAME FROM comment, article, category WHERE comment.ARTICLE_ID=article.ID AND article.CATEGORY_ID=category.ID LIMIT 1', 'with() accepts several arguments, so you don\'t need to call it several times'); 344 344 345 345 $t->diag('withI18n()'); … … 359 359 $article = $finder->findOne(); 360 360 $query = $finder->getLatestQuery(); 361 $t->is($query, 'SELECT article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID, article_i18n.CONTENT, article_i18n.ID, article_i18n.CULTURE FROM article, article_i18n WHERE article_i18n.CULTURE=\'en\' AND article.ID=article_i18n.ID LIMIT 1', 'withI18n() hydrates the related I18n object with a culture taken from the user object');361 $t->is($query, 'SELECT article.ID, article.TITLE, article.CATEGORY_ID, article_i18n.CONTENT, article_i18n.ID, article_i18n.CULTURE FROM article, article_i18n WHERE article_i18n.CULTURE=\'en\' AND article.ID=article_i18n.ID LIMIT 1', 'withI18n() hydrates the related I18n object with a culture taken from the user object'); 362 362 $t->is($article->getContent(), 'english content', 'withI18n() considers the current user culture for hydration'); 363 363 $t->is(Propel::getConnection()->getLastExecutedQuery(), $query, 'withI18n() hydrates the i18n object so that no further query is necessary'); … … 367 367 $article = $finder->findOne(); 368 368 369 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID, article_i18n.CONTENT, article_i18n.ID, article_i18n.CULTURE FROM article, article_i18n WHERE article_i18n.CULTURE=\'fr\' AND article.ID=article_i18n.ID LIMIT 1', 'withI18n() hydrates the related I18n object with a culture taken from the user object');369 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article.TITLE, article.CATEGORY_ID, article_i18n.CONTENT, article_i18n.ID, article_i18n.CULTURE FROM article, article_i18n WHERE article_i18n.CULTURE=\'fr\' AND article.ID=article_i18n.ID LIMIT 1', 'withI18n() hydrates the related I18n object with a culture taken from the user object'); 370 370 $t->is($article->getContent(), 'contenu français', 'withI18n() considers the current user culture for hydration'); 371 371 … … 379 379 $finder = sfPropelFinder::from('Article')->with('I18n'); 380 380 $article = $finder->findOne(); 381 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID, article_i18n.CONTENT, article_i18n.ID, article_i18n.CULTURE FROM article, article_i18n WHERE article_i18n.CULTURE=\'en\' AND article.ID=article_i18n.ID LIMIT 1', 'with(\'I18n\') is a synonym for withI18n()');381 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article.TITLE, article.CATEGORY_ID, article_i18n.CONTENT, article_i18n.ID, article_i18n.CULTURE FROM article, article_i18n WHERE article_i18n.CULTURE=\'en\' AND article.ID=article_i18n.ID LIMIT 1', 'with(\'I18n\') is a synonym for withI18n()'); 382 382 $finder = sfPropelFinder::from('Article')->with('i18n'); 383 383 $article = $finder->findOne(); 384 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID, article_i18n.CONTENT, article_i18n.ID, article_i18n.CULTURE FROM article, article_i18n WHERE article_i18n.CULTURE=\'en\' AND article.ID=article_i18n.ID LIMIT 1', 'with(\'i18n\') is a synonym for withI18n()');384 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article.TITLE, article.CATEGORY_ID, article_i18n.CONTENT, article_i18n.ID, article_i18n.CULTURE FROM article, article_i18n WHERE article_i18n.CULTURE=\'en\' AND article.ID=article_i18n.ID LIMIT 1', 'with(\'i18n\') is a synonym for withI18n()'); 385 385 386 386 $t->diag('withColumn()'); … … 466 466 orderBy('NbComments'); 467 467 $article = $finder->findOne(); 468 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID, COUNT(comment.ID) AS \'NbComments\' FROM article, comment WHERE article.ID=comment.ARTICLE_ID GROUP BY article.ID ORDER BY NbComments ASC LIMIT 1', 'Columns added with withColumn() can be used for sorting');468 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article.TITLE, article.CATEGORY_ID, COUNT(comment.ID) AS \'NbComments\' FROM article, comment WHERE article.ID=comment.ARTICLE_ID GROUP BY article.ID ORDER BY NbComments ASC LIMIT 1', 'Columns added with withColumn() can be used for sorting'); plugins/sfPropelFinderPlugin/test/unit/sfPropelFinderTest.php
r10344 r10540 227 227 228 228 $article = $finder->with('Category')->findPk($article2->getId()); 229 $t->cmp_ok(strpos($finder->getLatestQuery(), 'SELECT article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID, category.ID, category.NAME FROM article, category'), '===', 0, 'findPk() is compatible with with()');229 $t->cmp_ok(strpos($finder->getLatestQuery(), 'SELECT article.ID, article.TITLE, article.CATEGORY_ID, category.ID, category.NAME FROM article, category'), '===', 0, 'findPk() is compatible with with()'); 230 230 231 231 ArticlePeer::doDeleteAll(); … … 464 464 $t->diag('_and() and _or()'); 465 465 466 $columns = "article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID";466 $columns = "article.ID, article.TITLE, article.CATEGORY_ID"; 467 467 $baseSelect = "SELECT $columns FROM article WHERE "; 468 468 … … 543 543 $t->diag('combine()'); 544 544 545 $columns = "article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID";545 $columns = "article.ID, article.TITLE, article.CATEGORY_ID"; 546 546 $baseSelect = "SELECT $columns FROM article WHERE "; 547 547 … … 788 788 try 789 789 { 790 sfPropelFinder::from('Comment')->joinArticle()->where('Article_Title', 'updated title')->set(array(' Version' => 3));790 sfPropelFinder::from('Comment')->joinArticle()->where('Article_Title', 'updated title')->set(array('Title' => 3)); 791 791 $t->fail('set() throws an exception when called on a finder with join()'); 792 792 } … … 801 801 $t->isa_ok($finder->getCriteria(), 'Criteria', 'getCriteria() returns the criteria as composed by the finder'); 802 802 $finder->findOne(); 803 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID FROM article WHERE article.TITLE=\'foo\' LIMIT 1', 'getLatestQuery() returns the latest SQL query');803 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article.TITLE, article.CATEGORY_ID FROM article WHERE article.TITLE=\'foo\' LIMIT 1', 'getLatestQuery() returns the latest SQL query'); 804 804 $finder = sfPropelFinder::from('Article')->add(ArticlePeer::TITLE, 'bar'); 805 805 $finder->findOne(); 806 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article. VERSION, article.TITLE, article.CATEGORY_ID FROM article WHERE article.TITLE=\'bar\' LIMIT 1', 'you can call Criteria methods directly on the finder object to modify its Criteria');806 $t->is($finder->getLatestQuery(), 'SELECT article.ID, article.TITLE, article.CATEGORY_ID FROM article WHERE article.TITLE=\'bar\' LIMIT 1', 'you can call Criteria methods directly on the finder object to modify its Criteria');