symfonyではデータベース処理にPropelを使用しています。
コマンドラインで symfony propel-build-model コマンドを実行するだけで モデルクラスを自動生成してくれるので非常に便利ではありますが、 アクション側で使用する際に使い勝手があまりよくありません。
だいたいこんな↓感じになります。
$objCriteria = new Criteria();
$objCriteria->add(ProductMstPeer::SALE_FLG,1);
$objCriteria->addAnd(ProductMstPeer::REGIST_DATETIME,"2008-01-01 00:00:00",Criteria::GREATER_EQUAL);
$objCriteria->addAnd(ProductMstPeer::SALE_DAY,"date("Y-m-d"),Criteria::LESS_EQUAL);
$objCriteria->addJoin(ProductMstPeer::MAKER_ID,MakerMstPeer::MAKER_ID, "INNER JOIN"); //JOIN
$objCriteria->addAscendingOrderByColumn(ProductMstPeer::PRODUCT_ID);
$objCriteria->setLimit(50);
$objCriteria->setOffset(0);
$this->arrObjProduct = ProductMstPeer::doSelect($objCriteria);
※DBの商品テーブルから、2008年以降に登録された現在販売中の商品を取得する場合の例。
追加条件:指定されたメーカーIDの商品のみ取得し、メーカーマスタに登録されているメーカー名も取得する。
追加条件:0件目から最大50件取得、整列順は商品IDの昇順とする。
SELECTの度に毎回こんな長い記述を書くのは面倒なので、検索条件を配列にセットして渡すだけで結果を取得できる、クラス生成ツールを作成してみました。
モデルクラス生成ツール ダウンロード
symfonyの propel-build-modelコマンドで作成されたモデルクラスを継承し、アクション側からデータを抽出するための子クラスを作成します。
上記のスクリプトは以下のようになります。
他のアクションなどで、条件を少し変えて使い回す場合などにも便利です。
$arr = array();
$arr['sale_flg'] = 1;
$arr['greater_eq_regist_datetime'] = "2008-01-01 00:00:00";
$arr['less_eq_sale_date'] = date("Y-m-d");
$arr['join_maker_mst'] = "INNER JOIN";
$arr['sort_column'] = "product_id_asc";
$arr['limit'] = 30;
$arr['offset'] = 0;
$this->arrObjProduct = ProductMstPeer::doSelectBySearchArr($arr);
モデルクラス生成ツールver1.0.0 ドキュメント †
【動作確認済バージョン】
【使用条件】
symfonyがインストールされたサーバ環境が必要です。
xampp等がインストールされたローカル環境でも使用可能?(未確認)
【インストール】
解凍した後、/mkModel/フォルダを、ご利用の環境のモジュールディレクトリの配下に置いてください。
※設置場所例:/プロジェクトルート/apps/アプリケーション名/modules/
【アンインストール】
インストール時に設置したフォルダを削除して下さい。
レジストリ等は一切使っていません。
【使用方法】
インストールしたサーバにブラウザでアクセス
例:http://192.168.1.xxx/index.php/mkModel/index
コントローラ名(index.php)とアクション名(index)は環境によっては省略可。
下記のような画面が表示されます。

※propel-build-modelコマンドを実行した時点で子クラスは生成されています。
全て空の状態ですので、上書き保存してください。
以上で、アクション側から呼び出して使用できるようになります。
【指定できる検索条件】
$arr['カラム名'] = 検索条件
$arr['like_カラム名'] = 検索条件
※VARCHAR型のカラムのみ有効
$arr['greater_カラム名'] = 検索条件 … 値 > 検索条件
$arr['greater_eq_カラム名'] = 検索条件 … 値 >= 検索条件
$arr['less_カラム名'] = 検索条件 … 値 < 検索条件
$arr['less_eq_カラム名'] = 検索条件 … 値 <= 検索条件
※INTEGER、DATE、TIMESTAMP型のカラムのみ有効
$arr['sort_column'] = カラム名_asc … 指定したカラムの昇順
$arr['sort_column'] = カラム名_desc … 指定したカラムの降順
$arr['limit'] = 最大件数;
$arr['offset'] = offset値;
$arr['join_テーブル名'] = "INNER JOIN"
$arr['join_テーブル名'] = "LEFT OUTER JOIN" ...
【ページャとの連携】
以下のように記述することにより、symfonyの提供するページャとの連携も可能です。
class xxxxAction extends sfAction
{
public function execute()
{
//検索条件をセット
$arr = array();
$arr['sale_flg'] = 1;
$arr['greater_eq_regist_datetime'] = "2008-01-01 00:00:00";
$arr['less_eq_sale_date'] = date("Y-m-d");
$arr['join_maker_mst'] = "INNER JOIN";
$arr['sort_column'] = "product_id_asc";
//criteriaオブジェクトを取得する
$objCriteria = ProductMstPeer::getSearchCriteria($arr);
$intPageLimit = 30;
//ページャを使用してデータを取得する
$objPager = new sfPropelPager('ProductMst', $intPageLimit);
$objPager->setCriteria($objCriteria);
$objPager->setPage($this->getRequestParameter('page', 1)); //ページ番号を指定 デフォルトは 1
$objPager->setPeerMethod('doSelect');
$objPager->init();
$this->objPager = $objPager;
//ページ遷移時に検索条件を維持するため、Attributeにセットしておく
$this->getRequest()->setAttribute('search_product_name', trim($this->getRequestParameter('search_product_name')));
$this->getRequest()->setAttribute('search_maker_id', $this->getRequestParameter('search_maker_id'));
}
}
<?php echo include_partial("global/page_navi", array('objPageNavi' => $objPager, 'linkto' => '/list','arrParm' => $sf_request->getAttributeHolder()->getAll())) ?>
<?php
//検索パラメータ配列をGetパラメータ用に展開
foreach ($arrParm as $k => $v)
{
if (strlen($v))
{
$strParm .= '&'.$k.'='.$v;
}
}
?>
全<?php echo $objPageNavi->getNbResults(); ?>件
<?php if ($objPageNavi->getNbResults()): ?>
中<?php echo $objPageNavi->getFirstIndice(); ?>~<?php echo $objPageNavi->getLastIndice(); ?>を表示しています。
<?php endif; ?>
<?php if ($objPageNavi->haveToPaginate()): ?>
<?php echo link_to('最初へ', $sf_params->get('module').$linkto.'?page=1'.$strParm, array('query_string' => $strPageParameter)) ?>
<?php echo link_to('前へ ', $sf_params->get('module').$linkto.'?page='.$objPageNavi->getPreviousPage().$strParm, array('query_string' => $strPageParameter)) ?>
<?php foreach ($objPageNavi->getLinks(20) as $page): ?>
<?php echo link_to_unless($page == $objPageNavi->getPage(), "".$page."", $sf_params->get('module').$linkto.'?page='.$page.$strParm, array('query_string' => $strPageParameter)) ?>
<?php echo ($page != $objPageNavi->getCurrentMaxLink()) ? '|' : '' ?>
<?php endforeach; ?>
<?php echo link_to(' 次へ', $sf_params->get('module').$linkto.'?page='.$objPageNavi->getNextPage().$strParm, array('query_string' => $strPageParameter)) ?>
<?php echo link_to('最後へ', $sf_params->get('module').$linkto.'?page='.$objPageNavi->getLastPage().$strParm, array('query_string' => $strPageParameter)) ?>
<?php endif; ?>
【おまけ】
サブクエリーやJOIN条件に複数のカラムを指定する場合など、複雑なSELECTを行う場合はオリジナルのメソッドが必要。
参考→http://www.centsys.jp/service/technical_information/symfony/
どうしてもベタベタなSQL文を書く必要がある場合は、下記のようにprepareStatementを使う方法があります。
public static function doSelectProductByDayArr($arrSearch)
{
$num = 1;
if ($arrSearch['limit'])
{
$addLimit = "limit ?";
}
if ($arrSearch['start_datetime'])
{
$addStartDatetime = "AND regist_datetime >= ?";
}
if ($arrSearch['end_datetime'])
{
$addEndDatetime = "AND regist_datetime < ?";
}
$con = Propel::getConnection(ProductMstPeer::DATABASE_NAME);
$stmt = $con ->prepareStatement("SELECT
date(regist_datetime) as date,
count(regist_datetime) as cnt
FROM
product_mst
WHERE
site_id = ? AND
delete_flg = 'f' AND
csv_flg = 'f' AND
now() >= disp_day AND
now() < end_day AND
regist_datetime != '1970-01-01 00:00:00' AND
regist_datetime IS NOT NULL
$addStartDatetime
$addEndDatetime
GROUP BY
date
ORDER BY
date desc ".$addLimit.";");
$stmt->setString(1,$arrSearch['site_id']);
if ($arrSearch['limit'])
{
$stmt->setString(++$num,$arrSearch['limit']);
}
if ($arrSearch['start_datetime'])
{
$stmt->setString(++$num,$arrSearch['start_datetime']);
}
if ($arrSearch['end_datetime'])
{
$stmt->setString(++$num,$arrSearch['end_datetime']);
}
$rs = $stmt->executeQuery();
$i = 0;
while($rs->next())
{
$arrData[$i]['date'] = $rs->getString("date");
$arrData[$i]['cnt'] = $rs->getString("cnt");
$i++;
}
return $arrData;
}

