(0)
(0)
(0)
(0)
Total: 0 symfonyでの開発を楽にする3つの方法
symfonyの開発は慣れていても思い出すのは大変
symfonyで開発して多少慣れてくると色々と面倒だなぁと思う事があります。その1つが実装方法やサンプルコードを思い返すのに時間が掛かるということです。
今日は、この問題をちょこっと解決できる3つの方法
- installerを利用する
- skeletonを利用する
- generatorを利用する
について紹介したいと思います。
下準備
今回紹介する方法はsymfonyが元々持っているスケルトンやジェネレーターを自前で用意するということです。
サンプルのコードはgithubに置きましたのでお好きなディレクトリにcloneなりしておきます。
ここでは、helpというディレクトリに展開しました。
% git clone git@github.com:brtriver/exSymfonyForBiginner.git ./help
そして、symfonyのプロジェクトは並列のディレクトリにsampleという名前で作成してあります。
|-- help
| |-- generator
| |-- installer
| |-- lib
| `-- skeleton
`-- sample
|-- apps
|-- cache
|-- config
|-- data
|-- lib
|-- log
|-- plugins
|-- test
`-- web
自前installerを利用する
sfFormExtraPluginはいつも使うのにインストールが面倒
ということがあると思います。もしくは、自社で利用するプラグインなどは毎回手作業でインストールするというのも大変です。
こういった場合は、generate:project実行時にinstallerを指定することができ、プロジェクト生成時にプラグインもインストールしてしまうことができるのです。
以下のようなinstaller.phpを用意し、
-
<?php
-
$this->logSection('install', 'add plugin sfFormExtraPlugin');
-
$this->getFilesystem()->execute('svn co http://svn.symfony-project.org/plugins/sfFormExtraPlugin/branches/1.3 plugins/sfFormExtraPlugin');
-
$this->enablePlugin('sfFormExtraPlugin');
/.symfony generate:project sample --installer=../help/installer/installer.php
のように--installerオプションでファイルのパスを指定してあげるだけです。
Doctrineのスキーマの書き方なんて覚えられない
schema.ymlはカラムの定義からリレーションやビヘイビアなど多くの定義が書けます。でも、全部を完全に覚えている人は居ないでしょう。チートシートを見ながら、もしくは本家サイトのドキュメントを見ながら...という人がほとんどかと思います。
というわけで、本家ドキュメントにあるスキーマのサンプルコードが手元にあると便利ですよね?
これも、さきほどのinstaller.phpを利用してサンプル付きshema.ymlをコピーするようにします。
-
$this->logSection('install', 'add files for symfony beginners');
ファイルのコピー(インストール)はinstaller.phpを置いたディレクトリにあるmy_skeletonディレクトリから行われるように指定しています。
なので./my_skeleton/config/doctrine/schema.yml.sampleというファイルで以下のようなファイルを用意しておきます。
-
---
-
# http://www.doctrine-project.org/documentation/manual/1_2/en/yaml-schema-files
-
# simple
-
User:
-
columns:
-
username: string
-
password: string
-
contact_id: integer
-
-
Contact:
-
columns:
-
first_name: string
-
last_name: string
-
phone: string
-
email: string
-
address: string
-
-
# same above
-
User:
-
columns:
-
username:
-
type: string(255)
-
password:
-
type: string(255)
-
contact_id:
-
type: integer
-
relations:
-
Contact:
-
class: Contact
-
local: contact_id
-
foreign: id
-
foreignAlias: User
-
foreignType: one
-
type: one
-
.....(以下続く)
これで
/.symfony generate:project sample --installer=../help/installer/installer.php
を実行したときに、config/doctrineディレクトリにこのサンプルファイルもコピーされるので、あとはこのファイルを見ながらスキーマを作成すれば楽になります。
このように、自前installerを活用すれば
- プラグインのインストール方法を思い出す
- スキーマの書き方を思い出す
といった手間は多少なり軽減されます。
skeletonを利用する
日本語環境のための設定って何をするんだったっけ...
ということもよくあります。覚えてはいてもsettings.ymlに何かを書けばよかったんだけど...とかありますね。
そういった場合はskeletonの機能を利用します。これは、ひな形となるファイルを用意しておき、そのひな形ファイルでアプリケーションやモジュールの初期ファイルを生成する機能です。
generate:appのひな形ファイルを作る
まずは、help/skeleton/appのファイル一式をdata/skeleton/appにコピーします。
% mkdir data/skeleton
% cp -r ../help/skeleton/app ./data/skeleton/
ここでは標準のapp/config/settings.ymlに以下のコードを追加してあります。
-
# for Japanese
-
default_culture: ja
-
i18n: true
この状態でいつもと同じgenerate:appを実行するだけです。
%./symfony generate:app frontend
作成されたアプリケーションのsettings.ymlにはさきほどのひな形に追加したコードが含まれるようになります。
コンポーネントを使いたいけどどう書くんだっけ...
これもよくあります。symfonyの標準のひな形にはactions.class.phpは含まれていますが、components.class.phpは含まれていません。
自分でファイルを用意しなくてはなりません。ファイルを書いたもののスペルミスで動かなかったりして悩んだりという苦い経験もあります。。
アクションやテンプレートで利用できるメソッドや書き方を思い出せない...
アクションでリファラーを取得するにはどうすればよかったっけ。。。テンプレートでエスケープさせずに出力する方法ってどうだったっけ。。。
色々とすぐに思い出せないことは多いです。
IEDを使っていたり、慣れてくればそれほど困らないことかもしれませんが、サンプルコードがアクションやテンプレートに付いていたら便利だと思いませんか?
generate:moduleのひな形ファイルを作る
これらを解決する方法もさきほどのアプリケーション生成と同じです。
helpディレクトリからmoduleのskeletonをコピーしておきます。
% mkdir data/skeleton
% cp -r ../help/skeleton/module ./data/skeleton/
あとは何も考えずにいつもどおりに
%./symfony generate:app frontend test
と実行するだけです。
すると、新しいひな形でファイル群が生成されます。
.
|-- actions
| |-- actions.class.php
| |-- actions.class.sample.php
| `-- components.class.php
|-- config
| `-- security.yml
`-- templates
|-- _sample.php
`-- indexSuccess.php
見てすぐわかるように、components.class.phpが自動生成されています。
さらには、configディレクトリも生成し、何も定義していないsecurity.ymlファイルも作成しています。
また、actions.class.sample.phpと_sample.phpはダミーのファイルです。
これらのファイルに以下のようなサンプルコードが書かれています。
* actions.class.sample.php
-
private function __sampleCode()
-
{
-
// for debug
-
$this->logMessage($message, 'debug'); // emerg, alert, crit, err, warning, notice, info, and debug
-
-
// get Rouging object
-
$object = $this->getRoute()->getObject();
-
-
// with form
-
$this->form = new HogeForm($object);
-
$this->form->bind($request->getParameter('hoge'));
-
if ($this->form->isValid()) {
-
// code here
-
$name = $this->form->getValue('name');
-
}
-
$widget = $this->form['name']->getWidget();
-
-
// use Request Parameter
-
$name = $request->getParameter('name', 'default_value');
-
$all_parameters = $request->getParameterHolder()->getAll();
-
$condition = $request->isMethod('post'); // if request method is 'post', return true.
-
....(続く)
*_sample.php
-
//---------------------------------//
-
// HTML
-
//---------------------------------//
-
<?php decorate_with('newlayout')?>
-
-
<?php use_stylesheet('mystyle.css')?>
-
-
<?php use_stylesheet('myjs.css')?>
-
-
link tag
-
or
-
<a href="<?php echo url_for('@routing_name') ?>">click here</a>
-
open with a new window
-
-
image tag(web/images/title.gif)
-
or
-
<img src="<?php echo image_path('title.gif') ?>" />
-
...(続く)
これらを見ながらコードを書き進めていけば調べる量も減るかと思います。
このように、自前skeletonを活用すれば
- settings.ymlなどにいつも書く内容を思い出さなくてよい
- components.class.phpを標準で用意できる
- サンプルコード付きのファイルを見ながら開発できる
- $formの使い方を書いておける
といったメリットがあります。
generatorを利用する
フォームクラスの書き方がわかんない
慣れていても難しいのがsfFormです。その理由は多くのクラスやメソッドから構成されているので、調べないと使えないということにあります。
たとえば、テキストボックスをテキストエリアにしたい...なんてことも、widgetのクラスの指定を変えなければなりませんが覚えていないかぎり間違えてもおかしくありません。
ファーストロジックさんがsymfonyでのwidgetの書き方をまとめたテンプレートを紹介してくれています。そこで、このテンプレートが自動生成時に含まれていたら便利なのに...というわけでsymfonyのgenerator機能を使います。
myDoctrineFormGenerator
を用意する。
symfonyのdoctrine:buidl-formsタスクでは--generator-classというオプションを指定することができます。
ここでは、ただひな形として作成されるファイルにテンプレートコードを含ませたいだけなので、ジェネレータークラスで使用するテーマを自前のものに変更するだけで実現できます。
githubからダウンロードしたファイルからgeneratorディレクトリとmyDoctrineFormGenerator.class.phpファイルをコピーしておきます。
% cp -r ../help/generator ./data/
% cp -r ../help/lib/generator ./lib/
dataディレクトリは以下のようになっています。
data/generator
`-- sfDoctrineForm
`-- beginner
`-- template
|-- sfDoctrineFormBaseTemplate.php
|-- sfDoctrineFormGeneratedInheritanceTemplate.php
|-- sfDoctrineFormGeneratedTemplate.php
|-- sfDoctrineFormPluginTemplate.php
|-- sfDoctrineFormTemplate.php <= 変更してあるのはコレだけ
`-- sfDoctrinePluginFormTemplate.php
beginnerというのがテーマ名になります。また、テンプレートで標準ファイルから変更しているのはsfDoctrineFormTemplate.phpだけです。
また、myDoctrineFormGenerator.class.phpはもっと単純で以下の内容だけです。
-
<?php
-
class myDoctrineFormGenerator extends sfDoctrineFormGenerator
-
{
-
protected $theme = 'beginner';
-
}
もともとのジェネレーターを拡張し、themeだけを変更しています。
これで、--generator-classオプションを指定してコマンドを実行します。
%./symfony doctrine:build-forms --generator-class=myDoctrineFormGenerator
ここでテンプレートが埋め込まれるファイルは
./lib/form/doctrine/XXXForm.class.phpが対象となります。
これらのファイルは対象となるモデル名に対応するフォームクラスファイルが存在しない場合のみ生成されます。
なので、すでにdoctrine:build-formsを実行している場合は新しいモデル定義が無い限り既存ファイルへ変更は行われません。もし、既にフォームクラスファイルが存在する場合は
% mv lib/form/doctrine/XXXForm.class.php lib/form/doctrine/XXXForm.class.php.bkup
などのように名前を一時的に変更しておいて実行すると自前ジェネレータによって新しいフォームクラスファイルが作成されます。
これで、以下のようなフォームクラスが作成されます。
-
public function setup()
-
{
-
parent::setup();
-
// ここにwidgetの処理を記述します
-
-
// ここにvalidationの処理を記述します
-
// $v =new sfValidatorCallback(array('callback' => array($this, 'checkUniqueEmail')));
-
// $v->setMessage('invalid', '既に登録されているメールアドレスです。パスワードを忘れた場合はパスワードの再発行を行ってください');
-
}
-
// saveする前に処理をしたい場合
-
public function updateObject($values=null)
-
{
-
$object = parent::updateObject($values);
-
/*
-
$object->setName("name: " . $object->getName());
-
*/
-
return $object;
-
}
-
private function __samplecode()
-
{
-
-
// widgetの記述サンプル
-
// http://symfony-jp.com/f/viewtopic.php?f=8&t=5&sid=0f84afcb9d94ba53468c6add2c4851e5
-
//ドロップダウンリストここから
-
$key = "sfWidgetFormChoice(dropDown)";
-
$this->validatorSchema[$key] = new sfValidatorString();
-
$this->validatorSchema[$key] ->setOption('required', false);//入力必須ではない
-
// $this->validatorSchema[$key] ->setOption('required', true);//入力必須
-
// $this->validatorSchema[$key] ->setMessage('required', '入力必須です');
-
// $this->widgetSchema [$key] ->setHidden(true); // フォームをhiddenにする場合
-
//ドロップダウンリストここまで
-
-
-
//リストボックスここから
-
$key = "sfWidgetFormChoice(list)";
-
$this->widgetSchema [$key]->addOption('multiple', true);
-
$this->widgetSchema [$key]->setOption('choices', array('multipleを', 'Trueにすると', 'リスト', 'に', 'なる!', '・・・', 'よ'));
-
$this->validatorSchema[$key] = new sfValidatorString();
-
$this->validatorSchema[$key] ->setOption('required', false);//入力必須ではない
-
// $this->validatorSchema[$key] ->setOption('required', true);//入力必須
-
// $this->validatorSchema[$key] ->setMessage('required', '入力必須です');
-
// $this->widgetSchema [$key] ->setHidden(true); // フォームをhiddenにする場合
-
//リストボックスここまで
-
-
-
//ラジオボタンここから
-
$key = "sfWidgetFormChoice(radio)";
-
$this->widgetSchema [$key]->addOption('expanded', true);
-
$this->widgetSchema [$key]->setOption('choices', array('expandedを', 'Trueにすると', 'ラジオに', 'なる', 'よ!'));
-
-
...(続く)
このジェネレータは全フォームクラスに存在する必要はないと思いますので、どれか1フォームで仮に作成しておき、参照しながら作業すすめるのが便利かと思います。
このように、自前generatorを活用すれば
- sfFormで調べる時間がぐっと減る
- テーマを複数用意すれば使い分けできる
といったメリットがあります。
デメリット
これらのジェネレータにデメリットもあります。それは、コアのテンプレート側が何かの理由で更新されたときに自前側のファイルにも更新が必要になる場合があるということです。
ただし、symfony1.4系はもう大きな改修は入らないでしょうし、Symfony2ではこのまま使えることはまず無いと思われるので割り切って使えるのではないでしょうか。
まとめ
かなりの長文になってしまいましたが、これらの機能を使い自分自身、会社共通の便利なスケルトン、ジェネレーターを作成し共有すれば、楽して開発ができるようになると思います。
関連するその他の記事
Comments
Leave a Reply