枯れたレガシーフレームワークは安定して収益を生むので、リプレースの必要をさほど感じないんですよね。
その結果、メモ書きでもいいから参考になる資料がどんどん枯れてきて、調べても調べても出てこないから「ウキャ〜!」ってなりませんか?なりますよねぇ。
ちなみに、symfony
は1まで。Symfony
てのは2以上になります。このフレームワークを開発している会社の社長がVer.2開発途中での社長自らの語った言葉のなかでVer.2以降はアッパーキャメルになると。知ってました?こういうのも枯れちゃうので書いときます。
「新しいぶどう酒は新しい革袋に」という格言がありますが、対抗勢力は得てして「古いのは旨い!」ってことで離れなられないものです。
やがて酸化しビネガー(酢)にしまうのに、いつまでもこだわってしまう。やはり旨いから…なんでしょうが、、、
Doctrineが古いのでファインダーの扱いがorz...
通常、
$searchParams = array(
'pref' => '北海道',
'postcode' => '0100110',
);
$r = $this->getTable()->findOneBy($searchParams);
で行けそうに思いますよね。Symfony
ならいけます。ググってもそういうのしか出ません。でもsymfony
ではNGのバージョンがあります。その場合、
$searchParams = array(
'0100110',
);
$r = $this->getTable()->findOneByPostcode($searchParams);
になります。先程のNGケースのような複数パラメータではどうするか?
$searchParams = array(
'北海道',
'0100110',
);
$r = $this->getTable()->findOneByPrefAndPostcode($searchParams);
And
で繋いでいく使い方になるのです。でもこれお察しの通り、郵便番号情報の更新なので、
- 郵便番号
- 都道府県名よみ
- 市区町村名よみ
- 丁目番地よみ
- 都道府県名
- 市区町村名
- 丁目番地
- 他にも色々...
とかをAnd
で繋いでいくとメンテナンス性の悪い呪文のようになってしまいます。しかも順番が違うと動かなかったりヘンテコになります。
じゃ、どうするか? $this->getTable()->createQuery()
を使って実装するのはどうでしょう。
$searchParams = array(
'北海道',
'0100110',
);
$r = $this->getTable()->createQuery()->where('`pref`=? AND `postcode`=?', $searchParams);
でもこれでは数多くの検索条件が加わった時のメリットを感じられません。それでバインド使ってみましょう。
$searchParams = array(
'pref' => '北海道',
'postcode' => '0100110',
);
$r = $this->getTable()->createQuery()->where('`pref`=:pref AND `postcode`=:postcode', $searchParams);
いかがです?これだと、検索条件が加わってもササッとメンテナンスできそうでしょ。
新しいテーブルを追加して動かす
スキーマ定義
まずschema.yml
に追加したいテーブルの定義を書く。
マイグレーションファイルの自動生成
続いて
./symfony doctrine:generate-migrations-diff
を実行。これでスキーマ差分が自動生成され、lib/migration/doctrine/
配下にマイグレーションファイルが出力されます。
テーブル自動生成
ファイル末尾にバージョンナンバーがついているので、[verson number]にその数を入れて
./symfony doctrine:migrate [verson number]
番号を入れなければ、上から順に実行していきます。
ちなみにやっぱりやめ、戻したければ、
./symfony doctrine:migrate [verson number] --down
これでテーブルは消えます。
基底クラスの生成
そして./symfony doctrine:build-model
を実行。基底クラス諸諸を作成してくれます。
BaseHogeFuga
HogeFuga
HogeFugaTable
こんなかんじのものを3つ。
フォームの生成
忘れそうなのがこれ。スキーマ定義でモデル編集用フォームで使われるウィジェットやバリデーターを生成しなければ。
ORMにDoctrineを使用しているならこうですね。
./symfony doctrine:build-forms
./form/doctrine/
配下に1つ、./form/doctrine/base
配下に1つ生成されます。
https://symfony.com/legacy/doc/gentle-introduction/1_4/ja/10-forms
ん?🤔↑ これ読み込んだらスキーマーベースで生成したフォームの第一引数にモデルのオブジェクト渡すことになってる。
さらに謎が深まるんだけど。。。
フォームのシリアライズ
その深い謎の究明にも取り組まね。その前に、浅めの沼からからどうぞ。
フォームのメンテナンス
いい記事を見つけたので、このリンクを辿ってみてください。
sfForm()を継承して作ったカスタムフォーム動作の謎
フォームは謎いわ〜。
フォームに入力して送信、バリデーションでエラーになって戻ってきたら全部消えてるってのはダメシステム。
だから初期値を設定して出力させたいのがフォーム実装の普通ですね。それで、次のように実装して…
class myCustomForm extends BaseForm
{
const NAME = 'my_custom';
public configure()
{
$this->widgetSchema->setNameFormat(self::NAME.'[%s]');
$this->setWidget(
'service',
new sfWidgetFormInputText(
array(
'default' => $this->getOption('service')
),
array(
'value' => $this->getOption('service')
)
)
);
}
}
カスタムフォームを出力するクラスを実装したのですが、それを使う側でこのように実装すると…
public function executeMyHome(sfWebRequest $request)
{
$service = $request->getParameter('service');
$default = array(
'service' => $service,
);
$params = $request->getParameter(myCustomForm::NAME);
$form = new myCustomForm($default);
$this->form = $form;
}
これだと$defaultの値が反映されて出力されません。このように出力されます。
<input type="text" name="my_custom[service]" class="my_custom_service">
value
が出力されて欲しいのです😓。それでハマりましたorz...
解決策①
アクション側で渡す位置をずらす。
public function executeMyHome(sfWebRequest $request)
{
$service = $request->getParameter('service');
$default = array(
'service' => $service,
);
$params = $request->getParameter(myCustomForm::NAME);
$form = new myCustomForm(null, $default);
$this->form = $form;
}
わかりますか? new myCustomForm(null, $default);
として値を設定します。
解決策②
フォーム側で受け取り方を、
class myCustomForm extends BaseForm
{
const NAME = 'my_custom';
public configure()
{
$this->widgetSchema->setNameFormat(self::NAME.'[%s]');
$this->setWidget(
'service',
new sfWidgetFormInputText(
array(
'default' => $this->getOption('service')
),
array(
//'value' => $this->getOption('service')
)
)
);
}
}
このように修正。うけとるようになりました。
<input value="$serviceの値が入るよ" type="text" name="my_custom[service]" class="my_custom_service">
でもこの記事書いた後で、なんかわかってきました。
myCustomForm($option, $attribute)
という扱いで、
// to:
$this->setWidget(
'mailTo',
new sfWidgetFormInputText(
array(), // $option側が適用される
array() // $attribute側が適用される
)
);
こういう構造になっているんですね。
じゃぁ疑問、みんなどうしてるのかな?初期値の設定を。
前半のarray()でdefaultで組むべきなのか?後半のvalueで組むべきなのか…
う〜謎い。コメントくだされ