Changeset 10120
- Timestamp:
- 07/04/08 16:11:04 (2 months ago)
- Files:
-
- plugins/sfPropelFinderPlugin/README (modified) (4 diffs)
- plugins/sfPropelFinderPlugin/lib/sfPropelFinder.php (modified) (4 diffs)
- plugins/sfPropelFinderPlugin/test/unit/sfPropelFinderRelationsTest.php (modified) (4 diffs)
- plugins/sfPropelFinderPlugin/test/unit/sfPropelFinderTest.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
plugins/sfPropelFinderPlugin/README
r10119 r10120 193 193 #!php 194 194 <?php 195 // Test data 195 196 $article1 = new Article(); 196 197 $article1->setTitle('Hello, world!'); … … 202 203 203 204 // Add a join statement 204 // No need to tell the finder which columns to use for the join, just the related Class205 // After all, the columns of the FK are already defined in the schema206 205 $article = sfPropelFinder::from('Article')-> 207 206 join('Comment')-> 208 207 where('Comment.Content', 'You rock!')-> 209 208 findOne(); 210 211 // As a matter of fact, join() is optional 212 // You can omit it if the join is simple and the finder can guess it 213 // That is, if you add conditions with explicit column names 209 // No need to tell the finder which columns to use for the join, just the related Class 210 // After all, the columns of the FK are already defined in the schema. 211 212 // If subsequent conditions use explicit column names, 213 // The finder can even guess the join table and you can omit the join() statement. 214 // This is the case here with Comment.Content, so the following also works 214 215 $article = sfPropelFinder::from('Article')-> 215 216 where('Comment.Content', 'You rock!')-> 216 217 findOne(); 217 218 218 // You can chain joins if you want to make it more complex 219 // So join() is mostly useful if you need to specify the members of the join 220 $article = sfPropelFinder::from('Article')-> 221 join('Article.Id', 'Comment.ArticleId')-> 222 where('Comment.Content', 'You rock!')-> 223 findOne(); 224 225 // Or if you want a special type of join (left, right, inner) 226 $article = sfPropelFinder::from('Article')-> 227 innerJoin('Comment')-> 228 where('Comment.Content', 'You rock!')-> 229 findOne(); 230 231 // Or both 232 $article = sfPropelFinder::from('Article')-> 233 innerJoin('Article.Id', 'Comment.ArticleId')-> 234 where('Comment.Content', 'You rock!')-> 235 findOne(); 236 237 // You can chain joins if you want to make more complex queries 219 238 $article2 = new Article(); 220 239 $article2->setTitle('Hello again, world!'); … … 499 518 * Merge with sfPropelImpersonatorPlugin! 500 519 * Add support for `with()` in `findPk()` (and document the method) 501 * Add the ability to do left, right, inner joins, etc.502 * Change `with()` and `join()` to accept only one relation at a time, but with the ability to set the local and foreign parts of the relation. maybe replace the current multiple ability of these methods by `joins()` and `withs()`503 520 * Handle complex queries with And and Or 504 521 * Add a `__toString()` method which returns a var_export() of the results, or a description of the conditions if not yet executed … … 510 527 === 2008-07-04 | Trunk === 511 528 529 * francois: Added the ability to do left, right, and inner joins in a simple way 512 530 * francois: Made `join()` useless if there is an explicit `where()` on the table afterwards 513 531 * francois: Added a `prove.php` test file to launch all tests at once in a test harness plugins/sfPropelFinderPlugin/lib/sfPropelFinder.php
r10119 r10120 891 891 * $articleFinder->join('Category', 'RIGHT JOIN') 892 892 * => $c->addJoin(ArticlePeer::CATEGORY_ID, CategoryPeer::ID, Criteria::RIGHT_JOIN) 893 */ 894 public function join($relatedClass, $arguments = array()) 895 { 896 list($column1, $column2) = $this->getRelation($relatedClass); 897 $this->relations[]= sfPropelFinderUtils::getPeerClassFromClass($relatedClass); 898 if(!is_array($arguments)) 899 { 900 $arguments = func_get_args(); 901 array_shift($arguments); 902 } 903 $operator = array_shift($arguments); 904 if(!$operator) 905 { 906 $operator = null; 893 * $articleFinder->join('Article.CategoryId', 'Category.Id', 'RIGHT JOIN') 894 * => $c->addJoin(ArticlePeer::CATEGORY_ID, CategoryPeer::ID, Criteria::RIGHT_JOIN) 895 */ 896 public function join() 897 { 898 $args = func_get_args(); 899 switch(count($args)) 900 { 901 case 0: 902 throw new Exception('sfPropelFinder::join() expects at least one argument'); 903 break; 904 case 1: 905 case 2: 906 // $articleFinder->join('Comment') 907 // $articleFinder->join('Category', 'RIGHT JOIN') 908 $relatedClass = $args[0]; 909 list($column1, $column2) = $this->getRelation($relatedClass); 910 $this->relations[]= sfPropelFinderUtils::getPeerClassFromClass($relatedClass); 911 $operator = isset($args[1]) ? $args[1] : null; 912 break; 913 case 3: 914 // $articleFinder->join('Article.CategoryId', 'Category.Id', 'RIGHT JOIN') 915 list($column1, $column2, $operator) = $args; 916 list($peerClass1, $column1) = $this->getColName($column1, $peerClass = null, $withPeerClass = true, $autoAddJoin = false); 917 if($peerClass1 != $this->peerClass && !$this->hasRelation($peerClass1)) 918 { 919 $this->relations []= $peerClass1; 920 } 921 list($peerClass2, $column2) = $this->getColName($column2, $peerClass = null, $withPeerClass = true, $autoAddJoin = false); 922 if($peerClass2 != $this->peerClass && !$this->hasRelation($peerClass2)) 923 { 924 $this->relations []= $peerClass2; 925 } 926 break; 907 927 } 908 928 $this->criteria->addJoin($column1, $column2, $operator); … … 985 1005 } 986 1006 987 protected function getColName($phpName, $peerClass = null, $withPeerClass = false )1007 protected function getColName($phpName, $peerClass = null, $withPeerClass = false, $autoAddJoin = true) 988 1008 { 989 1009 if(array_key_exists($phpName, $this->withColumns)) … … 1010 1030 $peerClass = $this->peerClass; 1011 1031 } 1012 if($peerClass != $this->peerClass && !$this->hasRelation($peerClass) )1032 if($peerClass != $this->peerClass && !$this->hasRelation($peerClass) && $autoAddJoin) 1013 1033 { 1014 1034 $this->join($class); … … 1039 1059 return $this->join(substr($name, 4), $arguments); 1040 1060 } 1061 if(strpos($name, 'Join') > 0) 1062 { 1063 $pos = strpos($name, 'Join'); 1064 $joinType = strtoupper(substr($name, 0, $pos)) . ' JOIN'; 1065 array_push($arguments, $joinType); 1066 return call_user_func_array(array($this, 'join'), $arguments); 1067 } 1041 1068 if(strpos($name, '_and') === 0) 1042 1069 { plugins/sfPropelFinderPlugin/test/unit/sfPropelFinderRelationsTest.php
r10101 r10120 12 12 You need a model built with a running database to run these tests. 13 13 The tests expect a model similar to this one: 14 15 propel: 16 article: 17 id: ~ 18 title: varchar(255) 19 category_id: ~ 20 article_i18n: 21 content: varchar(255) 22 category: 23 id: ~ 24 name: varchar(255) 25 comment: 26 id: ~ 27 content: varchar(255) 28 article_id: ~ 29 author_id: ~ 30 author: 31 id: ~ 32 name: varchar(255) 33 34 And a second model similar to: 14 35 15 36 propel: … … 58 79 $con = Propel::getConnection(); 59 80 60 $t = new lime_test( 4, new lime_output_color());81 $t = new lime_test(71, new lime_output_color()); 61 82 62 83 $t->diag('findRelation()'); … … 92 113 $t->is($person->getName(), 'John Doe', 'findRelation() can find a relation when the foreign phpName is not the camelCase version of the foreign Tablename'); 93 114 $t->is($person->getCivility()->getIsMan(), true, 'findRelation() can find a relation when the foreign phpName is not the camelCase version of the foreign Tablename'); 115 116 $t->diag('getRelation()'); 94 117 95 118 ClubPeer::doDeleteAll(); … … 106 129 $person1->setFoo($club1->getId()); 107 130 $person1->save(); 131 132 list($column1, $column2) = sfPropelFinder::from('Article')->getRelation('Category'); 133 $t->is($column1, ArticlePeer::CATEGORY_ID, 'getRelation() guesses the two parts of a relation properly for many-to-one relationships'); 134 $t->is($column2, CategoryPeer::ID, 'getRelation() guesses the two parts of a relation properly for many-to-one relationships'); 135 list($column1, $column2) = sfPropelFinder::from('Article')->getRelation('Comment'); 136 $t->is($column1, ArticlePeer::ID, 'getRelation() guesses the two parts of a relation properly for one-to-many relationships'); 137 $t->is($column2, CommentPeer::ARTICLE_ID, 'getRelation() guesses the two parts of a relation properly for one-to-many relationships'); 138 139 $t->diag('join()'); 140 141 $finder = sfPropelFinder::from('Article')->join('Comment'); 142 $join = array_pop($finder->getCriteria()->getJoins()); 143 $t->is($join->getJoinType(), null, 'join() ends up in a simple join'); 144 $t->is($join->getLeftColumnName(), 'ID', 'join($table) guesses the left column name'); 145 $t->is($join->getLeftTableName(), 'article', 'join($table) guesses the left table name'); 146 $t->is($join->getRightColumnName(), 'ARTICLE_ID', 'join($table) guesses the right column name'); 147 $t->is($join->getRightTableName(), 'comment', 'join($table) guesses the right table name'); 148 149 $finder = sfPropelFinder::from('Article')->join('Comment', Criteria::LEFT_JOIN); 150 $join = array_pop($finder->getCriteria()->getJoins()); 151 $t->is($join->getJoinType(), 'LEFT JOIN', 'join($table, $type) creates a typed join'); 152 $t->is($join->getLeftColumnName(), 'ID', 'join($table, $type) guesses the left column name'); 153 $t->is($join->getLeftTableName(), 'article', 'join($table, $type) guesses the left table name'); 154 $t->is($join->getRightColumnName(), 'ARTICLE_ID', 'join($table, $type) guesses the right column name'); 155 $t->is($join->getRightTableName(), 'comment', 'join($table, $type) guesses the right table name'); 156 157 $finder = sfPropelFinder::from('Article')->join('Article.Id', 'Comment.ArticleId', Criteria::LEFT_JOIN); 158 $join = array_pop($finder->getCriteria()->getJoins()); 159 $t->is($join->getJoinType(), 'LEFT JOIN', 'join($start, $end, $type) creates a typed join'); 160 $t->is($join->getLeftColumnName(), 'ID', 'join($start, $end, $type) converts the left column name'); 161 $t->is($join->getLeftTableName(), 'article', 'join($start, $end, $type) converts the left table name'); 162 $t->is($join->getRightColumnName(), 'ARTICLE_ID', 'join($start, $end, $type) converts the right column name'); 163 $t->is($join->getRightTableName(), 'comment', 'join($start, $end, $type) converts the right table name'); 164 165 ArticlePeer::doDeleteAll(); 166 CategoryPeer::doDeleteAll(); 167 $category1 = new Category(); 168 $category1->setName('cat1'); 169 $category1->save(); 170 $category2 = new Category(); 171 $category2->setName('cat2'); 172 $category2->save(); 173 $article1 = new Article(); 174 $article1->setTitle('aaaaa'); 175 $article1->setCategory($category1); 176 $article1->save(); 177 $article2 = new Article(); 178 $article2->setTitle('bbbbb'); 179 $article2->setCategory($category1); 180 $article2->save(); 181 $article3 = new Article(); 182 $article3->setTitle('ccccc'); 183 $article3->setCategory($category2); 184 $article3->save(); 185 $nbArticles = sfPropelFinder::from('Article')->join('Category')->where('Category.Name', 'cat1')->count(); 186 $t->is($nbArticles, 2, 'join() allows to join to another table (many-to-one)'); 187 $nbArticles = sfPropelFinder::from('Article')->where('Category.Name', 'cat1')->count(); 188 $t->is($nbArticles, 2, 'join() can be omitted if column names are explicit (many-to-one)'); 189 $nbArticles = sfPropelFinder::from('Article')->join('Category')->where('Category.Name', 'cat2')->count(); 190 $t->is($nbArticles, 1, 'join() allows to join to another table (many-to-one)'); 191 $nbArticles = sfPropelFinder::from('Article')->join('Category')->where('Category.Name', 'cat2')->count(); 192 $t->is($nbArticles, 1, 'join() can be omitted if column names are explicit (many-to-one)'); 193 $article = sfPropelFinder::from('Article')->join('Category')->where('Category.Name', 'cat2')->findOne(); 194 $t->is($article->getTitle(), 'ccccc', 'join() allows to join to another table (many-to-one)'); 195 ArticlePeer::doDeleteAll(); 196 CommentPeer::doDeleteAll(); 197 $article1 = new Article(); 198 $article1->setTitle('aaaaa'); 199 $article1->setCategory($category1); 200 $article1->save(); 201 $article2 = new Article(); 202 $article2->setTitle('bbbbb'); 203 $article2->setCategory($category1); 204 $article2->save(); 205 $comment = new Comment(); 206 $comment->setContent('foo'); 207 $comment->setArticleId($article2->getId()); 208 $comment->save(); 209 $nbArticles = sfPropelFinder::from('Article')->join('Comment')->where('Comment.Content', 'foo')->count(); 210 $t->is($nbArticles, 1, 'join() allows to join to another table (one-to-many)'); 211 $nbArticles = sfPropelFinder::from('Article')->where('Comment.Content', 'foo')->count(); 212 $t->is($nbArticles, 1, 'join() can be omitted if column names are explicit (one-to-many)'); 213 $article = sfPropelFinder::from('Article')->join('Comment')->where('Comment.Content', 'foo')->findOne(); 214 $t->is($article->getTitle(), 'bbbbb', 'join() allows to join to another table (one-to-many)'); 215 216 ArticlePeer::doDeleteAll(); 217 CommentPeer::doDeleteAll(); 218 AuthorPeer::doDeleteAll(); 219 $article1 = new Article(); 220 $article1->setTitle('aaaaa'); 221 $article1->setCategory($category1); 222 $article1->save(); 223 $author1 = new Author(); 224 $author1->setName('John'); 225 $author1->save(); 226 $comment = new Comment(); 227 $comment->setContent('foo'); 228 $comment->setArticleId($article1->getId()); 229 $comment->setAuthor($author1); 230 $comment->save(); 231 $article = sfPropelFinder::from('Article')->join('Comment')->join('Author')->where('Author.Name', 'John')->findOne(); 232 $t->is($article->getTitle(), 'aaaaa', 'you can chain several join() statements'); 233 $article = sfPropelFinder::from('Article')->join('Comment')->where('Author.Name', 'John')->findOne(); 234 $t->is($article->getTitle(), 'aaaaa', 'join() can be omitted if column names are explicit'); 235 $article = sfPropelFinder::from('Article')->joinComment()->joinAuthor()->where('Author.Name', 'John')->findOne(); 236 $t->is($article->getTitle(), 'aaaaa', 'joinXXX() does a join according to the XXX column name'); 237 238 $t->diag('leftJoin(), rightJoin(), innerJoin()'); 239 240 $finder = sfPropelFinder::from('Article')->leftJoin('Comment'); 241 $join = array_pop($finder->getCriteria()->getJoins()); 242 $t->is($join->getJoinType(), 'LEFT JOIN', 'leftJoin($table) ends up in a left join'); 243 $finder = sfPropelFinder::from('Article')->rightJoin('Comment'); 244 $join = array_pop($finder->getCriteria()->getJoins()); 245 $t->is($join->getJoinType(), 'RIGHT JOIN', 'rightJoin($table) ends up in a right join'); 246 $finder = sfPropelFinder::from('Article')->innerJoin('Comment'); 247 $join = array_pop($finder->getCriteria()->getJoins()); 248 $t->is($join->getJoinType(), 'INNER JOIN', 'innerJoin($table) ends up in an inner join'); 249 250 $finder = sfPropelFinder::from('Article')->leftJoin('Article.Id', 'Comment.ArticleId'); 251 $join = array_pop($finder->getCriteria()->getJoins()); 252 $t->is($join->getJoinType(), 'LEFT JOIN', 'leftJoin($start, $end) creates a left join'); 253 $t->is($join->getLeftColumnName(), 'ID', 'leftJoin($start, $end) converts the left column name'); 254 $t->is($join->getLeftTableName(), 'article', 'leftJoin($start, $end) converts the left table name'); 255 $t->is($join->getRightColumnName(), 'ARTICLE_ID', 'leftJoin($start, $end) converts the right column name'); 256 $t->is($join->getRightTableName(), 'comment', 'leftJoin($start, $end) converts the right table name'); 257 258 $t->diag('with()'); 259 260 ArticlePeer::doDeleteAll(); 261 CategoryPeer::doDeleteAll(); 262 $category1 = new Category(); 263 $category1->setName('cat1'); 264 $category1->save(); 265 $article1 = new Article(); 266 $article1->setTitle('aaaaa'); 267 $article1->setCategory($category1); 268 $article1->save(); 269 $finder = sfPropelFinder::from('Article')->join('Category')->with('Category'); 270 $article = $finder->findOne(); 271 $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'; 272 $t->is($finder->getLatestQuery(), $sql, 'with() gets the columns of the with class in addition to the columns of the current class'); 273 $finder = sfPropelFinder::from('Article')->with('Category'); 274 $article = $finder->findOne(); 275 $t->is($finder->getLatestQuery(), $sql, 'with() adds a join if not already added'); 276 $t->is($article->getTitle(), 'aaaaa', 'fetching objects with a with() returns the correct main object'); 277 $category = $article->getCategory(); 278 $t->is($category->getName(), 'cat1', 'fetching objects with a with() returns the correct related object'); 279 $con = Propel::getConnection(); 280 $latestQuery = $con->getLastExecutedQuery(); 281 $t->is($latestQuery, $sql, 'calling a FK getter on an object hydrated with with() does not issue a new query'); 282 283 ArticlePeer::doDeleteAll(); 284 CommentPeer::doDeleteAll(); 285 AuthorPeer::doDeleteAll(); 286 $article1 = new Article(); 287 $article1->setTitle('bbbbb'); 288 $article1->setCategory($category1); 289 $article1->save(); 290 $author1 = new Author(); 291 $author1->setName('John'); 292 $author1->save(); 293 $comment = new Comment(); 294 $comment->setContent('foo'); 295 $comment->setArticleId($article1->getId()); 296 $comment->setAuthor($author1); 297 $comment->save(); 298 $finder = sfPropelFinder::from('Comment')->with('Article')->with('Author'); 299 $comment = $finder->findOne(); 300 $t->is($comment->getContent(), 'foo', 'you can call with() several times to hydrate more than one related object'); 301 $t->is($comment->getArticle()->getTitle(), 'bbbbb', 'you can call with() several times to hydrate more than one related object'); 302 $t->is($comment->getAuthor()->getName(), 'John', 'you can call with() several times to hydrate more than one related object'); 303 $t->is($finder->getLatestQuery(), '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', 'you can call with() several times to hydrate more than one related object'); 304 305 $finder = sfPropelFinder::from('Comment')->with('Article')->with('Category'); 306 $comment = $finder->findOne(); 307 $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'); 308 309 $finder = sfPropelFinder::from('Comment')->with('Article', 'Category'); 310 $comment = $finder->findOne(); 311 $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'); 312 313 $t->diag('withI18n()'); 314 315 ArticlePeer::doDeleteAll(); 316 ArticleI18nPeer::doDeleteAll(); 317 $article1 = new Article(); 318 $article1->setTitle('aaa'); 319 $article1->setCulture('en'); 320 $article1->setContent('english content'); 321 $article1->setCulture('fr'); 322 $article1->setContent('contenu français'); 323 $article1->save(); 324 325 sfContext::getInstance()->getUser()->setCulture('en'); 326 $finder = sfPropelFinder::from('Article')->withI18n(); 327 $article = $finder->findOne(); 328 329 $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', 'withI18n() hydrates the related I18n object with a culture taken from the user object'); 330 $t->is($article->getContent(), 'english content', 'withI18n() considers the current user culture for hydration'); 331 332 sfContext::getInstance()->getUser()->setCulture('fr'); 333 $finder = sfPropelFinder::from('Article')->withI18n(); 334 $article = $finder->findOne(); 335 336 $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'); 337 $t->is($article->getContent(), 'contenu français', 'withI18n() considers the current user culture for hydration'); 338 339 sfContext::getInstance()->getUser()->setCulture('fr'); 340 $article = sfPropelFinder::from('Article')-> 341 withI18n('en')-> 342 findOne(); 343 $t->is($article->getContent(), 'english content', 'withI18n() accepts a culture parameter to override the user culture'); 344 345 sfContext::getInstance()->getUser()->setCulture('en'); 346 $finder = sfPropelFinder::from('Article')->with('I18n'); 347 $article = $finder->findOne(); 348 $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()'); 349 $finder = sfPropelFinder::from('Article')->with('i18n'); 350 $article = $finder->findOne(); 351 $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()'); 352 353 $t->diag('withColumn()'); 354 355 ArticlePeer::doDeleteAll(); 356 CommentPeer::doDeleteAll(); 357 358 $article1 = new Article(); 359 $article1->setTitle('bbbbb'); 360 $article1->setCategory($category1); 361 $article1->save(); 362 $author1 = new Author(); 363 $author1->setName('John'); 364 $author1->save(); 365 $comment = new Comment(); 366 $comment->setContent('foo'); 367 $comment->setArticleId($article1->getId()); 368 $comment->setAuthor($author1); 369 $comment->save(); 370 371 $comment = sfPropelFinder::from('Comment')-> 372 join('Article')-> 373 withColumn('Article.Title')-> 374 findOne(); 375 $t->is($comment->getColumn('Article.Title'), 'bbbbb', 'Additional columns added with withColumn() are stored in the object and can be retrieved with getColumn()'); 376 377 $comment = sfPropelFinder::from('Comment')-> 378 join('Article')-> 379 findOne(); 380 try 381 { 382 $comment->getColumn('Article.Title'); 383 $t->fail('getColumn() is not available as long as you don\'t add a column with withColumn()'); 384 } 385 catch(Exception $e) 386 { 387 $t->pass('getColumn() is not available as long as you don\'t add a column with withColumn()'); 388 } 389 390 $comment = sfPropelFinder::from('Comment')-> 391 withColumn('Article.Title')-> 392 findOne(); 393 $t->is($comment->getColumn('Article.Title'), 'bbbbb', 'If withColumn() is called on a related object column with no join on this class, the finder adds the join automatically'); 394 395 $comment = sfPropelFinder::from('Comment')-> 396 join('Article')-> 397 withColumn('Article.Title', 'ArticleTitle')-> 398 findOne(); 399 $t->is($comment->getColumn('ArticleTitle'), 'bbbbb', 'withColumn() second parameter serves as a column alias'); 400 401 $comment = sfPropelFinder::from('Comment')-> 402 join('Article')-> 403 withColumn('Article.Title', 'ArticleTitle', 'int')-> 404 findOne(); 405 $t->is($comment->getColumn('ArticleTitle'), '0', 'withColumn() third parameter serves as a type caster'); 406 407 $comment = sfPropelFinder::from('Comment')-> 408 join('Article')->join('Author')-> 409 withColumn('Article.Title')-> 410 withColumn('Author.Name')-> 411 findOne(); 412 $t->is($comment->getColumn('Article.Title'), 'bbbbb', 'withColumn() can be called several times'); 413 $t->is($comment->getColumn('Author.Name'), 'John', 'withColumn() can be called several times'); 414 415 $comment = sfPropelFinder::from('Comment')-> 416 join('Article')->with('Author')-> 417 withColumn('Article.Title')-> 418 findOne(); 419 $t->is($comment->getColumn('Article.Title'), 'bbbbb', 'Columns added with withColumn() live together well with related objects added with with()'); 420 $t->is($comment->getAuthor()->getName(), 'John', 'Related objects added with with() live together well with columns added with withColumn()'); 421 422 $article = sfPropelFinder::from('Article')-> 423 join('Comment')-> 424 groupBy('Article.Id')-> 425 withColumn('COUNT(comment.ID)', 'NbComments')-> 426 findOne(); 427 $t->is($article->getColumn('NbComments'), '1', 'withColumn() accepts complex SQL calculations as additional column'); 428 429 $finder = sfPropelFinder::from('Article')-> 430 join('Comment')-> 431 groupBy('Article.Id')-> 432 withColumn('COUNT(comment.ID)', 'NbComments')-> 433 orderBy('NbComments'); 434 $article = $finder->findOne(); 435 $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'); plugins/sfPropelFinderPlugin/test/unit/sfPropelFinderTest.php
r10119 r10120 65 65 ArticlePeer::doDeleteAll(); 66 66 67 $t = new lime_test(1 46, new lime_output_color());67 $t = new lime_test(102, new lime_output_color()); 68 68 69 69 $t->diag('find()'); … … 596 596 $t->is($article->getTitle(), 'ccccc', 'orderByXXX() takes an order as argument'); 597 597 598 $t->diag('join()');599 600 list($column1, $column2) = sfPropelFinder::from('Article')->getRelation('Category');601 $t->is($column1, ArticlePeer::CATEGORY_ID, 'getRelation() guesses the two parts of a relation properly for many-to-one relationships');602 $t->is($column2, CategoryPeer::ID, 'getRelation() guesses the two parts of a relation properly for many-to-one relationships');603 list($column1, $column2) = sfPropelFinder::from('Article')->getRelation('Comment');604 $t->is($column1, ArticlePeer::ID, 'getRelation() guesses the two parts of a relation properly for one-to-many relationships');605 $t->is($column2, CommentPeer::ARTICLE_ID, 'getRelation() guesses the two parts of a relation properly for one-to-many relationships');606 ArticlePeer::doDeleteAll();607 CategoryPeer::doDeleteAll();608 $category1 = new Category();609 $category1->setName('cat1');610 $category1->save();611 $category2 = new Category();612 $category2->setName('cat2');613 $category2->save();614 $article1 = new Article();615 $article1->setTitle('aaaaa');616 $article1->setCategory($category1);617 $article1->save();618 $article2 = new Article();619 $article2->setTitle('bbbbb');620 $article2->setCategory($category1);621 $article2->save();622 $article3 = new Article();623 $article3->setTitle('ccccc');624 $article3->setCategory($category2);625 $article3->save();626 $nbArticles = sfPropelFinder::from('Article')->join('Category')->where('Category.Name', 'cat1')->count();627 $t->is($nbArticles, 2, 'join() allows to join to another table (many-to-one)');628 $nbArticles = sfPropelFinder::from('Article')->where('Category.Name', 'cat1')->count();629 $t->is($nbArticles, 2, 'join() can be omitted if column names are explicit (many-to-one)');630 $nbArticles = sfPropelFinder::from('Article')->join('Category')->where('Category.Name', 'cat2')->count();631 $t->is($nbArticles, 1, 'join() allows to join to another table (many-to-one)');632 $nbArticles = sfPropelFinder::from('Article')->join('Category')->where('Category.Name', 'cat2')->count();633 $t->is($nbArticles, 1, 'join() can be omitted if column names are explicit (many-to-one)');634 $article = sfPropelFinder::from('Article')->join('Category')->where('Category.Name', 'cat2')->findOne();635 $t->is($article->getTitle(), 'ccccc', 'join() allows to join to another table (many-to-one)');636 ArticlePeer::doDeleteAll();637 CommentPeer::doDeleteAll();638 $article1 = new Article();639 $article1->setTitle('aaaaa');640 $article1->setCategory($category1);641 $article1->save();642 $article2 = new Article();643 $article2->setTitle('bbbbb');644 $article2->setCategory($category1);645 $article2->save();646 $comment = new Comment();647 $comment->setContent('foo');648 $comment->setArticleId($article2->getId());649 $comment->save();650 $nbArticles = sfPropelFinder::from('Article')->join('Comment')->where('Comment.Content', 'foo')->count();651 $t->is($nbArticles, 1, 'join() allows to join to another table (one-to-many)');652 $nbArticles = sfPropelFinder::from('Article')->where('Comment.Content', 'foo')->count();653 $t->is($nbArticles, 1, 'join() can be omitted if column names are explicit (one-to-many)');654 $article = sfPropelFinder::from('Article')->join('Comment')->where('Comment.Content', 'foo')->findOne();655 $t->is($article->getTitle(), 'bbbbb', 'join() allows to join to another table (one-to-many)');656 657 ArticlePeer::doDeleteAll();658 CommentPeer::doDeleteAll();659 AuthorPeer::doDeleteAll();660 $article1 = new Article();661 $article1->setTitle('aaaaa');662 $article1->setCategory($category1);663 $article1->save();664 $author1 = new Author();665 $author1->setName('John');666 $author1->save();667 $comment = new Comment();668 $comment->setContent('foo');669 $comment->setArticleId($article1->getId());670 $comment->setAuthor($author1);671 $comment->save();672 $article = sfPropelFinder::from('Article')->join('Comment')->join('Author')->where('Author.Name', 'John')->findOne();673 $t->is($article->getTitle(), 'aaaaa', 'you can chain several join() statements');674 $article = sfPropelFinder::from('Article')->join('Comment')->where('Author.Name', 'John')->findOne();675 $t->is($article->getTitle(), 'aaaaa', 'join() can be omitted if column names are explicit');676 $article = sfPropelFinder::from('Article')->joinComment()->joinAuthor()->where('Author.Name', 'John')->findOne();677 $t->is($article->getTitle(), 'aaaaa', 'joinXXX() does a join according to the XXX column name');678 679 $t->diag('with()');680 681 ArticlePeer::doDeleteAll();682 CategoryPeer::doDeleteAll();683 $category1 = new Category();684 $category1->setName('cat1');685 $category1->save();686 $article1 = new Article();687 $article1->setTitle('aaaaa');688 $article1->setCategory($category1);689 $article1->save();690 $finder = sfPropelFinder::from('Article')->join('Category')->with('Category');691 $article = $finder->findOne();692 $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';693 $t->is($finder->getLatestQuery(), $sql, 'with() gets the columns of the with class in addition to the columns of the current class');694 $finder = sfPropelFinder::from('Article')->with('Category');695 $article = $finder->findOne();696 $t->is($finder->getLatestQuery(), $sql, 'with() adds a join if not already added');697 $t->is($article->getTitle(), 'aaaaa', 'fetching objects with a with() returns the correct main object');698 $category = $article->getCategory();699 $t->is($category->getName(), 'cat1', 'fetching objects with a with() returns the correct related object');700 $con = Propel::getConnection();701 $latestQuery = $con->getLastExecutedQuery();702 $t->is($latestQuery, $sql, 'calling a FK getter on an object hydrated with with() does not issue a new query');703 704 ArticlePeer::doDeleteAll();705 CommentPeer::doDeleteAll();706 AuthorPeer::doDeleteAll();707 $article1 = new Article();708 $article1->setTitle('bbbbb');709 $article1->setCategory($category1);710 $article1->save();711 $author1 = new Author();712 $author1->setName('John');713 $author1->save();714 $comment = new Comment();715 $comment->setContent('foo');716 $comment->setArticleId($article1->getId());717 $comment->setAuthor($author1);718 $comment->save();719 $finder = sfPropelFinder::from('Comment')->with('Article')->with('Author');720 $comment = $finder->findOne();721 $t->is($comment->getContent(), 'foo', 'you can call with() several times to hydrate more than one related object');722 $t->is($comment->getArticle()->getTitle(), 'bbbbb', 'you can call with() several times to hydrate more than one related object');723 $t->is($comment->getAuthor()->getName(), 'John', 'you can call with() several times to hydrate more than one related object');724 $t->is($finder->getLatestQuery(), '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', 'you can call with() several times to hydrate more than one related object');725 726 $finder = sfPropelFinder::from('Comment')->with('Article')->with('Category');727 $comment = $finder->findOne();728 $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');729 730 $finder = sfPropelFinder::from('Comment')->with('Article', 'Category');731 $comment = $finder->findOne();732 $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');733 734 $t->diag('withI18n()');735 736 ArticlePeer::doDeleteAll();737 ArticleI18nPeer::doDeleteAll();738 $article1 = new Article();739 $article1->setTitle('aaa');740 $article1->setCulture('en');741 $article1->setContent('english content');742 $article1->setCulture('fr');743 $article1->setContent('contenu français');744 $article1->save();745 746 sfContext::getInstance()->getUser()->setCulture('en');747 $finder = sfPropelFinder::from('Article')->withI18n();748 $article = $finder->findOne();749 750 $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', 'withI18n() hydrates the related I18n object with a culture taken from the user object');751 $t->is($article->getContent(), 'english content', 'withI18n() considers the current user culture for hydration');752 753 sfContext::getInstance()->getUser()->setCulture('fr');754 $finder = sfPropelFinder::from('Article')->withI18n();755 $article = $finder->findOne();756 757 $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');758 $t->is($article->getContent(), 'contenu français', 'withI18n() considers the current user culture for hydration');759 760 sfContext::getInstance()->getUser()->setCulture('fr');761 $article = sfPropelFinder::from('Article')->762 withI18n('en')->763 findOne();764 $t->is($article->getContent(), 'english content', 'withI18n() accepts a culture parameter to override the user culture');765 766 sfContext::getInstance()->getUser()->setCulture('en');767 $finder = sfPropelFinder::from('Article')->with('I18n');768 $article = $finder->findOne();769 $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()');770 $finder = sfPropelFinder::from('Article')->with('i18n');771 $article = $finder->findOne();772 $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()');773 774 $t->diag('withColumn()');775 776 ArticlePeer::doDeleteAll();777 CommentPeer::doDeleteAll();778 779 $article1 = new Article();780 $article1->setTitle('bbbbb');781 $article1->setCategory($category1);782 $article1->save();783 $author1 = new Author();784 $author1->setName('John');785 $author1->save();786 $comment = new Comment();787 $comment->setContent('foo');788 $comment->setArticleId($article1->getId());789 $comment->setAuthor($author1);790 $comment->save();791 792 $comment = sfPropelFinder::from('Comment')->793 join('Article')->794 withColumn('Article.Title')->795 findOne();796 $t->is($comment->getColumn('Article.Title'), 'bbbbb', 'Additional columns added with withColumn() are stored in the object and can be retrieved with getColumn()');797 798 $comment = sfPropelFinder::from('Comment')->799 join('Article')->800 findOne();801 try802 {803 $comment->getColumn('Article.Title');804 $t->fail('getColumn() is not available as long as you don\'t add a column with withColumn()');805 }806 catch(Exception $e)807 {808 $t->pass('getColumn() is not available as long as you don\'t add a column with withColumn()');809 }810 811 $comment = sfPropelFinder::from('Comment')->812 withColumn('Article.Title')->813 findOne();814 $t->is($comment->getColumn('Article.Title'), 'bbbbb', 'If withColumn() is called on a related object column with no join on this class, the finder adds the join automatically');815 816 $comment = sfPropelFinder::from('Comment')->817 join('Article')->818 withColumn('Article.Title', 'ArticleTitle')->819 findOne();820 $t->is($comment->getColumn('ArticleTitle'), 'bbbbb', 'withColumn() second parameter serves as a column alias');821 822 $comment = sfPropelFinder::from('Comment')->823 join('Article')->824 withColumn('Article.Title', 'ArticleTitle', 'int')->825 findOne();826 $t->is($comment->getColumn('ArticleTitle'), '0', 'withColumn() third parameter serves as a type caster');827 828 $comment = sfPropelFinder::from('Comment')->829 join('Article')->join('Author')->830 withColumn('Article.Title')->831 withColumn('Author.Name')->832 findOne();833 $t->is($comment->getColumn('Article.Title'), 'bbbbb', 'withColumn() can be called several times');834 $t->is($comment->getColumn('Author.Name'), 'John', 'withColumn() can be called several times');835 836 $comment = sfPropelFinder::from('Comment')->837 join('Article')->with('Author')->838 withColumn('Article.Title')->839 findOne();840 $t->is($comment->getColumn('Article.Title'), 'bbbbb', 'Columns added with withColumn() live together well with related objects added with with()');841 $t->is($comment->getAuthor()->getName(), 'John', 'Related objects added with with() live together well with columns added with withColumn()');842 843 $article = sfPropelFinder::from('Article')->844 join('Comment')->845 groupBy('Article.Id')->846 withColumn('COUNT(comment.ID)', 'NbComments')->847 findOne();848 $t->is($article->getColumn('NbComments'), '1', 'withColumn() accepts complex SQL calculations as additional column');849 850 $finder = sfPropelFinder::from('Article')->851 join('Comment')->852 groupBy('Article.Id')->853 withColumn('COUNT(comment.ID)', 'NbComments')->854 orderBy('NbComments');855 $article = $finder->findOne();856 $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');857 858 598 $t->diag('set()'); 859 599