トップ » サービス » 技術情報 » symfony » その他 » symfony モデルクラス生成ツール
symfony

symfony モデルクラス生成ツール - 記述日2009/1/23 - 綿引


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);

↑Pagetop


モデルクラス生成ツールver1.0.0 ドキュメント †

【動作確認済バージョン】

  • symfony-1.0.14
  • postgresql-8.1.3 ~ 8.1.11

【使用条件】

symfonyがインストールされたサーバ環境が必要です。
xampp等がインストールされたローカル環境でも使用可能?(未確認)

【インストール】

解凍した後、/mkModel/フォルダを、ご利用の環境のモジュールディレクトリの配下に置いてください。
※設置場所例:/プロジェクトルート/apps/アプリケーション名/modules/

【アンインストール】

インストール時に設置したフォルダを削除して下さい。
レジストリ等は一切使っていません。

【使用方法】

インストールしたサーバにブラウザでアクセス
例:http://192.168.1.xxx/index.php/mkModel/index
コントローラ名(index.php)とアクション名(index)は環境によっては省略可。


下記のような画面が表示されます。

  • 使用するスキーマファイルを選択
    /プロジェクトルート/config/直下にあるスキーマファイルからのみ選択できます。
  • モデルクラスを作成したいテーブルの名称を入力
    例:商品マスタ(product_mst)のモデルクラスを作成したい場合は「product_mst」と入力
  • JOINテーブル名を入力
    JOINする可能性のあるテーブルの名称を入力します。
    複数あるばあいは「,(カンマ)」区切りで入力してください。
  • ファイル生成場所を入力
    デフォルトは /プロジェクトルート/lib/mkModel/です。
    ディレクトリが存在しない場合は新規に作成します。
  • 生成実行ボタンをクリック
    →指定された生成場所にモデルクラスを作成します。
    「テーブル名.php」と「テーブル名Peer.php」の2ファイル作成されます。
  • 生成された2ファイルを設置
    propel-build-modelコマンドで生成されているモデルクラスのディレクトリに設置してください。>
    例:/プロジェクトルート/lib/model/配下

※propel-build-modelコマンドを実行した時点で子クラスは生成されています。
全て空の状態ですので、上書き保存してください。

以上で、アクション側から呼び出して使用できるようになります。

↑Pagetop


【指定できる検索条件】

  • 完全一致
$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    … 指定したカラムの降順
  • limit/offset
$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'));
	}
}

  • テンプレート記述例
    ※他のページでも使えるよう、page_naviを別ファイルにしておく
<?php echo include_partial("global/page_navi", array('objPageNavi' => $objPager, 'linkto' => '/list','arrParm' => $sf_request->getAttributeHolder()->getAll())) ?>
  • ページャ記述例(/プロジェクトルート/apps/アプリケーション名/templates/_page_navi.php
<?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; ?>

↑Pagetop


【おまけ】

サブクエリーや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;
}

symfony 最新記事

↑Pagetop