ぷぎがぽぎ このページをアンテナに追加 RSSフィード

2008-12-02

[][][] symfony + Doctrine 公式ドキュメント

"The symfony and Doctrine book" is part of the official symfony documentation.

symfony | Web PHP Framework | The symfony and Doctrine book

以前から本家のリポジトリにこのドキュメントの下書きがあることは知っていて、既に全部読んでいたりしますが、具体的なDQLの書き方のサンプルなど分かりやすくDoctrineを使うならば確実にお世話になるはずです。

にしてもjobeetといいこのドキュメントといいsymfonyのドキュメントがどんどん増えてくる。。

2008-11-18

[][][] parent::setName($value)は使わずに$this->_set('name', $value)を使え

昨日の続き。

まず、現象の再現方法。

現在某ブログでaskeetをsymfony1.2で実践中なのですが、

symfony+Doctrineでレコード(Doctrine_Record)のプロパティ(body)のセッター部分をハックし、html_bodyというプロバティにMarkdown形式で上書きたい場合のお話です。

本家チュートリアルのように、意識せずPropelのコードと同様に以下のようなaskeetのコードを書いてブラウザから登録を行うと。。

class Question extends BaseQuestion
{
  ....
  public function setBody($v)
  {
    require_once('markdown.php');
    parent::setBody($v); // <= ここで落ちる
    // strip all HTML tags
    $v = htmlentities($v, ENT_QUOTES, sfConfig::get('sf_charset'));
    $this->setHtmlBody(markdown($v));
  }

見事にセグメンテーションエラー。(PHP5.2.6)

[notice] child pid 23191 exit signal Segmentation fault (11)

しかも、不思議なことにdoctrine:data-loadの場合はエラーで落ちずにちゃんと読み込んでくれます。

parent::setBodyメソッド部分で落ちているのはわかったのですが、原因がわからない。。

確かにDoctrineはマジックメソッドを多用しているので、Propelのように親クラスにはsetBodyというメソッドはありません。

でもそれで動くのがマジックメソッドのはずなのに。。。

で、公式ドキュメントみても該当するものが無いと諦めかけていたときにようやく見つけました。まさにこの現象についての記事を。

The _set() and _get() methods must be used to avoid a infinite loop when overriding accessors and mutators.

symfony | Web PHP Framework | Blog | New in symfony 1.2: Doctrine goodies

アクセッサを上書きすると無限ループになっちゃうと。なので、アクセッサとしてDoctrine_Recordに用意された_set()メソッドと_get()メソッドを使えと。

というかまぢですか。

とりあえず、以下のコードがプロパティを上書きするための正しいDoctrineのコード。

class Question extends BaseQuestion
{
  ....
  public function setBody($v)
  {
    require_once('markdown.php');
    $this->_set('body', $v);
    // strip all HTML tags
    $v = htmlentities($v, ENT_QUOTES, sfConfig::get('sf_charset'));
    $this->_set('html_body', markdown($v));
  }

これは知らないとはまる。

2008-08-28

[][][] 単数形に変換されないようにする

symfony1.1を使い始めると同時にDoctrineに乗り換えました。

Propelに比べたらかなり直感的ですし、明らかに学習コストも低いですね。

もちろん、Propelだけにしか対応していないようなプラグインも多々あるので、その辺りと天秤にかけて決定すると良いよ。

で、お題の件。

自分の場合は、スキーマファイルはDBを作成した後に、タスクコマンドで生成するようにしています。

一番の理由はyamlやXMLの記述間違いで時間をつぶしたくないのと、phpMyAdminなどでテーブルを作成したほうが早いですし。

さらには、スキーマファイルからテーブル作成すると勝手にdropされることもあるし。。

で、いつものように物理的なテーブルを作成してから以下のコマンドで作成しました。

$ ./symfony doctrine:build-schema backend

そうすると作成されたschema.ymlを見てみるとテーブル名がGoodsのモデル名がGoodに。。

Doctrineのマニュアルにはちゃんと書いてありますね。。

デフォルトではDoctrineは既存のデータベースから読み込まれた各モデルの名前を単数型にしようとします。

1.4.3 インポートの際のテーブル名の単数形化

このルールのために、コマンドで既存DBからスキーマを作成させると単数形のモデル名でschema.ymlが作成されてしまいます。

propelしか触った事がなければ「なぬ!」となりますが、

DoctrineはActive Recordの影響を受けてますのでCakePHPをつかったことがあれば「あー。あれね」ぐらいなものでしょうか。

これをキッカケにこの規則に合わせようかとも思いましたが、Goodに違和感を感じてしまいます。(設計の段階でItemsとかにすれば良いのにというオチなんですけどね。。。)

というわけで、この設定を無効にするためDoctrine_Managerのattributeの singularize_importを falseにしなさいとマニュアルには書いてあります。

symfonyではDoctrineはプラグインでインストールしていますので、プラグインの設定をすればよさげです。

そこで、<プロジェクトルート>/config/doctrine.ymlというファイルを作成して

all:
  attributes:
    singularize_import: false 

としてやるだけで設定を無効にできました。

2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2016 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |