http://blog.tarotoast.com/tag/propel/
總之,ORM 就是可以省下寫 database specific SQL 的麻煩的 abstraction 就是了。Symfony 用的是 Propel ,是一個 PHP5 的 database framework,跟 ADOdb 是類似的東西,雖然兩者到底詳細差在哪我也不知道。不過總之 Symfony 的作者們決定用 Propel 來省下許多 code generation 和實作 ORM。
有幾個非常重要的檔案必須編輯好才能使用 Symfony 裡面的 propel 功能。
老實說 propel.ini 和 schema.yml 為啥要有兩個檔案,我也不知道 (as of now)。總之兩個檔案都得把 database 的設定寫進去就是了。然後 schema.yml 才是整個 ORM 的重點,Symfony 就是讀這個檔案生出所有 database object class 的。習慣直接編輯 schema.yml 的話是會很方便,不過老實說我也還不習慣,所以都用 phpmyadmin 先把 database 生好然後再讓 Symfony 生出 schema.yml。
database.yml
all: propel: class: sfPropelDatabase param: dsn: mysql://username:password@localhost/database
propel.ini (上面)
propel.targetPackage = lib.model propel.packageObjectModel = true propel.project = myproject propel.database = mysql propel.database.createUrl = mysql://username:password@localhost/ propel.database.url = mysql://username:password@localhost/database
大致的生產順序如下:
symfony propel-build-schema
symfony propel-build-model
用這個 schema.yml 當範例
propel: blog_article: _attributes: { phpName: Article } id: title: varchar(255) content: longvarchar created_at: blog_comment: _attributes: { phpName: Comment } id: article_id: author: varchar(255) content: longvarchar created_at:
會生出 8 個檔案,4 個檔案在 lib/model/om/ 下面 (Base Class):
1. BaseArticle.php
2. BaseArticlePeer.php
3. BaseComment.php
4. BaseCommentPeer.php
然後另外 4 個檔案在 lib/model/ 下面 (Custom Class):
1. Article.php
2. ArticlePeer.php
3. Comment.php
4. CommentPeer.php
生在 lib/model/om/ 下面的檔案只要每次跑 propel-build-model 就會重新被蓋過,所以如果要自己修改 model 增加功能的話,就得修改 lib/model/ 下面的 class。在 Base class 裡面所有 field 的 accessor 都會被自動生出來,也就是說上面這個 yml 生出來的 model 可以這樣使用。
// 單純是示範怎麼用 primary key $articles = ArticlePeer::retrieveByPks(array(123, 124, 125)); // 使用 setter/getter $article = new Article(); $article->setTitle('My first article'); $article->setContent('This is my very first article.\n Hope you enjoy it!'); $article->save(); $title = $article->getTitle(); $content = $article->getContent(); // 這才是 ORM 的精華 $comments = $article->getComments();
要如何 Query 比較複雜的判斷呢?答案是用 Criteria 這個 class。以下這段的功能:
$c = new Criteria(); $c->add(CommentPeer::AUTHOR, 'Steve'); $c->addJoin(CommentPeer::ARTICLE_ID, ArticlePeer::ID); $c->add(ArticlePeer::CONTENT, '%enjoy%', Criteria::LIKE); $c->addAscendingOrderByColumn(CommentPeer::CREATED_AT); $comments = CommentPeer::doSelect($c);
其實就等於 SQL 下面的:
SELECT blog_comment.ID, blog_comment.ARTICLE_ID, blog_comment.AUTHOR, blog_comment.CONTENT, blog_comment.CREATED_AT FROM blog_comment, blog_article WHERE blog_comment.AUTHOR = 'Steve' AND blog_article.CONTENT LIKE '%enjoy%' AND blog_comment.ARTICLE_ID = blog_article.ID ORDER BY blog_comment.CREATED_AT ASC
常用到的 condition 可以參考這個列表:
WHERE column = value | ->add(column, value); |
WHERE column <> value | ->add(column, value, Criteria::NOT_EQUAL); |
Other Comparison Operators | |
> , < | Criteria::GREATER_THAN, Criteria::LESS_THAN |
>=, <= | Criteria::GREATER_EQUAL, Criteria::LESS_EQUAL |
IS NULL, IS NOT NULL | Criteria::ISNULL, Criteria::ISNOTNULL |
LIKE, ILIKE | Criteria::LIKE, Criteria::ILIKE |
IN, NOT IN | Criteria::IN, Criteria::NOT_IN |
Other SQL Keywords | |
ORDER BY column ASC | ->addAscendingOrderByColumn(column); |
ORDER BY column DESC | ->addDescendingOrderByColumn(column); |
LIMIT limit | ->setLimit(limit) |
OFFSET offset | ->setOffset(offset) |
FROM table1, table2 WHERE table1.col1 = table2.col2 | ->addJoin(col1, col2) |
FROM table1 LEFT JOIN table2 ON table1.col1 = table2.col2 | ->addJoin(col1, col2, Criteria::LEFT_JOIN) |
FROM table1 RIGHT JOIN table2 ON table1.col1 = table2.col2 | ->addJoin(col1, col2, Criteria::RIGHT_JOIN)
|