ラベル Symfony の投稿を表示しています。 すべての投稿を表示
ラベル Symfony の投稿を表示しています。 すべての投稿を表示

2010年7月25日日曜日

[PHP][Symfony][Doctrine]: DoctrineでIDをキーにレコードを取り出す

いくつかの案件でSymfony 1.4+Doctrineを使ってみて大体勝手が分かってきたので,メモ.

Doctrineで以下のテーブルがあったとする.

BlogPost:
columns:
title:
type: string(255)
body:
type: string()
この場合,自動的にidというフィールドが追加され,作られるテーブルは以下の通りになる(MySQL使用時).

mysql> show fields from blog_post;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| title | varchar(255) | YES | | NULL | |
| body | text | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+
ここで,IDを指定して1レコードだけ引っ張ってくる方法にはいくつかある.


$q = Doctrine_Query::create()
->from('BlogPost bp')
->where('bp.id = ?', $id);
$records = $q->execute();
if(count($records) > 0){
$record = $records[0];
}


$q = Doctrine_Query::create()
->from('BlogPost bp')
->where('bp.id = ?', $id);
$record = $q->fetchOne();


$record = Doctrine::getTable('BlogPost')->find($id);

最初の方法ではlimit文が付かないので,その分遅くなる.後の二つは発行されるSQLも同じ.
最後の方法は非常に手軽なので,覚えておくと楽.

2010年2月22日月曜日

[PHP][Symfony]: Symfonyプロジェクト内にSymfonyライブラリを含める

require_once dirname(__FILE__).'/../lib/vendor/symfony/autoload/sfCoreAutoload.class.php';
多数のSymfonyプロジェクトを扱っていて困るのは、既にリリースして安定稼働中のSymfonyプロジェクトと、新規で開発するSymfonyのバージョンが異なるというケースだ。
一応Symfony公式ページではupdate方法も書かれているが、安定稼働中の本番サイトのバージョンアップはやはりリスクが大きい。
なので、バージョンの違うSymfonyを共存させる方法を書いておく。

基本的にはSymfonyのライブラリディレクトリを丸ごとプロジェクトディレクトリ内(SF_ROOT以下のどこか)にコピーし、コンフィグファイルにそのディレクトリを指定してやれば良い。

古いバージョンのSymfonyだと、config/config.phpというファイルがあり、ここにSymfonyのパスを指定するようになっている。これを「dirname(__FILE__)."/../pear/symfony"」などに変えてやれば良い。

$ cat config/config.php
<?php

// symfony directories
$sf_symfony_lib_dir = '/usr/local/lib/php/symfony';
$sf_symfony_data_dir = '/usr/local/lib/php/data/symfony';
最近のバージョンの場合は、config/ProjectConfiguration.class.phpというファイルに設定があるので、最初にあるinclude行を

require_once dirname(__FILE__).'/../lib/vendor/symfony/autoload/sfCoreAutoload.class.php';

といった形で書きかえる。これでプロジェクトを丸ごと他のサーバに移動したときなども、問題なくSymfonyごと移行することができる。

2009年1月23日金曜日

[PHP][Symfony]: SymfonyのドキュメントルートのURLを取得する

Symfonyは基本的に専用のバーチャルドメインを立てて,web/index.phpがドキュメントルートにあることを前提としている(例えば,http://example.com/index.php).

しかし,ドキュメントルートには静的なコンテンツを置きたいとか,一つのバーチャルドメイン上で複数のSymfonyアプリケーションを動かしたいという時には,ドキュメントルート直下で無い所にindex.phpが置かれる.例えば,http://example.com/SF_APP/index.phpなどである.

この様にSymfonyのアプリケーションディレクトリがドキュメントルート直下にあることが保証されない場合,他のファイルのURLをどのように取得すればよいかが困る.
例えば,web/contents/hogehoge.dataといったデータを置いている場合,上記の場合で言えば「/SF_APP/」というサイト内絶対パスを取得する方法が必要になる.

これがスタイルシートやJavaScriptなら,stylesheet_path()やjavascript_path()といった関数がテンプレート内で使えるが,これらの関数は勝手に拡張子を補完したり,cssやjsディレクトリの補完を勝手にやってしまうため,その一つ上位のディレクトリであるwebディレクトリにアクセスすることはできない.

で,色々と検索してみたのだが,それっぽい関数は見つからなかったので,結局以下の方法に落ち着いた.
テンプレート内で,
dirname($sf_request->getScriptName());
これで,Symfonyのwebディレクトリに当たるディレクトリのサイト内絶対パスを取得することができる.
具体的には,

<a href="<?=dirname($sf_request->getScriptName())?>/contents/hogehoge.data">
の様な形式になる.

・・・でもこういった処理は何か関数がありそうなんだけどなぁ・・・

2009年1月22日木曜日

[PHP][Symfony]: 特定のスタイルシートを読み込まないようにする

# テスト環境はSymfony v1.2.0

Symfonyを使っていると,apps/APP_NAME/config/view.ymlに書いたデフォルトのスタイルシートは常に勝手に読み込まれることに気付く.
これは親切なのだが,デフォルトのapps/APP_NAME/templates/layout.phpを使わずに全て手動でHTMLを出力させたい時などには不便である.

例えば,apps/APP_NAME/templates/null.phpとして,以下のようなファイルを作る.

<?php echo $sf_content ?>

このレイアウトは,デフォルトのlayout.phpと違い,HTMLタグやHEADタグなどを含んでいないため,CSVを出力したり,HTML以外の任意のデータを出力する時に使う.
使い方は,Actionの中で

$this->setLayout('null');
とすればよい.

さて,このレイアウトテンプレートはCSSやXMLなどの非HTMLを出力する場合は問題なく機能する.
しかし,HTMLを出力しようとした際に問題が発生する.
というのは,アクションのテンプレートにHTMLを普段通り記述しただけでは,SymfonyがHEADタグを自動検出して,デフォルトのスタイルシートを読み込んでしまうのだ.

例えば,以下のテンプレートの場合,赤字の部分にデフォルトのスタイルシートが読み込まれる.

<html>
<head>
<meta ... />
<meta ... />
<!--ここに読み込まれる-->
</head>
<body>
</body>
</html>


デフォルトのスタイルシートを読み込みたくない場合,この動作はお節介なので,読み込まないように設定したい.
で,SymfonyのAPIドキュメントによると,Responseクラスを継承したsfWebResponseクラスにremoveStylesheet()というメソッドがあるので,これを使ってみるのだが,うまくいかないことが分かる.

public function executeHoge(sfWebRequest $request){
$response = $this->getResponse();
$response->removeStylesheet('stylesheet_to_remove');
return sfView::SUCCESS;
}

どうみても問題なさそうなのだが,やはりデフォルトのスタイルシートが挿入されてしまう.

で,お行儀が悪いが,テンプレートの方でこのメソッドを呼んでみる.

<?php
$sf_response->removeStylesheet('stylesheet_to_remove');
?>
<html>
<head>
<meta ... />
<meta ... />
</head>
<body>
</body>
</html>

すると,無事にスタイルシートが読み込まれなくなった.

どうやら,デフォルトのスタイルシートを挿入する処理は個別のActionのテンプレート処理の後に行うらしい.多分Filterか何かがやっているのだと思う.
この処理の順番を知らなかったのでかなりハマった.同じような経験をした人はいるのかな?