page_adsence

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

2011年11月16日水曜日

symfonyでメンテナンス画面に簡単に切り替える方法

symfonyを使っている案件でDBメンテが入るため、サービス停止をしないといけない状況になった。
なんとか簡単にメンテナンス画面を出せないかと思っていたら、ありましたよ。
ググったら一発で出てきました。

ものすごく簡単にできました。
まず、メンテナンス中に表示するHTMLの用意をします。
用意する場所は以下の通り。

$ vi config/unavailable.php

この「unavailable.php」にメンテナンス中に表示させるHTMLを記載する。

次にsetting.ymlを編集します。

$ vi apps/アプリケーション名/config/settings.yml
all:
  .settings:
    check_lock: true

各環境で分けたい場合はprod、test、devのそれぞれの場所に書いてください。
で、念のためsymfony ccします。

以上で準備は完了です。

実際にメンテナンス画面にする方法は以下の通り

例)prod環境をメンテナンス中にする方法
$ ./symfony project:disable prod

例)dev環境をメンテナンス中にする方法
$ ./symfony project:disable dev

たったこれだけでメンテナンス画面に切り替えることが出来ます。
すばらしいですね。
ものすごい楽です。

メンテナンスを解除する場合
例)prod環境のメンテナンスを解除する方法
$ ./symfony project:enable prod

例)dev環境のメンテナンスを解除する方法
$ ./symfony project:enable dev

解除もこの通りです。
最高です。

2011年9月28日水曜日

DoctrineのSELECT文に関して

DoctrineでSELECT文を上書きする際にハマったのでメモ。

対象テーブルは2テーブル
・account(アカウント一覧)
・friends(友達一覧)
・check(チェックしたユーザー一覧)

以下のようなSQL文をDoctrineから生成しようとしたがうまくいかなかった。
SELECT *, account_id IN (1,2,3,4) AS is_friend FROM friends ORDER BY is_friend DESC;

やりたいことは以下の通り。
checkテーブルのデータを各種条件を指定して取得し、
そのデータを友達かどうかをキーにしてソートする。

最初に書いていたのはこんな感じ。

$query = Doctrine_Core::getTable('Check')
           ->select('*, account_id IN (1,2,3,4) as is_friend')
           ->where('delete_flg = ?', 0)
           ->limit(10)
           ->offset(0)
           ->orderBy('is_friend DESC');

SELECT内に書かれている「account_id IN (1,2,3,4)」の部分がうまく解釈されずに、
本来であればいる「1」かいないか「0」の2種類の結果がis_friendに格納されて返ってくるはずなのだが、
is_friendにはcheckテーブルに含まれるaccount_idが入って返ってきてしまっていた。

原因はどうやらparseSelectの中でやっている処理っぽい。
さすがにこの部分を書き換えるわけにはいかないので、
どうにかできないかと色々と試してはみたのだが、結局わからず終い。

どうしたものかと思っていたのだが、
だったら別のSQLの書き方で同じ結果を取得できるようにすればいいんじゃないかと思った。

JOINとかしてやる方法はパフォーマンス的に悪すぎるので却下。
なんとかSQL一発で取れる方法を探していたらありましたよ。

「CASE」

これ使えばいけるかもと思って、早速MySQLでコマンド叩いてみた。
SELECT *, CASE WHEN account_id IN (1,2,3,4) THEN 1 END AS is_friend FROM friends ORDER BY is_friend DESC;

いけた!
全く同じ結果ではないですが、is_friendに1かNULLが入る感じの結果が返ってきました。
CASEもう一個書けばNULLのとこを0返すようにできますが、必要ないと思ったのでやっていません。

で、今度はこれをちゃんとDoctrineが作ってくれるのかってとこです。

$query = Doctrine_Core::getTable('Check')
           ->select('*, CASE WHEN account_id IN (1,2,3,4) THEN 1 END AS is_friend')
           ->where('delete_flg = ?', 0)
           ->limit(10)
           ->offset(0)
           ->orderBy('is_friend DESC');

これを実行してみると、SQLのSyntaxエラーに…。
ググってみたら、意外とさっくり出てきた。
どうやらCASE~ENDの前後に括弧をつけるといけるらしい。
早速試してみた。

$query = Doctrine_Core::getTable('Check')
           ->select('*, (CASE WHEN account_id IN (1,2,3,4) THEN 1 END) AS is_friend')
           ->where('delete_flg = ?', 0)
           ->limit(10)
           ->offset(0)
           ->orderBy('is_friend DESC');

出来た!!!

エラーもなく、希望通りのレスポンスが返ってきました。
やはり複雑なSQLになるとDoctrineを使うのも一苦労ですね…。
Doctrineのキャッシュを使いたいがためにDoctrineで頑張ってやってましたけど、
それに見合うかどうかも判断する必要がありますね。
毎回こんな感じでハマってると時間がいくらあっても足りない…。

2011年9月21日水曜日

symfony2のインストール方法

今頃ですが、symfony2のインストール方法です。

今回は以下の環境にインストールをしていきます。
CentOS 5.5
Apache 2.2
PHP 5.3.6
MySQL 5.5.12

Symfonyの設置先ディレクトリは以下の通りです。
/path/to/dir/

まず設置先ディレクトリへ移動します。
$ cd /path/to/dir/

で、ここからソースをダウンロードしてきます。
「Symfony Standard」か「Symfony Standard without vendors」のいずれかを選択してダウンロードします。
通常は「Symfony Standard」をダウンロードしてくることになるかと思いますが、
gitをインストールしている環境では「Symfony Standard without vendors」を選択しても良いみたいです。
まぁ結局ダウンロードすることには変わりないので、お好きな方を選んで下さい。
「Symfony Standard without vendors」を選んだ場合には、ダウンロード後にgit経由でvendor系のファイルをインストールすることになります。

ダウンロードが完了後、落としてきたファイルを解凍します。
$ tar -xzpf Symfony_Standard_Vendors_2.0.1.tgz

解凍が完了すると、Symfonyディレクトリが作成され、その中にいくつかファイルやディレクトリがあります。

で、その解凍して出てきたSymfonyディレクトリへ移動。
$ cd Symfony

Symfonyがきちんと使用できる環境なのかチェックしてくれるファイルがありますので、
それを実行します。
$ php app/check.php
********************************
*                              *
*  Symfony requirements check  *
*                              *
********************************

php.ini used by PHP: /etc/php.ini

** WARNING **
*  The PHP CLI can use a different php.ini file
*  than the one used with your web server.
*  If this is the case, please ALSO launch this
*  utility from your web server.
** WARNING **

** Mandatory requirements **

  OK        Checking that PHP version is at least 5.3.2 (5.3.6 installed)
  OK        Checking that the "date.timezone" setting is set
  OK        Checking that app/cache/ directory is writable
  OK        Checking that the app/logs/ directory is writable
  OK        Checking that the json_encode() is available
  OK        Checking that the SQLite3 or PDO_SQLite extension is available
  OK        Checking that the session_start() is available
  OK        Checking that the ctype_alpha() is available
  OK        Checking that the APC version is at least 3.0.17

** Optional checks **

  OK        Checking that the PHP-XML module is installed
  OK        Checking that the libxml version is at least 2.6.21
  OK        Checking that the token_get_all() function is available
  OK        Checking that the mb_strlen() function is available
  OK        Checking that the iconv() function is available
  OK        Checking that the utf8_decode() is available


[[WARNING]] Checking that the posix_isatty() is available: FAILED
            *** Install and enable the php_posix extension (used to colorized the CLI output) ***


[[WARNING]] Checking that the intl extension is available: FAILED
            *** Install and enable the intl extension (used for validators) ***
  OK        Checking that a PHP accelerator is installed
  OK        Checking that php.ini has short_open_tag set to off
  OK        Checking that php.ini has magic_quotes_gpc set to off
  OK        Checking that php.ini has register_globals set to off
  OK        Checking that php.ini has session.auto_start set to off

** Optional checks (Doctrine) **

  OK        Checking that PDO is installed
  OK        Checking that PDO has some drivers installed: mysql, sqlite

今回の僕の環境では特になにもエラーが出なかったので何もしていませんが、
エラーが出た場合は不足しているものをインストールしてあげましょう。

で、この後にwithout vendorsを選んだ方はvendorライブラリをインストールします。
$ php bin/vendors install

以上で設置作業は完了です。

ここからはバーチャルホストの設定ですが割愛します。
ドキュメントルートは以下のディレクトリに設定します。
/path/to/dir/Symfony/web

webディレクトリ直下にconfig.phpというファイルがありますので、
ブラウザからここにアクセスしてみます。
但し、localhostからしかアクセスできるようになっていないので、適宜修正して下さい。
僕の場合は自分のIPを追加しておきました。

設定が成功していると「Symfony Configuration」というタイトルのページが表示されます。
以上でSymfonyの設置は完了です。

次回はSymfony2の初期設定の手順を書いていきたいと思います。

2011年9月12日月曜日

myPageStateとmemcacheの相性の悪さに関して

前の会社の人が作ったライブラリでmyPageState.class.phpを今回の案件で使用してみたのですが、
memcacheとの相性が悪いのか、symfony1.4との相性が悪いのかよくわかりませんが、セッションから値が取れないという不具合が発生しました。

前の会社でもsymfony(ver.1.2ですが)を使ってフォームを作る時には大体使っていたのですが、
こういったことは起こったことがありませんでした。

なので消去法でいくと一番怪しいのはmemcacheかなと。

最初はmemcacheにオブジェクトを突っ込んでた(memcacheが勝手にserializeする)んですが、
その場合には3割位の確率でmyPageState経由で保存したセッション情報の取得に失敗してしまうという現象が起きました。
仕方ないのでオブジェクトを配列にして保存するように修正してみた。
一応発生しにくくはなったものの、根本的な原因がわかってないので、
発生しないという状態までは持っていけませんでした。
しかし一体何が原因なんだろう…。
不思議です。

2011年9月7日水曜日

symfonyのfilterに関して

symfonyを久々に使って、filterを使うことになった。
symfonyの中核を担っているらしいフィルタの機能ですが、今回初めて使ってみた。
フィルタは必ず通るので、全部に対して通したい場合は比較的楽なんですが、
ユーザーのステータスを見て、どこかにリダイレクトとかさせたりする場合は、
下手をすると無限ループに陥るので注意が必要。
一度無限ループに陥ると、どういう状態になっているのか分からなくなってしまうので、
きちんと状態をログファイルに出力するようにしたほうがよい。

filterの設置場所は以下の通り。
project_root/app/アプリ名/lib/filter/~Filter.class.php

基本的な書き方としては以下の通り。
<?php
class myTestFilter extends sfFilter
{
  public function execute($filterChain)
  {
    // 入力時に実行されるfilter
    if ($this->isFirstCall())
    {
      // contextとかはこうやって取れる
      $context    = $this->getContext();
      $user       = $context->getUser();
      $controller = $context->getController();
      $request    = $context->getRequest();

    }

    $filterChain->execute();

    // 出力時に実行されるfilter
  }
}

ちなみにログの出力方法はこんな感じ。
$logger = sfContext::getInstance()->getLogger();
$logger->info('ログメッセージ');

2011年9月1日木曜日

symfonyのprod環境のログ出力に関して

symfonyのprod環境に関してはプロジェクトルート以下に作成されているlogディレクトリ以下に、
ログファイルが作成されないようになっている。
これを出力するように変更するには、各アプリケーションディレクトリの下にあるコンフィグファイル内にあるfactories.ymlを修正する必要がある。

prod:
#  logger:
#    class:   sfNoLogger
#    param:
#      level:   err
#      loggers: ~


この部分を上記のようにコメントアウトすることで、ログファイルが生成されるようになる。

ちなみに、 自分でアプリケーションログに吐きだしたい場合は以下のように書くことで出力が可能になる。

$logger = sfContext::getInstance()->getLogger();
$logger->info('出力したいメッセージ');

2010年10月27日水曜日

さくらレンタルサーバではまった。

さくらレンタルサーバはもう使いたくないってくらいへんな仕様が多い・・・。
hoge.htmlというファイルがあって、「http://www.hogehoge.jp/hoge」のようなURLのリクエストがあった場合、
通常であれば404 Not Foundになるはずなのに、
拡張子の前までの文字のファイルを検索して、マッチしたファイルを表示してしまう。
つまり下記の2つは一緒のファイルが表示される。

http://www.hogehoge.jp/hoge
http://www.hogehoge.jp/hoge.html

この仕様のせいでsymfonyがうまく動かなくて、手間取った。
routing.ymlに書いてあるにも関わらず、デフォルトのルールにマッチしてしまい、
404 Not Foundになってしまうということが起きた。
apacheのmod_rewriteのせいとか色々疑ってみたけど、symfony内部の処理のせいだった。
sfWebRequest.class.phpの中を修正しないとちゃんと動かない。

/**
 * Retrieves the path info for the current web request.
 *
 * @return string Path info
 */
public function getPathInfo()
{
  $pathInfo = '';

  $pathArray = $this->getPathInfoArray();
  // simulate PATH_INFO if needed
  $sf_path_info_key = $this->options['path_info_key'];
  if ( !preg_match('/^(.*)\.php$/', $this->getScriptName(), $matched) ) unset($pathArray[$sf_path_info_key]);
  if (!isset($pathArray[$sf_path_info_key]) || !$pathArray[$sf_path_info_key])
  {
    if (isset($pathArray['REQUEST_URI']))
    {
      $qs = isset($pathArray['QUERY_STRING']) ? $pathArray['QUERY_STRING'] : '';
      $script_name = $this->getScriptName();
      if ( !preg_match('/^(.*)\.php$/', $script_name, $matched) ) $script_name .= '.php';
      else $script_name = $matched[1];
      $uri_prefix = $this->isAbsUri() ? $this->getUriPrefix() : '';
      $pathInfo = preg_replace('/^'.preg_quote($uri_prefix, '/').'/','',$pathArray['REQUEST_URI']);
      $pathInfo = preg_replace('/^'.preg_quote($script_name, '/').'/', '', $pathInfo);
      $prefix_name = preg_replace('#/[^/]+$#', '', $script_name);
      $pathInfo = preg_replace('/^'.preg_quote($prefix_name, '/').'/', '', $pathInfo);
      $pathInfo = preg_replace('/\??'.preg_quote($qs, '/').'$/', '', $pathInfo);
    }
  }
  else
  {
    $pathInfo = $pathArray[$sf_path_info_key];
    if ($relativeUrlRoot = $this->getRelativeUrlRoot())
    {
      $pathInfo = preg_replace('/^'.str_replace('/', '\\/', $relativeUrlRoot).'\//', '', $pathInfo);
    }
  }

  // for IIS
  if (isset($_SERVER['SERVER_SOFTWARE']) && false !== stripos($_SERVER['SERVER_SOFTWARE'], 'iis') && $pos = stripos($pathInfo, '.php'))
  {
    $pathInfo = substr($pathInfo, $pos + 4);
  }

  if (!$pathInfo)
  {
    $pathInfo = '/';
  }

  return $pathInfo;
}

上記のように赤文字になっている部分の処理を修正する必要がある。

2010年10月4日月曜日

doctrineでcreated_atとupdated_atに自動で日付を入れる方法

今回初めてdoctrineを使っていて、作成日と更新日に時間が自動で入っていないことに気づいた。
Propelの場合は何もしなくても、勝手に入れてくれていたが、doctrineはそうではないらしい。
調べてみるとschema.ymlに以下のような記述を追加すればできるみたい。

モデル名がTableName、テーブル名がtable_nameに対して自動で日付を入れる場合
config/doctrine/schema.ymlを開いて以下のように「actAs: { Timestampable: ~ }」の行を追加する。

TableName:
  actAs: { Timestampable: ~ }
  connection: doctrine
  tableName: table_name
  columns:
    table_id:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: true
      :
      :

といった感じ。
Timestampableの値が「~」ってなってて、なんだこれと思ったけど、追加してみるとちゃんと動いた。
追加した後はモデルを再生成する。
そうするとBaseTableNameクラスのsetUpという関数の中に以下の記述が追加される。

$timestampable0 = new Doctrine_Template_Timestampable();
$this->actAs($timestampable0);

これで変更作業は完了。
あとはsaveメソッドで保存したものに関しては作成日付と更新日付が自動で挿入されるようになる。

2010年9月14日火曜日

doctrineで生成するschema.ymlに関して

symfonyのタスクでデータベース上に保存されているデータをfixture形式でダンプを取ってくれるタスクがあり、
それを実行してみた。

symfony doctrine:data-dump

すると、
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'v.id' ~
v.idってカラムがないらしい。
そもそもidなんてカラム作ってないのになんでこんなことになってるんだと思って調べてみたら、
エラーが出たのはViewの部分の記述だった。
そこで、schema.ymlを見てみた。
中を見てみると

VHoge:
  connection: doctrine
  tableName: v_hoge
  columns:
    id:
      type: integer(8)
      autoincrement: true
      primary: true
    fuga_id:
      type: integer(4)
      fixed: false
      unsigned: true
      primary: true
      default: '0'
      notnull: true
      autoincrement: false
idってカラムがありました・・・。
なんでこんなカラムが追加されてるんだと思いながらも、削除してみた。
モデルも再生成して、もっかい実行。
同じエラーが・・・。
カラムは削除したはずなのになーと思いながらも、primaryがtrueになっているカラムがないといけないのではないかと思い、fuga_idのprimaryをtrueにして、モデルを再生成して実行してみたら成功しました。

どうやらschema.ymlには必ずprimaryがtrueになっているカラムが1つないとエラーになるみたいです。
あとでソースを追って、ちゃんとした原因を突き止めよう。

2010年9月3日金曜日

symfonyのセキュリティの設定に関して

最近ちょくちょくsymfonyを触るようになってきたので、一度セキュリティに関して調べてみた。
今回気になったのは下記の記事。

http://blog.symfony.jp/2009/03/05/178

この記事ではsf_charsetがUTF-8で、なおかつescaping_methodをESC_ENTITIESにすると問題があるというものです。
古いバージョンのsymfonyではデフォルトがESC_ENTITIESになっていましたが、
1.2以降のsymfonyではデフォルト値がESC_SPECIALCHARSに書き換えられているようですので、
自分で意図的に変更しない限りはトラブルに見舞われることはないと思われますが、一応念のため記事にしておくことにしました。

symfonyでは標準でHTML出力のエスケープ処理が組み込まれており、テンプレートにスカラ、配列、オブジェクトのメソッド呼び出しの結果など、あらゆる値がエスケープされるようになっています。
そのエスケープメソッドがhtmlentitiesであると問題が発生するよということ。
このhtmlentitiesですが、マルチバイトでなければ何の問題もありませんが、
マルチバイトでUTF-8の文字コードの場合に未定義の文字参照が生成されてしまうおそれがあります。
こちらのブログでは「∵」(U+2235)がその該当の文字だということで、取り上げられています。

symfony1.4ではescaping_strategyはデフォルトtrue、escaping_methodもESC_SPECIALCHARSとなっているので、
特に心配する必要はありません。
とはいえ、古いsymfonyを使っている案件の更新とか、途中からアサインされた場合に設定がESC_ENTITIESになっている可能性が0ではないので、一応覚えておこうと思う。

・リファレンス
http://www.symfony-project.org/reference/1_4/ja/04-Settings#chapter_04_sub_escaping_strategy

2010年8月27日金曜日

symfonyのフロントコントローラーとrouting.ymlにはまった

symfonyでフロントエンドと管理画面のアプリを作成しようと思った時にrouting.ymlに記述した変数が取得できなくて、
なんで取得できないのかさっぱりわからなくて、いろいろ検証してみた。



最初の状態はこんな感じ

web/index.php ← フロントエンド用のフロントコントローラー
web/manager.php ← 管理画面用のフロントコントローラー


まず、新しくプロジェクト作成してまっさらな状態できちんと取れるか試してみた。

routing.ymlはこんな感じ

testIndex:
url: /test
param: { module: test, action: index }

test:
url: /test/:value
param: { module: test, action: index }


この場合は特に問題なく取得することができた。



次にルーティングのURLの階層を増やしてみたが、これも問題なかった。



testIndex:
url: /dummyA/dummyB/test
param: { module: test, action: index }

test:
url: /dummyA/dummyB/test/:value
param: { module: test, action: index }


管理画面用のフロントコントローラーの場所を一階層下に変えてみた。



web/manager/index.php


それに伴い.htaccessを書き加えた。



RewriteRule ^manager(.*)$ manager/index.php [QSA,L]


こうするとvalueが取れなくなった。

mod_rewriteのせいなのかもしれない。

が、これをどう書き直せばrouting.ymlがちゃんと取ってくれるのかがわからない…。

そこで、フロントコントローラーのファイル名と場所を元に戻し、.htaccessを以下のように修正してみた。



RewriteRule ^manager(.*)$ manager.php [QSA,L]


こうすると取得できるようになった。

とりあえずこれでよしとする。

2010年8月25日水曜日

symfonyのWebデバックツールに関して

symfonyでプロジェクトとアプリケーションを1つ作成すると、webディレクトリ以下にindex.phpなどのファイルができ、symfonyのデフォルトページを表示させることができるようになるが、この画面で使用されている画像や、webデバックツール(デバックモードで画面右上に表示されるツールバー)に使用されている画像などは初期状態ではパスが違っているため、読み込みできない。
違っている理由としてはスケルトンが用意されており、そこからパスを変更せずにコピーしてくるためである。
それを回避するために、シンボリックリンクを張っていたんですが、バーチャルホストのAliasに書くほうがすっきりしてていい気がしてきたので、これからはその方法でやっていきたいと思う。

2010年7月27日火曜日

doctrineで生成されるBase~.class.phpと~.class.phpと~Table.class.phpの棲み分けについて

doctrineでmodelを生成すると1つのテーブルに対して以下の3ファイルが生成されます。

例)テーブル名がhogeだった場合に作成されたモデルクラスの場合

base/BaseHoge.class.php
Hoge.class.php
HogeTable.class.php

これらのファイルにはそれぞれ違った役割があり、
それを意識することで綺麗なコードが書けるようになると思います。

BaseHoge.class.phpに関して
こちらはbuildするたびに書き換えられてしまうので、触らないようにしましょう。
もし修正してもbuild-modelのコマンドを実行した時点で新しいファイルに差し替わってしまいます。

HogeTable.class.phpに関して
このクラス内ではテーブルからレコードを取得する処理を記述する。
ようは、テーブルに対して行う処理に関しては全てここに記述する。

Hoge.class.phpに関して
HogeTable.class.phpで取得したレコードに対して処理を実行する場合はこちらに記述する。
つまり、テーブルにレコードを直接取得するような記述は書かない。
あくまでHogeTable.class.phpで取得してきた取得結果に対しての処理を記述するのがこっち。

以上が棲み分けになる。
なぜこのようになるかというのは、継承関係が以下のようになっているからってことみたいです。
・Doctrine_Record > sfDoctrineRecord > Hogeクラス
・Doctrine_Table > HogeTableクラス

・参考文献
http://www.kazu.tv/blog/archives/000954.html

2010年7月25日日曜日

symfonyでContent-Typeを指定する

Conotent-TypeにあるcharsetはApacheで設定したAddDefaultCharsetが基本的には設定されるが、
この部分がコメントアウトされている場合にはcharsetが指定されずにHTTPリクエストヘッダがやりとりされる。

Content-Type text/html

といった感じ。
が、文字化けを防ぐためには、Content-Type内にcharsetを指定しておくほうがいいと思う。
でも、Apacheで設定しまうと、1台のサーバで複数のサイトを運営していた場合に不都合がでる可能性がないとも言い切れない。
そこでsymfonyではview.ymlにContent-Typeが指定できるようになっているので、
これを利用することにする。
以下はview.ymlの記述を抜粋したものである。

default:
  http_metas:
    content-type: text/html

このようになっている部分を以下部分の記述を追加してやる。

default:
  http_metas:
    content-type: text/html; charset=sjis

この用にすればアプリケーションレベルで文字コードを設定することができる。

2010年7月13日火曜日

mod_rewriteが効かない

symfonyでrouting.ymlに記述しているにも関わらず、全然効いてない。
キャッシュかなと思ったけど、symfony ccしてみたけど直らない。
で、mod_rewriteがちゃんと効いてるかどうか確認してみたら、これが効いてなかった・・・。
AllowOverrideはちゃんと書いたのになんでだろうと思って、
httpd.confをよく見てみたら

<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>

になってた・・・。
Directoryは記述された階層で書いた設定が、それ以下のディレクトリ全体に反映される。
つまり今回の場合は全てのディレクトリでAllowOverrideは使えないよって状態になっていた。
前からこんなの書いてあったっけと思いつつもこのDirectoryの部分をコメントアウト。
apache再起動。

Internal Server Error

あれっと思ってエラーログを確認すると、

[Wed Jun 16 18:19:22 2010] [alert] [client 192.168.XXX.XXX] /path/to/directory/web/.htaccess: Option FollowSymLinks not allowed here

FollowSymLinksは有効になってないからだめってことみたい。
ちなみにFollowSymLinksとはシンボリックリンクが有る場合はそのリンク先の参照を許可するって設定。

$ vi web/.htaccess
Options +FollowSymLinks +ExecCGI

<IfModule mod_rewrite.c>
RewriteEngine On

# uncomment the following line, if you are having trouble
# getting no_script_name to work
#RewriteBase /

# we skip all files with .something
#RewriteCond %{REQUEST_URI} \..+$
#RewriteCond %{REQUEST_URI} !\.html$
#RewriteRule .* - [L]

# we check if the .html version is here (caching)
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f

# no, so we redirect to our front web controller
RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

確かにsymfonyの初期状態で生成される.htaccessにはFollowSymLinksの指定が追加されている。
じゃあこれを消せば問題解決のはず。
$ vi web/.htaccess
Options +ExecCGI
以下略


で、アクセスしてみたら問題なかった。

2010年6月16日水曜日

symfony1.4.5でアドミンジェネレーターを作成

楽に管理画面が作れるって聞いてたので使ってみた。
まず結果。

できませんでした・・・。

今回はフロントエンドなしの状態から管理画面を作ろうとしました。
まずこのページにやりかたが書いてあったので、これをベースに進めていきます。
1.プロジェクト作る。
$ ./symfony generate:project test_project

2.database.ymlをデータベースに接続できる状況にする。
$ vi config/database.yml

all:
doctrine:
class: sfDoctrineDatabase
param:
dsn: mysql:host=localhost;dbname=test
username: your_database_username
password: your_database_password

3.管理画面用にアプリケーションを作る。
$ ./symfony generate:app test_project test_app

4.schema.ymlを作るんですが、今回はMySQL_Workbenchを使ってsqlを作っておいたので、
それをデータベースに入れてからbuild-schemaでschema.ymlを作ります。
$ ./symfony doctrine:build-schema

するとconfig/doctrine/schema.ymlができます。
5.fixtures.ymlを作ります。データはとりあえず1つだけ作ります。
$ vi data/fixtures/fixtures.yml

Tablename:
Tablename_1:
field_name1: field_value
:
:

6.doctrine:build-all-reloadってタスクを実行しているのですが、僕の作った環境にはなかったので、
順番に実行していきました。何度も実行するなら自分でタスク作ったほうがいいと思います。
データベースを削除

データベースを新規作成

モデルの作成

モデルからsqlの作成

フォームクラスを作成

フィルターフォームクラスを作成

fixtures.ymlの読み込み

7.apps/test_app/config/routing.ymlに記述を追加
your_database_table_name:
class: sfDoctrineRouteCollection
options:
model: your_database_table_model_class_name
module: your_app_modlue_name
prefix_path: なぞ
column: primary_key_id ← これを書かなかったらエラーになったので追加した。
with_wildcard_routes: true

8.管理画面を作成するタスクを実行する
$ ./symfony doctrine:generate-admin test_app module_name

とりあえずこんな感じで管理画面自体は見れるようにはなったが、以下のような不具合があった。
・cssが読み込まれていなかった→これは
・日本語が文字化けしてる。
・データベースのフィールド数が多い場合リスト表示のテーブルと詳細表示のテーブルが重なって見えない

いろいろよくわからなくて調べた時の資料。
- filterとかformをgenerateし忘れたときにでたエラーの回答
http://samsami2u.wordpress.com/2009/04/06/class-formfilter-not-found-in-symfony/
- デバックモード時にでるconfigのタブの中にあるUserのリストの中のdefault_cultureやcultureを変更しようとした時に調べた資料。結局未解決
http://www.symfony-project.org/jobeet/1_4/Propel/ja/19
http://www.symfony-project.org/reference/1_4/ja/04-Settings
http://www.symfony-project.org/reference/1_4/ja/05-Factories
http://www.kazu.tv/blog/archives/000929.html
http://www.pistolfly.jp/weblog/2006/11/default-culture.html
http://www.pistolfly.jp/weblog/2006/12/userculture.html

2010年6月12日土曜日

pear経由でsymfonyのインストール手順

まずpearがインストールされているかを確認。

$ which pear
/usr/bin/pear

pearがインストールされていることを確認。

でpearコマンドを使ってsymfonyをインストールする。

環境依存を極力なくすためにライブラリはすべてプロジェクトディレクトリ内にインストールすることが好ましい。

なので今回は以下のようなvendorディレクトリを作成し、その下にsymfonyをインストールする。

$ mkdir project_dir/vendor
$ cd vendor

$ pear config-create /path/to/project_dir/vendor .pearrc
Configuration (channel pear.php.net):
=====================================
Auto-discover new Channels auto_discover
Default Channel default_channel pear.php.net
HTTP Proxy Server Address http_proxy
PEAR server [DEPRECATED] master_server
Default Channel Mirror preferred_mirror
Remote Configuration File remote_config
PEAR executables directory bin_dir /path/to/project_dir/vendor/pear
PEAR documentation directory doc_dir /path/to/project_dir/vendor/pear/docs
PHP extension directory ext_dir /path/to/project_dir/vendor/pear/ext
PEAR directory php_dir /path/to/project_dir/vendor/pear/php
PEAR Installer cache directory cache_dir /path/to/project_dir/vendor/pear/cache
PEAR data directory data_dir /path/to/project_dir/vendor/pear/data
PHP CLI/CGI binary php_bin
PEAR test directory test_dir /path/to/project_dir/vendor/pear/tests
Cache TimeToLive cache_ttl
Preferred Package State preferred_state
Unix file mask umask
Debug Log Level verbose
PEAR password (for password
maintainers)
Signature Handling Program sig_bin
Signature Key Directory sig_keydir
Signature Key Id sig_keyid
Package Signature Type sig_type
PEAR username (for username
maintainers)
User Configuration File Filename /path/to/project_dir/vendor/.pearrc
System Configuration File Filename #no#system#config#
Successfully created default configuration file "/path/to/project_dir/vendor/.pearrc"

pearコマンドを使ってsymfonyのpearチャンネルを登録し、バージョンを指定してインストールを行う

$ pear -c .pearrc channel-discover pear.symfony-project.com
Adding Channel "pear.symfony-project.com" succeeded
Discovery of channel "pear.symfony-project.com" succeeded

symfonyの1.4.5をインストール

$ pear -c .pearrc install -a symfony/symfony-1.4.5
symfony/symfony requires PHP extension "dom"
No valid packages found
install failed

今度はdomがないのでrootユーザーになってyumでインストール
# yum install php-dom

もう一度symfonyをインストール
$ pear -c .pearrc install -a symfony/symfony-1.4.5
downloading symfony-1.4.5.tgz ...
Starting to download symfony-1.4.5.tgz (3,171,881 bytes)
.............done: 3,171,881 bytes
install ok: channel://pear.symfony-project.com/symfony-1.4.5

あとはvendorディレクトリから、プロジェクトルートディレクトリに戻り、インストールしたsymfonyパッケージからプロジェクトの初期化を行う

$ vendor/pear/symfony generate:project example

これでインストールは完了。

Subversionを使用している場合にはプロジェクトディレクトリ内をsvn addしてからsvn ciする