基本的な C.R.U.D. オペレーション

このガイドではPropelを使用してデータベース上で基本的なC.R.U.D.(Create, Retrieve, Update, Delete)オペレーションを実行する方法を示します。一貫性のためにクイックスタートガイドからシンプル化した例のデータモデルを使用します。

このガイドでは既にPropelをインストールして利用を始めていることを前提とします。

作成

新しいデータをデータベースに追加するためにPropelで生成されたオブジェクトをインスタンス化してsave()メソッドを呼び出します。Propelはインスタンス化したオブジェクトから適切なINSERT SQLを生成します。

シンプルな追加

もっともシンプルなフォームにおいて、新しい列をINSERTするには次のようにします:

<?php
/* Propelを初期化するなど */

$author = new Author();
$author->setFirstName("Jack");
$author->setLastName("London");
$author->save();

背景において、これは次のSQLをデータベース上で実行したことになります:

INSERT INTO author (first_name, last_name) VALUES ('Jack', 'London');

関連した列を追加する

Propelは新しいオブジェクトがそれに追加された他の関連したオブジェクトを持つときに"カスケーディング"INSERT文を実行することで関連した列の追加を簡単にします。この例では、新しいAuthorとPublisherオブジェクトを作成し、新しいBookオブジェクトに追加されます; Book->save()メソッドが実行されたときにすべての3つのオブジェクトは保存されます。

<?php
/* Propelを初期化するなど */

// 1) Authorを作成する ('author'テーブルの列)

include_once 'bookstore/Author.php';

$author = new Author();
$author->setFirstName("Leo");
$author->setLastName("Tolstoy");
// 注: まだこれを保存していません

// 2) Publisherを作成する ('publisher'テーブルの列)

include_once 'bookstore/Publisher.php';

$pub = new Publisher();
$pub->setName("Viking Press");
// 注: まだこれを保存していません

// 3) Bookを作成する ('book'テーブルの列)

include_once 'bookstore/Book.php';

$book = new Book();
$book->setTitle("War & Peace");
$book->setIsbn("0140444173");
$book->setPublisher($pub);
$book->setAuthor($author);
$book->save(); // 3のオブジェクトをすべて保存します!

Propelはオブジェクトが保存されるかされないかをどうかを知っているので、オブジェクトをBookオブジェクトに関連したものとして追加するまえにオブジェクトをsave()するためにも動作をします。(関連した列と連携するための情報に関してはwiki:Users/Documentation/Relationships?をご覧頂けるようお願いします。)

取得する

データベースからオブジェクトを取得することは、オブジェクトをハイドレイトするとも言いますが、データベースへのSELECTクエリを実行する必用不可欠なプロセスでそれぞれの返された列の内容で適切なオブジェクトの新しいインスタンスを投入します。

Propelにおいて、データベースから存在する列を選択する生成されたPeerクラスを使用します。Peerクラスは特定のテーブル上でオペレーションを実行するための独占的な静的メソッドです。一つのオブジェクトを選択するもしくはデータベースから複数のオブジェクトをクエリすることを手助けするために生成されたいくつかのメソッドが存在します。

主キーによって取得する

データベースからオブジェクト(列)を取得するもっともシンプルな方法は生成されたretrieveByPK()を使用することです。このメソッドは取得したいオブジェクトのために主キー(primary key)の値にわたされなければなりません。

シングルカラムの主キー

通常テーブルは主キーとして単独のカラムを持ちます。このことはretrieveByPK() メソッドは単独のパラメータを受け取ることを意味します。

<?php

$firstBook = BookPeer::retrieveByPK(1);
// 何もマッチしなかった場合、$firstBookがBookオブジェクトもしくはNULLです。

マルチカラムの主キー

いくつかの場合において、主キーは一つ以上のカラムで構成されることがあります。その場合、retrieveByPK()メソッドは複数のパラメータを受け取るために作成され、それぞれの主キーカラムに対して一つです。

例に関しては、複数のカラムの主キーを伴うテーブルを持つ場合、次のように定義します:

   <table name="multicolpk_example" phpName="MultiColPKExample">
      <column name="id1" type="INTEGER" primaryKey="true"/>
      <column name="id2" type="INTEGER" primaryKey="true"/>
      <!-- other columns ... -->
   </table>

... それからretrieveByPK()メソッドは次のように起動します:

<?php

$myObject = MultiColPKExamplePeer::retrieveByPK(1,2);

主キーで複数のオブジェクトを取得する

パラメータを主キーのパラメータとして取得する生成されたretrieveByPKs()メソッドを呼び出すことで主キーに基づいて複数のオブジェクトを選択することも出来ます。

<?php

$selectedBooks = BookPeer::retrieveByPKs(array(1,2,3,4,5,6,7));
// $selectedBooksはBookオブジェクトの配列

単独のカラムの主キーを伴うテーブルに対してのみ動作することを注意して下さい。

データベースをクエリする

主キー以外の基準(criteria)で複数の列を選択するためには、2つの選択肢があります: 1) PropelのCriteriaクラスを使用する、もしくは 2) カスタムのSQLを書く。 Criteriaクラスはクエリを構築するために相対的にシンプルな方法を提供します。データベースの中立性と論理的な簡潔性によって多くの共通のクエリのためによい選択がなされます; しかしながら、とても複雑なクエリのために、PropelオブジェクトをハイドレイトするカスタムSQLクエリを使用するために、それはもっと効果的(そして苦痛が少ない)であることがわかるかもしれません。

シンプルなCriteria

複数のオブジェクトを返すために使用されるシンプルなCriteriaの例です。

例 1: ファーストネームがKarkであるがラストネームはMarxではないすべての著者を探します。

<?php

$c = new Criteria();
$c->add(AuthorPeer::FIRST_NAME, "Karl");
$c->add(AuthorPeer::LAST_NAME, "Marx", Criteria::NOT_EQUAL);

$authors = AuthorPeer::doSelect($c);
// $authorsはAuthorオブジェクトの配列を含みます

... 次のようなSQLになります:

SELECT ... FROM author WHERE author.FIRST_NAME = 'Karl' AND author.LAST_NAME <> 'Marx';

例 2: ラストネームがTolstoy、Dostoevsky、もしくはBakhtinであるすべての著者を探します

<?php

$c = new Criteria();
$c->add(AuthorPeer::LAST_NAME, array("Tolstoy", "Dostoevsky", "Bakhtin"), Criteria::IN);

$authors = AuthorPeer::doSelect($c);
// $authorsはAuthorオブジェクトの配列を含みます

... 結果のSQLクエリは次の通りです:

SELECT ... FROM author WHERE author.LAST_NAME IN ('Tolstoy', 'Dostoevsky', 'Bakhtin');

論理的に複雑なCriteria

異なるcriteria句間の論理的な関係(AND、OR、など)を表現する必要がある場合、個々のCriterionオブジェクトを一緒に手作業で結合させる必要があります。Criteria->add()'メソッドを使用する時にCriterionオブジェクトは透過的にCriteriaにまとめられるコンポーネントです。

例 1: ファーストネームが"Leo"もしくはラストネームが"Tolstoy"、"Dostoevsky"、もしくは"Bakhtin"であるすべての著者を見つける

<?php

$c = new Criteria();
$cton1 = $c->getNewCriterion(AuthorPeer::FIRST_NAME, "Leo");
$cton2 = $c->getNewCriterion(AuthorPeer::LAST_NAME,  array("Tolstoy", "Dostoevsky", "Bakhtin"), Criteria::IN);
 
// それらを結合する
$cton1->addOr($cton2);
 
// Criteriaに追加する
$c->add($cton1);

... SQLクエリの結果は次の通り:

SELECT ... FROM author WHERE (author.FIRST_NAME = 'Leo' OR author.LAST_NAME IN ('Tolstoy', 'Dostoevsky', 'Bakhtin'));

同じカラムを参照する句の間の論理的な関係に対するクエリを実行したい場合、Criteriaショートカットがいくつかあります。

例 2: ファーストネームが'Leo'もしくは'Karl'である著者をすべて探す

詳細なCriterionの方法を使う方法です:

<?php

$c = new Criteria();
$cton1 = $c->getNewCriterion(AuthorPeer::FIRST_NAME, "Leo");
$cton2 = $c->getNewCriterion(AuthorPeer::FIRST_NAME, "Karl");
 
// それらを結合します
$cton1->addOr($cton2);
 
// Criteriaに追加します
$c->add($cton1);

ショートハンドのCriteriaメソッドを使用します:

<?php

$c = new Criteria();
$c->add(AuthorPeer::FIRST_NAME, "Leo");
$c->addOr(AuthorPeer::FIRST_NAME, "Karl");

これらのショートハンドのCriteriaメソッドは多くの制限があることに注意して下さい -- まず単独のカラムの関係のみにしか動作をしません。著者の観点からすると、句の間の論理的な関係を表現する必要がある場合、これらのメソッドは推奨されません。Criterionオブジェクト間の実際の関係が不明瞭で簡単にデバッグするのが難しいクエリの生成問題につながるからです。(これらのメソッドはおそらくPropel2で変更されるもしくは削除されます。)

カスタムSQLを使用する

Propelはあなたの足を引っ張るよりも強調するために設計されています。多くの場合Criteriaを使用して複雑なクエリを書くことは標準のSQLクエリよりも本当に汚くて、あまり明瞭でないもしくはメインテナンスしずらい結果になります。結果セットをハイドレイトするあなた独自のSQLクエリを使用することを簡単にすることによってPropelはデータベースに対して中立的なCriteriaシステムの固有の制限を動作させるために作成されました。

ですので、少し余分な作業をすれば、SQLを使用してデータベースからオブジェクトを取得することが出来ます。データベースへのクエリをするためにSQLを使用することで生成されたPeerクラスにあるpopulateObjects()メソッドが導入されます -- これはdoSelect()メソッドの裏側で呼び出されます。このメソッドはCreoleのResultSetオブジェクトに渡され、数値的にインデックス化されることが期待されます(すなわち、!ResultSet::FETCHMODE_NUMオプションを使用してexecuteQuery()に作成されます)

例 1: データベースを投入するためにサブセレクトを使用する

<?php

$con = Propel::getConnection(DATABASE_NAME);

$sql = "SELECT books.* FROM books WHERE NOT EXISTS (SELECT id FROM review WHERE book_id = book.id)";  
$stmt = $con->createStatement();
$rs = $stmt->executeQuery($sql, ResultSet::FETCHMODE_NUM);  

$books = BookPeer::populateObjects($rs);    

Propelを投入するためにカスタムのSQLを使用するときに覚えておくことは次の通りです: * ResultSetカラムは数値でインデックス化されなければなりません * ResultSetはオブジェクトにすべてのカラムを含まなければなりません。 * ResultSetはschema.xmlファイルで定義されたように同じ順番でカラムをもたなければなりません

更新

データベースの列を更新することは基本的にオブジェクトの取得、内容の修正、そしてそれらの保存を伴います。実際には、Propelのために、これは取得と作成セクションで既に見てきたものの組み合わせです。

<?php

// 1) 主キーでオブジェクトを取得する

$myBook = BookPeer::retrieveByPK(1);

// 2) 値を更新する & save()する

$myBook ->setTitle("War & Peace");
$myBook->save();

本当にそれよりもさらにすることはありません。もちろん、作成セクションで既に見た同様の方法でリレーションシップを更新することも出来ます。

<?php
/* Propelを初期化します */

// 1) Authorを取得します
$author = AuthorPeer::retrieveByPK(1);

// 2) Bookを取得します
$book = BookPeer::retrieveByPK(1);

// 3) これで盲目的に$book!のための著者として$authorを設定します

$book->setAuthor($author);
$book->save();

削除

オブジェクトを削除することはPeerクラスもしくはobjectクラスを使用することで達成することが出来ます。

Peerを使用する

テーブルから列を削除するために生成されたPeerクラスの生成されたdoDelete()メソッドを使用することが出来ます。このメソッドを主キー、適切なメソッドのインスタンスもしくはCriteriaオブジェクトを使用することが出来ます(しかしながらこれはあまり便利ではなりません。主キーだけでしか削除できないからです)。

例 1: 主キーを使用して削除する

<?php

BookPeer::doDelete(1);

例 2: オブジェクトをインスタンス化して削除する

<?php

$book = BookPeer::retrieveByPK(1);
BookPeer::doDelete($book);

オブジェクトを使用する

C.R.U.D.オペレーションの一貫性のためにオブジェクトクラスを使用してデータベースの列も削除することが出来ます。オブジェクトをインスタンス化してそれの上でdelete()メソッドを呼び出すことを好む人もいます。データベースの列を実際には指定しないオブジェクトが残されるので他にはこれを"風変わり"と思う人がいます。何で荒れ - 自由に選択できます :)

$book = BookPeer::retrieveByPK(1);
$book->delete();
// (これで$bookオブジェクトを使用できないことを覚えて下さい)