|
whats_new_sf12
symfony 1.2では何が新しくなったの? このチュートリアルは手っ取り早くsymfony1.2のための技術的な紹介です。 すでにsymfony 1.0や1.1で作業をしたことがあり、symfony1.2の新しい機能について学びたい開発者のためのチュートリアルです。 最初に、symfony 1.1がPHP 5.1、symfony 1.0がPHP 5.0で動作していたのに対してsymfony1.2はPHP5.2.4かそれ以降に対応している事に注意してください。 もし、symfony 1.0 か 1.1からアップグレードしたいのであれば、symfonyをインストールしたディレクトリにあるUPGRADEファイル(http://www.symfony-project.org/installation/1_2/upgrade) ファイルを読んでください。 ここにsymfony 1.2 にプロジェクトを安全にアップグレードするために必要とされる情報のすべてがあります。 PropelPropelはバージョン1.3にアップグレードされました。このバージョンではCreoleに代わりPDOがサポートされいたり、 多くの新しい機能が含まれています。新しい機能とはオブジェクトインスタンスプーリング、マスタースレーブコネクション、 入れ子集合のサポート、そしてより良い日付関連のハンドリングなどです。 databases.yml設定ファイルはPDO構文を使うようになりました。 [yml]
dev:
propel:
param:
classname: DebugPDO
all:
propel:
class: sfPropelDatabase
param:
dsn: mysql:dbname=example;host=localhost
username: username
password: password
encoding: utf8
persistent: true
pooling: true
classname: PropelPDOトランザクションapiはわずかに変更が行われます。それは ->begin は ->beginTransaction()に、そして ->rollback()は->rollBack()に変更されることです。以下がその違いです。 ::doSelectRSメソッドは ::doSelectStmtに変更されました。 更なるアップグレードの詳細についてはhttp://propel.phpdb.org/trac/wiki/Users/Documentation/1.3/Upgradingを、 完全なドキュメントについてはhttp://propel.phpdb.org/trac/wiki/Users/Documentation/1.3を見てくさい DoctrineDoctrineはsymfony 1.2 では第1級の市民です。 symfony 1.2 では Propelプラグインと Doctrineプラグインの両方をバンドルしているということです。 全ての組み込まれた機能はPropelとDoctrineの両方で利用できます。 あなたにより適したORマッパーを自由に選択してください。 リクエスト(Request)ブラウザからの PUT と DELETE リクエストを POST メソッドと特別な sf_method パラメータを追加することで シミュレーションが可能になりました。 [php]
<form action="#" method="POST">
<input type="hidden" name="sf_method" value="PUT" />
<!-- // ... -->
</form>form_tag() ヘルパーは GET と POST と異なるメソッドのために自動的にhiddenタグを生成します。 そのため、formの開始タグは次のように form_tag() ヘルパーを使うことで生成できます。 [php]
<?php echo form_tag('#', array('method' => 'PUT')) ?>フォーム(Forms)### フォームの入れ子 symfony1.1ではPropelでのフォームの主な制限の1つとして組み込まれたフォームからオブジェクトを自動保存することができないことでした。 symfony1.2では実装されるようになりました。これはPropelのフォームを保存するとき、symfonyによって自動的に主となるオブジェクトと 関連する入れ子になったフォームの全てをオブジェクトを保存してくれるということです。 ### 新しい sfForm メソッド 新しい sfForm::renderFormTag() メソッドは form開始タグを現在のフォームのために生成します。 また、フォームがマルチパートを必要とする場合は enctype 属性も追加しますし、 メソッドが GETまたはPOST以外の場合はhiddenタグを追加します。 [php]
<?php echo $form->renderFormTag('@article_update', array('method' => 'PUT')) ?>sfFormPropel クラスは 関連するオブジェクトに基づくHTTPメソッドを自動的に変更するために renderFormTag()を上書きします。つまり、オブジェクトが新しければ、メソッドはPOSTであり オブジェクトが既に存在すればメソッドはPUTになるでしょう。 sfForm クラスはformにエラーがあればfalseを返し、 そうでなければtrueを返す新しい hasErrors() メソッドを返します。 このメソッドはフォームに値が結びつけられていない場合は false を返します。 このメソッドはテンプレートでとても役に立ちます。 [php]
<?php if ($form->hasErrors()): ?>
The form has some errors you need to fix.
<?php endif; ?>新しい renderUsing メソッドが sfForm クラスに追加されました。このメソッドによって レンダー処理されるフォームが特定のwidgetスキーマのフォーマッターを使うことを許可します。 これによってテンプレートにおいて直接フォーマッターを使うことができるようになります。 [php]
// in a template, the form will be rendered using the "list" form formatter
echo $form->renderUsing('list');sfForm::renderHiddenFields()メソッドはhiddenウィジットのためのHTMLを返します。 フォームのフィールドをテンプレート内で見えないようにしたいときに役に立ちます。 [php]
<form action="<?php echo url_for('@some_route') ?>">
<?php echo $form->renderHiddenFields() ?>
<ul>
<?php echo $form['name']->renderRow() ?>
</ul>
<input type="submit" />
</form>n フォームは getStyleSchees()とgetJavaScripts()メソッドという フォームを表示するときに必要となるスタイルシートとJavascriptのファイルを返すメソッドを持つようになりました。 この2つのメソッド上書きすることで、またはより一般的に各ウィジットを使うことで これらのファイルをフォーム自身のなかに定義しておくことができます。 (詳しくはWidgetの項目を確認してください) テンプレート中ではinclude_javascripts_for_form()とinclude_stylesheets_for_form()ヘルパーを利用できます。 これら両方とも引数としてフォームオブジェクトを渡します。 [php]
<?php include_javascripts_for_form($form) ?>
<?php include_stylesheets_for_form($form) ?>sfFormはより簡単にテンプレート内でフォームのフィールドを繰り返しやすくできるようにIteratorとCountableインターフェースを実装しています。 [php]
<ul>
<?php foreach ($form as $field): ?>
<li><?php echo $field ?></li>
<?php endforeach; ?>
</ul>### 前処理で値をクリーンアップ オブジェクトを更新して、Propelによって値が利用される前に値をクリーニングできる前処理の方法が追加されました。 もし値のための前処理を行いたいのであれば、updateXXXColumn() メソッドを XXXがPropelカラムのPHP名である部分の formに追加する必要があります。 このメソッドは 処理された値かクリーンアップされた値の配列から値を取り除くために false を返さなければなりません。 [php]
class UserForm extends sfFormPropel
{
// ...
protected function updateProfilePhotoColumn($value)
{
// if the user has not submitted a profile_photo,
// remove the value from the values as we want
// to keep the old one
if (!$value)
{
return false;
}
// remove the old photo
// save the photo on the disk
// change the value to the new file name
return $filename;
}
}バリデーター(Validators)### sfValidatorSchemaCompare sfValidatorSchemaCompare定数は変更されました。コードに変更は必要ありません。しかしこれからは、 すばらしいショートカットを使う事ができます。 次の2つの例が実装例です。 [php]
// symfony 1.1 と 1.2での記述方法
$v = new sfValidatorSchemaCompare('left', sfValidatorSchemaCompare::EQUAL, 'right');
// symfony 1.2 での記述方法
$v = new sfValidatorSchemaCompare('left', '==', 'right');### sfValidatorChoice sfValidatorChoiceは sfValidatorChoiceManyにある multiple オプションと同じ振るまいをするために multipleオプションを持つよようになりました。 sfValidatorPropelChoiceは sfValidatorPropelChoiceManyにある multiple オプションと同じ振るまいをするために multipleオプションを持つよようになりました。 ### sfValidatorDateRange symfony 1.2は日付の期間を検証するための新しいsfValidatorDateRangeバリデータを備えています。 ### sfValidatorFile sfValidatedFileクラスはファイルを保存するときに少しばかり柔軟になりました。 このコンストラクターは新しい引数をとることができ、ファイルを保存するときに利用するパスを渡すことができます。 それで、ファイルを保存するとき、次のようにすることができます。
[php]
$file->save(sfConfig::get('sf_uploads_dir').'/filename.pdf');
[php]
$file->save('filename.pdf');
[php]
$file->save();さらに、 save() メソッドは(引数のパスに相対的な)保存されたファイルのファイル名を返すようになりました。 sfValidatedFileオブジェクトは sfValidatorFile バリデーターによって生成されるので、 新しいpathオプションは後者のクラスに追加され sfValidatedFileコンストラクターにただ渡されるだけです。 [php]
$this->validatorSchema['file'] = new sfValidatorFile(array('path' => sfConfig::get('sf_uploads_dir')));sfFormPropelはこれらの新しい改良部分をPropelオブジェクトに関連するファイルの保存を自動化することで活用することができます。 それが新しいsaveUploadedFile()メソッドです。 そのため、もしfileカラムを持つPropelオブジェクトがあり、フォームクラスでfileバリデーターを定義するときパスを渡しているなら symfonyはあなたの代わりに全ての処理を行ってくれます。
それで、関連するアクションにおいて、ただ$this->form->save()とするだけで自動的にオブジェクトを保存しファイルを保存します。 標準では、symfonyはハッシュと推測した拡張子を追加してユニークなファイル名を生成します。 もしファイル名を変更したいならgenerateXXXFilename() メソッドをオブジェクト内に作成するだけです。 このメソッドはsfValidatedFileオブジェクトに与えられています。 [php]
public function generateFileFilename(sfValidatedFile $file)
{
return $this->getId().$file->getExtension($file->getOriginalExtension());
}もちろん さきほど説明したようにupdateXXXColumn()をこの振る舞いを上書きするために作成し、 あなた自身でファイルのアップロードの処理をマージする事も可能です。 ### sfValidatorI18nChoiceCountry と sfValidatorI18nChoiceLanguage symfony1.1ではsfValidatorI18nChoiceCountryとsfValidatorI18nChoiceLanguageバリデーターは cultureオプションが必須でした。このcultureはこれらのバリデーターで使われていないので、 cultureオプションは廃止される予定です。後方互換性のためにまだ残っていますが、もう使う必要はありません。 ### メッセージに関連するrequiredとinvalidの標準のエラーコードの設定 2つの新しいメソッドがsfValidatorBaseクラスに追加され、標準時のrequiredとinvalideエラーコードのための メッセージを定義できるようになりました。 [php]
sfValidatorBase::setRequiredMessage('This field is required');
sfValidatorBase::setInvalidMessage('The value provided for this field is invalid');ウィジット(Widgets)### Widget オプション 全てのwidgetsは新しいdefaultオプションを持っています。このオプションはwidgetの 標準の値をセットします。 [php]
$widget = new sfWidgetFormInput(array('default' => 'default value'));
$widget->setDefault('default value');
echo $widget->getDefault();widgetスキーマに標準の値をセットすることもできるようになりました。 [php]
$widget = new sfWidgetFormSchema(...);
$widget->setDefaults(array('name' => 'default value'));
$widget->setDefault('name', 'default value');
var_export($widget->getDefaults());フォームの標準値で上書きしないときこれらの標準に設定した値はそのことを考慮します すべてのwidgetは新しいlabelオプションを持っています。このオプションは 各widgetにラベルを設定します。 [php]
$widget = new sfWidgetFormInput(array('label' => 'Enter your name here'));
$widget->setLabel('Enter your name here');
echo $widget->getLabel();### Widgets JavaScripts と stylesheets WidgetはgetJavascripts()とgetStyleSheets()メソッドで描画される必要がある JavaScriptとスタイルシートを宣言することができます。 [php]
class MyWidget extends sfWidgetForm
{
public function getJavaScripts()
{
return array('/path/to/a/file.js');
}
public function getStylesheets()
{
return array('/path/to/a/file.css' => 'all', '/path/to/a/file.css' => 'screen,print');
}
}getJavaScripts()メソッドはJavaScriptファイルの配列を返さなければなりません。 getStylesheets()メソッドはファイル名をキーとし、メディアを値とする配列を返さなければなりません。 ### New widgets symfony 1.2 は新しいwidgetが備わっています。
### sfWidgetFormChoice family 新しいchoice widgetファミリーも追加されました。
標準で、これらのwidgetsはそれらのSelectの複製です。しかし、それらは sfWidgetFormSelect、sfWidgetFormSelect、sfWidgetFormSelectRadio そしてsfWidgetFormSelectCheckBoxウィジットの上部にあるラッパーです。 レンダリングのためにこれらの1つを使用します。標準のウィジットを変更するためにはいくつかのオプションを利用できます。
これはレンダー処理されるwidgetに渡したいオプションです。 オプションを利用したサンプルです。 [php]
$widget = new sfWidgetFormPropelSelect(array('model' => 'Article'));
// is equivalent to
$widget = new sfWidgetFormPropelChoice(array('model' => 'Article'));
// change the rendering to use a radio list
$widget->setOption('expanded', true);
// create a multiple select
$widget = new sfWidgetFormPropelChoiceMany(array('model' => 'Article'));
// change the rendering to use a checkbox list
$widget->setOption('expanded', true);フォームを生成されたPropelのためにこれらの新しいwidgetsは標準で利用できます。 レスポンス(Response)### sfWebResponse::getCharset() getCharset()はレンスポンスの現在の文字コードを返します。 コンテントタイプの設定を変更することでこの文字コードは自動的に更新されます。 ### sfWebResponse::getStylesheets() と sfWebResponse::getJavascripts() もしsfWebResponse::ALLを最初の引数として渡せば getStyleSheets()とgetJavascripts()メソッドは現在は全てのスタイルシートとJavaScriptをポジションで指定された順番で返します。 [php]
$response = new sfWebResponse(new sfEventDispatcher());
$response->addStylesheet('foo.css');
$response->addStylesheet('bar.css', 'first');
var_export($response->getStylesheets());
// outputs
array(
'bar.css' => array(),
'foo.css' => array(),
)sfWebResponse::ALLはポジションの引数のための標準の値でもあります。 Prototype と Scriptaculoussymfony1.2においてバンドルされていたPrototypeと Scriptaculousライブラリとヘルパー(JavascriptHelper)はコアプラグインに移動しました。 コアプラグインは本物のプラグインのように振る舞いますが、symfonyプラットフォームによって操作されます。 (コア)プラグインなので、新しいsfProtoculousPlugin(PrototypeとScriptaculousの組み合わせの名前で非公式でよく使われる)のJavaScriptとCSSファイルが作成され、これらは本当のプラグインアセットとして振る舞います。 それらは (1.0や1.1のときに配置されていた)web/sfディレクトリではなくweb/sfProtoculousPluginディレクトリに配置されることになります。 prototype_web_dir設定はその新しいディレクトリ(web/sfProtoculousPlugin)を指し示すようにもなります。 さらに、色々なJSフレームワークによって利用される基本的なJavascriptヘルパーがコア部分にJavascriptBaseHelperとして抽出されます。 新しい追加機能として、javascript_tag()はslot()のように動作するようになります。次のような使い方ができます。 [php]
<?php javascript_tag() ?>
alert('All is good')
<?php end_javascript_tag() ?>テスト(Tests)### sfBrowser::info() 多くの機能テストをモジュールのためにかくとき、何が行われているかについて視覚的な情報が役に立つ事があります。 symfony 1.2では info()メソッドがあなたのテストをカテゴライズするのに役立つテキストを出力します。 [php]
$browser->
info('First scenario')->
// ... some tests
info('Second scenario')->
// ... some more tests
;### デバッキングテスト 機能テストで問題が発生するとき、ブラウザーに送信された情報は原因を診断するために役に立ちます。 symfony 1.2では流暢なインターフェーススタイルを邪魔することなく生成されたHTMLを表示することができます。 [php]
$browser->
get('/a_uri_with_an_error')->
with('response')->debug()->
// some tests that won't be executed
;debug()メソッドはレスポンスヘッダとコンテンツを出力し、ブラウザのフローを遮ります。 ### テスター sfTestFunctionalBaseクラスは実際のテストをsfTesterクラスに委任するようになりました。 symfony 1.2はいくつかの組み込みテスタークラスがあります。
全ての古いテストブラウザのメソッドはテスタークラスのメソッドに移動されました。 class:
テスタークラスも新しいメソッドが用意されました。
以下が新しいテスターの使い方です。 [php]
$browser->
get('/')->
with('request')->isParameter('module', 'foo')->
with('request')->isParameter('module', 'bar')
;with()メソッドを呼び出すことで呼び出し可能なメソッドにあるテスターオブジェクトを返します。 もし、複数のメソッドをテスターオブジェクトで呼び出したいなら、それらをblock内におくことができます。 [php]
$browser->
get('/')->
with('request')->begin()->
isParameter('module', 'foo')->
isParameter('module', 'bar')->
isMethod('get')->
isFormat('html')->
end()->
with('response')->begin()->
isStatusCode(200)->
checkElement('body', 'foo')->
isHeader('Content-Type', 'text/html; charset: UTF-8')->
isRedirected(false)->
end()
;sfTesterから継承されたクラスを作成し登録することによって独自のテスターを追加することができます。 [php]
$browser->setTester('my_tester', 'myTesterClassName');既存のテスタークラスも標準のクラス名を上書きすることで拡張することができます。 [php]
$browser->setTester('request', 'myTesterRequest');formがあるページのテストを改善するために、select()とdeselect()メソッドをテストブラウザに追加しました。 現在はチェックボックスの選択/非選択とラジオボタンの選択処理をサポートしており、これは同じnameのラジオボタンが非選択になる原因かもしれません。 [php]
$browser->
select('aRadioId')->
select('aCheckboxId')->
deselect('anotherCheckbox');### Cookies クッキーは sfBrowserやsfTestBrowserクラスにおいてもサポートされるようになります。 クッキーを sfBrowserクラスにあるsetCookie()、removeCokie()そしてclearCookies()メソッド間で扱うことができます。 [php]
$b->
setCookie('foo', 'bar')->
removeCookie('bar')->
get('/')->
// ...
clearCookies()->
get('/')->
// ...また、sfTesterRequestクラスからhasCookie()とisCookie()メソッドでクッキーをテストすることができます。 [php]
$b->
get('/')->
with('request')->begin()->
hasCookie('foo')->
hasCookie('foobar', false)->
isCookie('foo', 'bar')->
isCookie('foo', '/a/')->
isCookie('foo', '/!z/')->
end()
;hasCookie()メソッドは第2引数でクッキーがセットされてない状態をテストするための真偽値をとります。 isCookie()メソッドの第2引数はcheckElementResponseメソッドの第2引数のような振る舞いをします。 それは文字列、正規表現もしくは否定正規表現だったりします。 ブラウザークラスは自動的に各クッキーにexpire値ごとにクッキーを消します。 ### リクエスト(Request) リクエストテスターからisMethod()メソッドを使ってあなたの機能的なテストでの リクエストで使用されているHTTPメソッドをテストすることもできます。 [php]
$b->
setField('login', 'johndoe')->
click('Submit')->
with('request')->isMethod('post');### リンク(Links) リンクになっているクリックやボタンをシミュレーションするとき、click()メソッドという名前を使います。 しかし、同じ名前で2つの異なるリンクやボタンを差別化するほうほうがありません。 symfony 1.2 では click()メソッドではオプションを第3引数に渡します。 positionというオプションをクリッックしたいしたいリンクを変更するときに渡します。 [php]
$b->
click('/', array(), array('position' => 1))->
// ...
;標準で、symfonyはページにある項目の最初のリンクをクリックします。 methodオプションでクリックしたいリンクやフォームのメソッドを変更することができます。 [php]
$b->
click('/delete', array(), array('method' => 'delete'))->
// ...
;これはリンクがJavascriptで動的に生成されるフォームで変換される場合に役立ちます。 ### フォーム(Forms) 新しいフォームフレームワークを使うなら、サブミットされたフォームから生成されたエラーをテストすることができるようになりました。 [php]
$browser->
click('save', array(...))->
with('form')->begin()->
hasErrors()->
isError('name', 'Required.')->
isError('name', '/Required/')->
isError('name', '!/Invalid/')->
isError('name')->
isError('name', 1)->
end()
;また、debug()メソッドでフォームをデバッグすることもできます。 [php]
$browser->
click('save', array(...))->
with('form')->debug()->
// some tests that won't be executed
;もしエラーがあればサブミットされた値と全てのエラーを出力します。 ### Propel Propelプラグインにはpropelテスターが附属しています。このテスターは標準では登録されていません。 [php]
$browser->setTester('propel', 'sfTesterPropel');このテスターはPropelモデルをテストするためのcheck()メソッドを提供します。 [php]
$browser->
post('...', array(...))->
with('propel')->begin()->
check('Article', array(), 3)->
check('Article', array('title' => 'new title'))->
check('Article', array('title' => 'new title'))->
check('Article', array('title' => 'new%'))->
check('Article', array('title' => '!new%'), 2)->
check('Article', array('title' => 'title'), false)->
check('Article', array('title' => '!title'))->
end()
;モデル名を最初の引数としてとり、第2引数としてCriteriaオブジェクトか条件の配列をとります。 そして第3引数は次のどれかでなければなりません。
### カバレッジ(Coverage) 実行したテストのコードカバレッジを出力するための新しいtest:coverageタスクが用意されました。 [php]
$ ./symfony test:coverage test/unit/model/ArticleTest.php lib/model/Article.php最初の引数はファイルかテストのディレクトリです。第2引数はあなたがカバーしたいファイルかディレクトリになります。 もし、どの行がカバーされていないかを知りたいなら、次のように--detailedオプションを追加するだけです。 [php]
./symfony test:coverage --detailed test/unit/model/ArticleTest.php lib/model/Article.phpロガー(Loggers)symfony 1.2 は新しいロガーを組み込むことになりました。それがsfVarLoggerです。 このロガークラスは後で利用するために全てのメッセージを配列でロギングします。 ログをとって、それらを次のように使うことができるようになります。 [php]
$log = new sfVarLogger();
$log->log('foo');
var_export($log->getLogs());
// outputs
array(
0 => array(
'priority' => 6,
'priority_name' => 'info',
'time' => 1219385295,
'message' => 'foo',
'type' => 'sfOther',
'debug_stack' => array()
)
)各ログはpriority、priority_name、time、message、typeそしてdebug_stackというキーを持つ 連想配列です。 debug_stack属性はxdebug_loggingオプションがtrueにセットされているときだけセットされます。 オプションがセットされているときはxdebugのスタックトレースを配列をして保持しています。 sfVarLoggerはまたsfWebDebugLoggerクラスのための基礎クラスでもあります。 そのため、sfWebDebugLoggerのxdebugLoggingオプションはxdebug_loggingに名前が変更されました。 Web Debug Toolbarウェブデバッグツールバーはカスタマイズができるようになりました。ツールバーはパネルで構成されています。 パネルはsfWebDebugPanelを拡張したオブジェクトであり、ツールバー上に表示するために必要とされる情報を 提供してくれます。 標準では、次のようなパネルが自動的に登録されています。
ウェブデバッグツールバーをdebug.web.load_panelsイベントに聞く事でカスタマイズできます。 このリスナーで追加された新しいパネルを追加したとき、既に存在するパネルを削除したときや 別のものに置き換えることができます。 sfWebDebugPanelLogsパネルはdebug.web.filter_logsイベントを通知することで表示されるログをフィルター処理します。 たとえば、sfWebDebugPanelPropelとsfWebDebugPanelTimerは全てのPropelに関連するログやログパネルから タイマーログを取り除くためにこのイベントに接続します。 ウェブデバッグツールバーに表示される全体の時間は$_SERVER['REQUEST_TIME'](以前はsfConfig::get('sf_time_start') で計算していましたが、もやはこれは存在しません)で計算しています。 表示される時間はsymfony1.0や1.1よりもより長くなっていることを意味します。 タスク(Tasks)取り込まれているPhingタスクが失敗するなら、Phingに依存しているPropelタスクははっきりとした エラーメッセージを出力します。 CLIタスクの中にはアプリケーション名を引数として必要としているものがあります。なぜなら それらはデータベースに接続する必要があるからです。アプリケーション上でカスタマイズされる設定ファイルが必要なため 私たちはアプリケーションが必要なのです。そして全てのsymfonyの設定システムはアプリケーションレベルが基礎となっています。 これらのタスクにとって、引数はオプションである"application"オプションになって取り除かれました。 もし、"application"オプションを提供しないならsymfonyはプロジェクトのdatabases.ymlファイルから データベース設定を取得してくるようになりました。 次のタスクの用法はこれらに従って変更されました。
>ノート >これはsfDatabaseManagerが今ではプロジェクト設定やアプリケーション設定を取得するようになったので可能になりました。 興味深いこととで、sfDatabaseConfigHandlerは今では静的か動的な設定ファイルの配列に基づく設定を返すから動作するのです。 (exeute()かevaluate()を見てください) デバッグのために、propel;build-model, propel:build-allそして propel:build-all-loadタスクは --traceオプションを指定すれば生成されるスキーマを取り除きません。 propel:insert-sqlタスクは全てのデータをデータベースから取り除きます。 情報を破壊するので、タスクの実行前にユーザーに訪ねるようになりました。 同じことがpropel:build-allとpropel:build-all-loadタスクにもあてはまります。 もし、これらのタスクをバッチ処理で使いたいなら確認のための質問を避けたいでしょう。そのときは no-confirmationオプションを渡してください。 $ php symfony propel:insert-sql --no-confirmation symfony 1.2より前では、propel:insert-sqlタスクはpropel.iniからのデータベースの情報を読み取ることしかしませんでした。 symfony 1.2ではdatabases.ymlから読みとるようになりました。そのため、モデルに複数の異なる接続先を設定したいなら このタスクはそれらを考慮するようになりました。 この新しい機能のおかげで、 もし指定した接続先からのSQLだけを読み込みたい場合に --connection オプションを使う事ができるようになりました。 $ php symfony propel:insert-sql --connection=propel また--envと--applicationオプションも次のように特定の設定を選択するために使う事ができます。 $ php symfony propel:insert-sql --env=prod --application=frontend ### タスクのために利用可能な新しいメソッド sfTask基底クラスはタスクで利用できる3つの新しいメソッドを提供するようになりました。
### propel:generate-module propel:generate-crutはpropel:generate-moduleに名前が変更されました。 古いタスク名はエイリアスとしてまだ利用することができます。 propel:generate-moduleタスクのnon-atomic-actionsオプションは取り除かれ次のような新しいオプションが追加されました。
### propel:generate-module-for-route 新しいpropel:generate-module-for-routeタスクはルーティングの定義に基づいたモジュールを作成します。 [php]
php symfony propel:generate-module-for-route frontend articles### app:routes いまではsymfonyは(以下のような)ルーティングを自動生成でき、app:routesタスクは 現在のアプリケーションに設定されているルーティングのリストを表示します。 [php]
php symfony app:routes frontendもしルーティングについて詳しく知りたいなら、次のようにルート名を追加するだけです。 [php]
php symfony app:routes frontend articles_update### plugin:install-assets 通常プラグインはタスクでインストールされるとき正しくコアプラグインが必要とするように webディレクトリにシンボリックリンクが作成されます。 これと同じことを手動で行うためには以下のようにします `symfony plugin:publish-assets --only-core` 目標はプロジェクトの生成とアップグレードタスクがあなたに代わってこれを行うことです。 ルーティング(Routing)### Routing オプション ルーティングタスクは2つのオプションをとります。
標準では、symfony 1.0, 1.1と互換性を保つためにfactories.ymlにおいてfalseがセットされています。 ルーティングの基礎部分でこれらのオプションの有効無効を設定することもできます。 [yml]
articles:
url: /articles/:page
param: { module: article, action: list, page: 1 }
options: { generate_shortest_url: true }できるだけ最も短いURLを生成しようとするので、もし、1のpageの値を渡すなら、 生成されるURLは/articlesになるでしょう [php]
echo url_for('@articles?page=1');
// /articles
// would have been /articles/1 in symfony 1.1
echo url_for('@articles?page=2');
// /articles/2extra_parameters_as_query_stringの例は以下のようになります。 [yml]
articles:
url: /articles
options: { extra_parameters_as_query_string: true }ルーティングは外部パラメータを受け取り、クエリストリングとしてそれらを追加します。 [php]
echo url_for('@articles?page=1');
// /articles?page=1
// would not have matched the route in symfony 1.1
echo url_for('@articles?page=2');
// /articles?page=2### sfRoute sfPatternRoutingクラスはフラットな連想配列の代わりにsfRouteオブジェクトの配列で ルーティングをためています。 標準では、symfonyは組み込みのsfRouteオブジェクトを使います。しかし次のように特定のclassエンティティを routing.yml設定ファイルで変更することができます。 yml foo_bar:url: /foo/:bar class: myRoute param: { module: foo, action: bar } 全てのルーティングのロジックはsfRouteクラスに含まれています。これは解析と あなた自身で生成ロジックを上書きすることができるということです。 >TIP >より簡単に標準の挙動をカスタマイズできるようにsfRouteクラスは古いsfPatternRougintクラスよりさらにモジュール化されました。 >"compilation"フェーズはより小さなメソッドにリファクタリングされ、コードはよりシンプルになり、"本当の"トークナイザーに基づいています。 PHPコードであなたのルーティングに接続するなら、sfRouteインスタンスをconnect()、preprendRoute() 、appendRoute()そしてinsertRouteBefore()メソッドの第2引数として渡さなければなりません。 [php]
$route = new myRoute('/foo/:bar', array('module' => 'foo', 'action' => 'bar'));
$routing->connect('foo_bar', $route);リクエストがあったばあい、一致しているルーティングオブジェクトはリクエストの属性として保存され、 getRoute()メソッドを通してアクションから取得することができます。 [php]
public function executeIndex()
{
$route = $this->getRoute();
}sfRouteコンストラクターは各ルーティングをカスタマイズできるようにその最後の引数としてオプションの配列をとります。 routing.yml設定ファイルで、optionsキーを次のようにつかいます。 [yml]
article:
url: /article/:id-:slug
options: { segment_separators: [/, ., -] }### sfRequestRoute symfonyは別の組み込みルーティングである sfRequestRouteを持っており、これによって HTTPメソッドをあなたのルーティングに強制することができます。 yml article:url: /article/:id requirements: { sf_method: get } class: sfRequestRoute もし、sf_methodを必要とせず指定しなkれば、symfonyはgetかheadリクエストを強制します。 sfRoutingのparse()メソッドが第2引数としてコンテキストをとるため可能になっています。 リクエストがルーティングを呼び出すとき、次のようなコンテキストを渡します。
前述のルーティング設定で、articleへのルーティングはHTTPメソッドがgetの場合のみ一致します。 同じurlを異なるメソッドを必要とするようにルーティングを設定するなら、次のようにルーティングを生成するとき sf_methodパラメータを渡すことができます。 [php]
<?php echo link_to('Great article', '@article?id=1&sf_method=get')) ?>### sfObjectRoute symfony 1.2 はsfRequestRouteを拡張した別のルーティングクラスである sfObjectRouteを実装しています。 sfObjectRouteはPHPオブジェクトにルーティングを結びつけています。 sfObjectRouteはオブジェクトやオブジェクトの集まりやルーティングに関連するコレクションを 取得するためのPHPのクラスにメソッドを呼び出せるようにしたりします。 [yml]
article:
url: /article/:id
class: sfObjectRoute
options: { model: Article, type: object, method: getById }URLがルーティングに一致するとき、sfObjectRoute::getObject()メソッドで、 Article::getById()メソッドによって呼ばれる関連するオブジェクトを取得することができます。 同じことがオブジェクトの集まりにも当てはまります。 [yml]
articles:
url: /articles/newest
class: sfObjectRoute
options: { model: Article, type: list, method: getNewest }### sfPropelRoute sfPropelRouteはsfObjectRouteをPropelのモデルへのルーティングへ結びつけるために拡張します。 アクションにおいて、sfObjectRoute::getObject()やsfObjectRoute::getObjects()メソッドを利用することで関連するオブジェクトやオブジェクトの集まりを 取得することができます。 [php]
public function executeList($request)
{
$this->articles = $this->getRoute()->getObjects();
}
public function executeShow($request)
{
$this->article = $this->getRoute()->getObject();
}ここにArticlePropelオブジェクトのための例があります。 [yml]
article:
url: /article/:id
param: { module: article, action: show }
class: sfPropelRoute
options: { model: Article, type: object }
articles:
url: /articles
param: { module: article, action: list }
class: sfPropelRoute
options: { model: Article, type: list, method: getPublishedArticleCriteria }メソッドを定義していないなら、sfPropelRouteは利用できるルーティングの変数に基づいてCriteriaオブジェクトを構築することで オブジェクトを取得します。 sfPropelRouteはsfRoute以上の2つの主な利点があります。
アクションにて利用することができ、関連するArticleオブジェクトはgetObject()メソッドを呼ぶ事で 利用することができます。 さらに、オブジェクトがデータベースに存在しないなら、自動的に404エラーページにリダイレクトします。 これはアクションでの決まりきった指示を減らすことができるということです。
次のようにArticleオブジェクトに直接引数を渡すことができます。 [php]
<?php echo url_for('article', $article) ?>その他のパラメータを渡すなら(例えばHTTPメソッドを強制したいような場合)、次のように配列を使うことができます。 [php]
<?php echo url_for('article', array('sf_subject' => $article, 'sf_method' => 'get')) ?>もちろん、次のように完全なパラメータもまだ利用することができます。 [php]
<?php echo url_for('article', array('id' => $article->getId(), 'slug' => $article->getSlug())) ?>もしくは次のように内部URLを使うこともできます。 [php]
<?php echo url_for('@article?id='.$article->getId().'&slug='.$article->getSlug()) ?>sfPropelRouteはArticleオブジェクトを自動的にパラメータの配列に変換します。 sfPropelRouteはプライマリキーだけでは動作しません。色々なカラムを用いて動作させることができます。 次の例では、slugカラムをルーティングパターンに追加することができます。 [yml]
article:
url: /article/:id/:slug
param: { module: article, action: show }
class: sfPropelRoute
options: { model: Article, type: object }しかし時には、データベースに存在しない情報をパターンに含めたい場合もあるでしょう。 このような場合、methodオプションに渡すことができます。 [yml]
post:
url: /post/:id/:year/:month/:day/:slug
param: { module: article, action: show }
class: sfPropelRoute
options: { model: Article, type: object, method: getObjectForRoute }getObjectForRoute()は最初の引数としてパラメータの配列を受け取りArticleオブジェクトを返さなければなりません。 [php]
class ArticlePeer extends BaseArticlePeer
{
static public function getObjectForRoute($parameters)
{
$criteria = new Criteria();
$criteria->add(self::ID, $parameters['id']);
return self::doSelectOne($criteria);
}
}sfPropelRouteはパラメータを解析されたルートを上書きするためのsetListCriteria()メソッドも提供します。 ルーティングによって返されるオブジェクトを洗練したいときに特に役立ちます。 たとえば、他のパラメータに基づくような次のような検索などです。 [php]
public function executeList($request)
{
$this->filters = new ArticleFormFilter();
if ($request->isMethod('post'))
{
$this->filters->bind($request->getParameter('article_filters'));
if ($this->filters->isValid())
{
$this->getRoute()->setListCriteria($this->filters->getCriteria());
}
}
$this->articles = $this->getRoute()->getObjects();
} ### sfRouteCollection, sfObjectRouteCollection, and sfPropelRouteCollection symfonyは"collection"ルートクラスも実装しています。 これらのクラスsfRouteCollection, sfObjectRouteCollection, sfPropelRouteCollection)は定義に基づいた標準的なルーティングを作成します。 [yml]
articles:
class: sfPropelRouteCollection
options: { model: Article, module: article }標準では、このルーティングは以下の7つのルーティングを生成します。
複数のオプションで生成されるルーティングをカスタマイズすることができます。
(標準では sfObjectRouteのためにはsfObjectRouteCollection sfPropelRouteCollectionのためにはsfPropelRouteを利用) ここにオプションを指定した場合の別の例があります。 [yml]
articles:
class: sfPropelRouteCollection
options:
model: Article
module: article
prefix_path: /foo
methods: [ list, edit, update ]
segment_names: { list: nouveau, edit: edition }
collection_actions: { filter: post }
object_actions: { publish: put }URLヘルパー(URL helpers)### link_to() and url_for() もし、POST, PUTまたはDELETEHTTPメソッドでサブミットされなければならない リソースへのリンクを作成したいとき、link_to()ヘルパーでmethodオプションを渡すことで リンクをフォームに変換することができます。 [php]
<?php echo link_to('@article_delete?id=1', array('method' => 'delete')) ?>古いpostオプションはまだ有効ですが廃止される予定です。 [php]
// 次は廃止される予定です
<?php echo link_to('@some_route', array('post' => true)) ?>
// 次で同じ実装になります
<?php echo link_to('@some_route', array('method' => 'post')) ?>ulf_for()とlink_to()ヘルパーは新しい特徴をサポートするようになりました。 内部URIの代わりに、ルーティング名とパラメータの配列もとることができます。 [php]
echo url_for('@article', array('id' => 1));
echo link_to('Link to article', '@article', array('id' => 1));何も変更を加えなくてもこれまでの設定は動作します。 設定(Configuration)symfony 1.2より前は、全てのプラグインはpluginsディレクトリにインストールされていました。 そして、全ての組み込みプラグインは自動的に読み込まれていました。 symfony 1.2では、あなたのプロジェクト内で利用したいプラグインを有効にする必要があります。 ProjectConfigurationクラスでこれを行うことができます。 以下がDoctrineプラグインを有効にし、Propelプラグインを無効にする方法です。 [php]
public function setup()
{
$this->enablePlugins('sfDoctrinePlugin');
$this->disablePlugins('sfPropelPlugin');
}複数のプラグインを一度に追加する倍はプラグイン名の配列を渡します。 [php]
public function setup()
{
$this->enablePlugins(array('sfDoctrinePlugin', 'sfGuardPlugin'));
}setPluginsメソッドを用いることでプラグインの読み込まれる順番を変更することができます。 [php]
public function setup()
{
$this->setPlugins(array('sfDoctrinePlugin', 'sfCompat10Plugin'));
}settings.ymlにあったorm設定は自動的にORMプラグインが読み込まれるときにセットされるようになったので廃止される予定です。 settings.yml設定にあるcompat_10設定も廃止される予定です。これはsfCompat10Pluginが読み込まれたときに 自動的にセットされるようになったからです。 そのため、1.0と互換性のあるプラグインを有効にするために、設定で次のように有効にする必要があります。 [php]
public function setup()
{
$this->enablePlugins('sfCompat10Plugin');
}標準では、symfonyはPropelプラグインだけが有効です。 全てのインストールしたプラグインも有効にすることができます。 [php]
public function setup()
{
$this->enableAllPluginsExcept('sfDoctrinePlugin');
}上のようにしてDoctrineプラグイン以外の全てのプラグインを有効にすることができます。 1.0または.1.1からアップグレードする場合は、この行によってsymfony 1.0と1.1のときのようにsymfonyを動作させることができます。 ### Plugin configuration プラグインはプラグインを設定するクラスのためオプションが存在します。 これらのプラグイン設定クラスはプラグインのためにオートローディングを設定し、sfProjectConfigurationにインストールされています。 symfony1.2タスクはプラグインクラスが仕様するアプリケーション名をもはや必要としません。 プラグインはcommand.*イベントに接続することで以前はできなかったことができるようになりました。 フィルター(Filters)symfonyはあなたのモデルに基づくフィルター(検索フォーム)をpropel:build-filtersタスクで生成することができるようになりました。 $ php symfony propel:build-filters このタスクは標準ではlib/filter/ディレクトリにフィルタ(検索フォーム)クラスを生成します。 Articleモデルをフィルター処理するためには、以下のようにアクションでコードを書く必要があります。 [php]
$this->filters = new ArticleFormFilter();
if ($request->isMethod('post'))
{
$this->filters->bind($request->getParameter('article_filters'));
if ($this->filters->isValid())
{
$this->articles = ArticlePeer::doSelect($this->filters->getCriteria());
}
}そして、以下が関連するテンプレートのコードです。 [php]
<form action="<?php echo url_for('@articles_filter') ?>" method="post">
<table>
<?php echo $filters ?>
<tr>
<td colspan="2">
<a href="<?php echo url_for('@articles') ?>">Reset</a>
<input type="submit" value="Filter" />
</td>
</tr>
</table>
</form>もし、永続的にリクエスト間でフィルターを保持したいなら、以下のようなちょっとした動作例のように行います。 [php]
public function executeList($request)
{
$this->filters = new ArticleFormFilter($this->getUser()->getAttribute('article_filters'));
if ($request->isMethod('post'))
{
$this->filters->bind($request->getParameter('article_filters'));
if ($this->filters->isValid())
{
$this->getUser()->setAttribute('article_filters', $this->filters->getValues());
}
}
$criteria = $this->filters->buildCriteria($this->getUser()->getAttribute('article_filters'));
$this->articles = ArticlePeer::doSelect($criteria);
}テンプレートの例外処理(Exception Templates)キャッチできないあらゆる発生した例外をレンダー処理するとき、symfonyは現在のリクエストフォーマットを考慮するようになりました。 プロジェクトまたはアプリケーションのconfig/errorディレクトリにテンプレートを追加することで各フォーマットの出力をカスタマイズできます。 例えば、XMLリクエストで発生したキャッチできない例外はアプリケーションがデバッグモード時はconfig/error/exception.xml.phpを、 デバッグモードでない場合はconfig/error/error.xml.phpをレンダー処理します。 プロジェクトディレクトリ内にカスタマイズした500エラーテンプレートを用意していれば、 それを新しいディレクトリに手動で移動する必要があります。
より小さい改善(Smaller improvements)symfony 1.2は多くの改善があちこちでなされています。ここにそのいくつかを紹介します。 ### Action アクションでは、generateUrl()を呼ぶことで直接ルーティングオブジェクトを使うことでURLを生成することができるようになります。 [php]
public function executeIndex()
{
$this->redirect($this->generateUrl('homepage'));
}generateUrl()メソッドにはルーティング名、パラメータの配列、絶対的URLを生成するかどうかをコンストラクターの引数として渡すことができます。 標準で、redirectIf()や``redirectUnless()'メソッドをアクションの中でつかうとき、 symfonyはHTTPレスポンスのステータスを自動的に302に変更します。 これらの2つのメソッドは追加のおpションを持つようになり、この標準のステータスコードを変更できるようになりました。 [php]
$this->redirectIf($condition, '@homepage', 301);
$this->redirectUnless($condition, '@homepage', 301);redirect()メソッドにおいては既にこの機能は実装されています。 ### YAML YAMLパーサーは完全なキーのマージをサポートしました。(サンプルについてはhttp://yaml.org/type/merge.htmlをみてくさい) [php]
$yaml = new sfYamlParser();
var_export($yaml->parse(<<<EOF
default_param: &default_param
datasource: propel
phptype: mysql
hostspec: localhost
database: db
username: user
password: pass
param:
<<: *default_param
username: myuser
password: mypass
EOF
));
// outputs
array(
'default_param' => array(
'datasource' => 'propel',
'phptype' => 'mysql',
'hostspec' => 'localhost',
'database' => 'db',
'username' => 'user',
'password' => 'pass',
)
'param' => array(
'datasource' => 'propel',
'phptype' => 'mysql',
'hostspec' => 'localhost',
'database' => 'db',
'username' => 'myuser',
'password' => 'mypass',
)
)### sfParameterHolder The sfParameterHolderのhas()メソッドはよりその本来の正しい動作になるように変更されました。 もし値がnullだった場合はtrueを返すようになりました。 [php]
$ph = new sfParameterHolder();
$ph->set('foo', 'bar');
$ph->set('bar', null);
$ph->has('foo') === true;
$ph->has('bar') === true; // returns false under symfony 1.0 or 1.1sfparameterHolder::has()メソッドは多くのコアクラスの中でhasParameter()や hasAttribute()メソッドで利用されています。 ### image_tag() helper symfony 1.0と1.1では image_tagヘルパーはファイル名からimgタグのalt属性を生成しています。 これからはsf_compat_10が有効になっているときにだけこのように動作します。 これからは(x)htmlバリデーターが使っているセットされていないalt属性を簡単に見つけることができます。 さらに、新しいalt_titleオプションによってaltをセットし、タイトル属性を同じ値にすることができます。 これはクロスブラウザーでのツールチップとして利用できます。 ### View Configuration symfony 1.2では、module.ymlでpartial_view_classを設定することでパーシャルを処理するために 使用されるビュークラスを変更することができるよになりました。 このクラスはsfPartialViewを拡張したものでなければなりません。 同じことがview_class設定でも行えます。symfonyは自動的にPartialViewを partial_view_classの値に適用しようとします。 [yml]
# module.yml
all:
partial_view_class: my### Factories sfViewCacheManager クラスは factories.ymlで設定できるようになりました。 [yml]
view_cache_manager:
class: sfViewCacheManager### View 標準のsf_cache_namespace_callable設定でsfViewCacheManager::generateCacheKey() を上書きすることができます。 symfony1.2では、collableは追加の引数のビュークラスインスタンスで呼び出されるようになりました。 ### Events symfony 1.2には新しいイベント機能が実装されています。
このイベントは変更が発生したあとに引数としてauthenticatedフラグをとることができます。 ### I18N 内部的に、sfCulterUnfoクラスはこれらかはシングルトンとしてのみ利用できるようになります。 getInstance()メソッドをバイパスすることが可能で、新しいオブジェクトを直接インスタンス化することができるとしても 廃止される予定です。 シングルトンとして利用するために、1リクエストの度に1つのカルチャーについての情報をインスタンス化するためパフォーマンスは向上し、 設定クラスの中でグローバルにカルチャーについて上書きする事ができるということです。 sfCulterInfo::getCountries()とsfCulterInfo::getCurrencies()そしてsfCultureInfo::getLanguages()メソッドは 戻り値を制限するためのオプションの引数をとることができるようになりました。 [php]
// will only return the FR and ES countries in english
$countries = sfCultureInfo::getInstance('en')->getCountries(array('FR', 'ES'));sfCulterInfo::getCurrencies()メソッドは通貨名の配列を返します。 以前のバージョンのsymfonyでは、通貨記号と名前の配列を返していました。 以前のような動作をさせるためには、次のように第2引数にtrueを渡すだけです。 [php]
$currencies = sfCultureInfo::getInstance('en')->getCurrencies(null, true);1つだけの国、言語、通貨の翻訳を取得するためには、getCountry()、getCurrency()、getLanguage()メソッドを sfCultureInfoクラスから使うことができるようになりました。 #### インクルードパスの管理(Include Path Management) symfony 1.2はPHPのinclude_path設定を簡単に行えるようにするために 静的メソッドであるsfToolkit::addIncludePath()メソッドを追加します。 このメソッドは2つのパラメーターを受け付けます。それは単一のパスかパスの配列と、 ポジションを意味する文字列("front", "back"のどちらか)です。第2引数は標準では"front"です。 [php]
// an example from sfPropelPlugin
sfToolkit::addIncludePath(array(
sfConfig::get('sf_root_dir'),
sfConfig::get('sf_symfony_lib_dir'),
realpath(dirname(__FILE__).'/../lib/vendor'),
)); アドミンジェネレータsymfony1.2のためにアドミンジェネレータは書き直されました。そして新しいアドミンジェネレータはフォームフレームワークに基づいています。 ジェネレータでモジュールを生成するためには、propel:generate-adminタスクを次のように利用します。 $ php symfony propel:generate-admin backend Article 標準では、モジュールのためにRESTルーティングを追加します。あなた自身でルーティングを作り、 それをモデルクラス名の代わりに引数として渡すこともできます。 $ php symfony propel:generate-admin backend article 設定はgenerator.ymlを通して行います。全ての設定はconfigキーの下に存在します。 [yml]
generator:
class: sfPropelGenerator
param:
model_class: DemoCategory
theme: admin
non_verbose_templates: true
with_show: false
singular: ~
plural: ~
route_prefix: categories
with_propel_route: 1
config:
actions: ~
fields: ~
list: ~
filter: ~
form: ~
edit: ~
new: ~editとnewの新しいフォームのための異なる設定をもつことができるようになり、それらは form設定から継承されています。 nameエントリーはlabelに名前が変更されました。 古いアドミンジェネレータは後方互換性が保たれています。そのため、propel:init-adminタスクを実行することで利用し続けることができます。 |
Sign in to add a comment