Symfony 2.5 から 2.6 への移行

原文は<a href="https://github.com/symfony/symfony/blob/master/UPGRADE-2.6.md" target="_blank">こちら</a>。個人的に `PdoSessionHandler` と `OptionsResolver` の変更が厄介だと思います(´・ω・｀)

## Form

- "choice", "date", "datetime" および "time" タイプのオプション `empty_value` が非推奨となりました。代わりに `placeholder` を使いましょう。

変更前:

```php
$form->add('category', 'choice', array(
    'choices' => array('politics', 'media'),
    'empty_value' => 'Select a category...',
));
```
変更後:
  
```php
$form->add('category', 'choice', array(
    'choices' => array('politics', 'media'),
    'placeholder' => 'Select a category...',
));
```
  
  これに合わせ、view が持つ変数 `empty_value` および `empty_value_in_choices` も非推奨となります。代わりに `placeholder`, `placeholder_in_choices` を使いましょう。
  
変更前:
  
```twig
{{ form.vars.empty_value }}

{% if form.vars.empty_value_in_choices %}
    ...
{% endif %}
```
  
変更後:
  
```twig
{{ form.vars.placeholder }}

{% if form.vars.placeholder_in_choices %}
    ...
{% endif %}
```

  ※オプション `empty_value` および view 変数 `empty_value`, `empty_value_in_choices` は、Symfony 3.0 で削除されます。

## Validator

- `Symfony\Component\Validator\Context\ExecutionContextInterface` に内部的なメソッド `setConstraint()` が追加されました。このメソッドは現在検証中の Constraint をコンテキストに通知します。

このインターフェースを実装している場合、`setConstraint()` メソッドを新たに追加する必要がありますが、とりあえず空のメソッドを実装するだけでも問題ありません:
  
```php
public function setConstraint(Constraint $constraint)
{
}
```
  
- 2.6 以前では、`Symfony\Component\Validator\Constraints\ExpressionValidator` は、NULLまたは空の文字列がセットされたオブジェクトのプロパティを検証しませんでしたが、2.6 以降では検証するようになりました。
  
以前の振る舞いを再現するには、Expressionを次のように書き換える必要があります:
  
```
value == null or (YOUR_EXPRESSION)
```

## Security

- `SecurityContextInterface` が非推奨となりました。代わりに `Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface` と `Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface` を使いましょう。

```
SecurityContextInterface::isGranted()  => AuthorizationCheckerInterface::isGranted()
SecurityContextInterface::getToken()   => TokenStorageInterface::getToken()
SecurityContextInterface::setToken()   => TokenStorageInterface::setToken()
```
  
これに合わせ、`SecurityContext` も非推奨となりますが、削除されるまでは後方互換性を100%保証します。

  ※ `SecurityContextInterface` および `SecurityContext` は Symfony 3.0 で削除されます。
  
- 上記に加え、 `security.context` サービスも非推奨となりますので、次のように置き換えてください:

```
@security.authorization_checker => isGranted()
@security.token_storage         => getToken()
@security.token_storage         => setToken()
```

## HttpFoundation

- セッションをDBに保存する `PdoSessionHandler` には大幅な変更が加えられました。
    - 同じセッションへの同時アクセスによるデータの損失を防ぐため、セッションのロックをデフォルトで行うようになりました。
      - セッション開始から終了までの間トランザクションが使用されるため、DBコネクションはアプリケーションで使用している物と使い分けるか、セッションが終了・保存されるまでDBにアクセスしない事を推奨します。また、ハンドラには既存のDBコネクションの代わりにDSN文字列を渡すことで、セッションが開始されるまでDBの接続を遅延させる事が可能です。
      - 同じセッションが開いている間はそのセッションへのアクセスはブロックされるので、それ以上のデータの書き込みが必要無くなった時点でセッションを保存するのが望ましいです。例えば読み取り専用のAJAXリクエストでは、セッション開始後すぐに保存することで同時実効性を高めることができます。
      - この他にトランザクションを必要としないアドバイザリロックを利用したり、ロック機能自体を無効にすることも可能です。楽観的並行性制御のような競合状態に対応する独自のロジックを持っている場合は無効にしてください。ロックストラテジは、`new PdoSessionHandler($pdoOrDsn, array('lock_mode' => PdoSessionHandler::LOCK_NONE))` のようにクラス定数で指定する事ができます。  
    ※詳しい情報はクラスのドキュメントをご覧ください。
    - テーブルのスキーマが変更されました。
      - セッションのデータはNULLバイトを含める事のできるバイナリテキストで書き込まれるため、保存先のカラムはBLOBのようなバイナリ型である必要があります。（base64によるエンコード処理は廃止されました。）
      - 新たにセッションのライフタイムを保持するカラムが必要となりました。これによりセッション毎に異なるライフタイムを保持する事が可能となりました。（`session.gc_maxlifetime` INI設定の値が適用されます。）
      - 既存のユーザのセッション情報を保持したい場合、手動でテーブル構成のマイグレートを行う必要があります。
      - `PdoSessionHandler::createTable` を利用することで、使用しているDBベンダに応じて正しくテーブルを初期化することが可能です。
 
## OptionsResolver

- `OptionsResolverInterface` の `setRequired()`, `setAllowedValues()`, `addAllowedValues()`, `setAllowedTypes()`, および `addAllowedTypes()` メソッドから "array" のタイプヒントが削除されました。
- `OptionsResolver` はクラス間で共有される事が無いため、`OptionsResolverInterface` は非推奨となりました。今後はタイプヒントで `OptionsResolver` を指定してください。

変更前:
  
```php
protected function configureOptions(OptionsResolverInterface $resolver)
{
   // ...
}
```
  
変更後:
  
```php
protected function configureOptions(OptionsResolver $resolver)
{
   // ...
}
```
  
- `OptionsResolver::isRequired()` は必須のオプションがデフォルト値を持っている場合でも`true` を返すようになりました。以前の挙動を再現するには新しく追加された `isMissing()` メソッドを使う必要があります。

変更前:
  
```php
$resolver->setRequired(array('port'));
  
$resolver->isRequired('port');
// => true
  
$resolver->setDefaults(array('port' => 25));
  
$resolver->isRequired('port');
// => false
```
  
変更後:
  
```php
$resolver->setRequired(array('port'));

$resolver->isRequired('port');
// => true
$resolver->isMissing('port');
// => true

$resolver->setDefaults(array('port' => 25));

$resolver->isRequired('port');
// => true
$resolver->isMissing('port');
// => false
```
  
- `OptionsResolver::replaceDefaults()` は非推奨となりました。代わりに `clear()` と `setDefaults()` を使いましょう。

変更前:
  
```php
$resolver->replaceDefaults(array(
    'port' => 25,
));
```
  
変更後:
  
```php
$resolver->clear();
$resolver->setDefaults(array(
    'port' => 25,
));
```
  
- `OptionsResolver::setOptional()` が非推奨になりました。代わりに `setDefined()` を使いましょう。

変更前:
  
```php
$resolver->setOptional(array('port'));
```
  
変更後:
  
```php
$resolver->setDefined('port');
```

  
- `OptionsResolver::isKnown()` が非推奨になりました。代わりに `isDefined()` を使いましょう。

変更前:
  
```php
if ($resolver->isKnown('port')) {
    // ...
}
```
  
変更後:

```php
if ($resolver->isDefined('port')) {
    // ...
}
```

- メソッド `setAllowedValues()`, `addAllowedValues()`, `setAllowedTypes()`, `addAllowedTypes()` は一括登録ができなくなりました。1度の実行で設定できるオプションは1つまでとなります。（後方互換性のために、Symfony 3.0までは以前のように使うこともできます。）

変更前:
  
```php
$resolver->setAllowedValues(array(
    'method' => array('POST', 'GET'),
));
```
  
変更後:

```php
$resolver->setAllowedValues('method', array('POST', 'GET'));
```

- `Options` クラスはインターフェースとなり、`OptionsResolver` が実装する形でマージされました。手動でこのクラスのインスタンス化を行っている場合は、`OptionsResolver` に置き換えてください。

変更前:
  
```php
$options = new Options();
```
  
変更後:

```php
$resolver = new OptionsResolver();
```

- 未設定のオプションはノーマライズが行われなくなりました。ノーマライズする場合はデフォルト値を定義してください。

変更前:
  
```php
$resolver->setOptional(array('port'));
$resolver->setNormalizers(array(
    'port' => function ($options, $value) {
        // return normalized value
    }
));

$options = $resolver->resolve($options);
```
  
変更後:

```php
$resolver->setDefault('port', null);
$resolver->setNormalizer('port', function ($options, $value) {
    // return normalized value
});

$options = $resolver->resolve($options);
```

- 未定義のオプションが `resolve()` に渡された時、`InvalidOptionsException` の代わりに `UndefinedOptionsException` がスローするようになりました。`InvalidOptionsException` はバリデーション制約に違反した時だけスローされるようになります。

変更前:
  
```php
$resolver->setDefaults(array(
    'transport' => 'smtp',
    'port' => 25,
));
$resolver->setAllowedTypes(array(
    'port' => 'integer',
));

// throws InvalidOptionsException
$resolver->resolve(array('foo' => 'bar'));

// throws InvalidOptionsException
$resolver->resolve(array('port' => '25'));
```
  
変更後:

```php
$resolver->setDefaults(array(
    'transport' => 'smtp',
    'port' => 25,
));
$resolver->setAllowedTypes(array(
  'port' => 'integer',
));

// throws UndefinedOptionsException
$resolver->resolve(array('foo' => 'bar'));

// throws InvalidOptionsException
$resolver->resolve(array('port' => '25'));
```

※非推奨となったインターフェースおよびメソッドは Symfony 3.0 で削除されます。

## VarDumper and DebugBundle

新しいコンポーネントとバンドルが追加されました。_dev_ および_test_ 環境では以下のバンドルを有効にしておく事をおすすめします。（次の行を `WebProfilerBundle` より前に追加にして下さい）

```php:app/AppKernel.php
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
```

PHPコード上で `dump($var)` を、Twigコード上で `{% dump var %}` または `{{ dump(var) }}` を実行する事で値をダンプすることができるようになりました。ダンプされた値は **デバッグツールバー** 内に表示されます。