Symfony 2.6 から 2.7 への移行

Symfony 2.6 から 2.7 への移行
=============================

Global
------

非推奨機能を使用すると、警告 (`@trigger_error('... is deprecated ...', E_USER_DEPRECATED)`) が発生するようになりました。

デフォルトの設定では、警告は減殺され、PHP のエラーログにも書き込まれないようになっています。ただし、それら警告は Web のデバッグツールバーから確認できるため、どこのコードを直すべきかがわかるようになっています。

加えて、テストを走らせた際に非推奨機能の警告を行ってくれる [phpunit-bridge](https://github.com/symfony/phpunit-bridge) の有効化を強く推奨します。

Router
------

 * Routeのconditionで、`%parameter%` 記法を使用してコンテナのパラメータを参照できるようになりました。
    条件式はコンパイル時にパラメータの置換が行われるので、既存の式に `%` が含まれる場合は注意が必要です。
    例えば `foo%bar%2` のようなモジュロ演算を行っている場合、2.6以前では `$foo % $bar % 2` と解釈されますが、2.7以降では `bar` がパラメータと判断され、エラーや予期せぬ結果を引き起こす原因となります。(※ 単一の `%` は影響を受けません)
 * `Symfony\Component\Routing\Router` の `getMatcherDumperInstance()` および `getGeneratorDumperInstance()` メソッドの可視性が `protected` から `public` に変更されました。これらのメソッドをサブクラスでオーバーライドしている場合、同じく可視性を `public` に変更しなければなりません。ただし、この変更は PHP 5.3 との互換性を維持するためだけの一時的な変更であり、 Symfony 3.0 では再び元に戻る予定です


Form
----

 * `AbstractType` および、`AbstractExtensionType` の `setDefaultOptions()` メソッドは非推奨となりました。代わりに新しく追加された `configureOptions()` メソッドを使いましょう。

  `setDefaultOptions(OptionsResolverInterface $resolver)` メソッドはSymfony 3.0で `configureOptions(OptionsResolver $resolver)` に置き換わります。

変更前:

```php
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class TaskType extends AbstractType
{
    // ...
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Task',
        ));
    }
}
```

変更後:

```php
use Symfony\Component\OptionsResolver\OptionsResolver;

class TaskType extends AbstractType
{
    // ...
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Task',
        ));
    }
}
```

 * `ChoiceType` の "choice_list" オプションは非推奨となりました。代わりに "choices_as_values" または、"choice_loader" を使いましょう。

変更前:

```php
$form->add('status', 'choice', array(
    'choice_list' => new ObjectChoiceList(array(
       Status::getInstance(Status::ENABLED),
       Status::getInstance(Status::DISABLED),
       Status::getInstance(Status::IGNORED),
    )),
));
```

変更後:

```php
$form->add('status', 'choice', array(
    'choices' => array(
       Status::getInstance(Status::ENABLED),
       Status::getInstance(Status::DISABLED),
       Status::getInstance(Status::IGNORED),
    ),
    'choices_as_values' => true,
));
```

 * `ChoiceType` の "choices" オプションの連想配列はキーと値を反転し、"choices_as_values" を `true` にする必要があります。また、このオプションはSymfony 3.0でデフォルトで `true` となります。

変更前:

```php
$form->add('status', 'choice', array(
    'choices' => array(
       Status::ENABLED => 'Enabled',
       Status::DISABLED => 'Disabled',
       Status::IGNORED => 'Ignored',
    )),
));
```

変更後:

```php
$form->add('status', 'choice', array(
    'choices' => array(
        'Enabled' => Status::ENABLED,
        'Disabled' => Status::DISABLED,
        'Ignored' => Status::IGNORED,
    ),
    'choices_as_values' => true,

    // JavaScript等で、optionのvalue属性値に依存する実装を行っている場合、
    // 以前と同じ動作を維持する為に以下の設定が必要です。
    'choice_value' => function ($choice) {
        return $choice;
    },
));
```

 * `Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface` は非推奨となり、Symfony 3.0で削除されます。代わりに `Symfony\Component\Form\ChoiceList\ChoiceListInterface` を使いましょう.

変更前:

```php
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;

public function doSomething(ChoiceListInterface $choiceList)
{
    // ...
}
```

変更後:

```php
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;

public function doSomething(ChoiceListInterface $choiceList)
{
    // ...
}
```

 * `Symfony\Component\Form\Extension\Core\ChoiceList\View\ChoiceView` は非推奨となり、Symfony 3.0で削除されます。代わりに `Symfony\Component\Form\ChoiceList\View\ChoiceView` を使いましょう。コンストラクタに渡す引数の順番は、非推奨のクラスと同じ順番が維持されます (2.7.0 で引数の順序が変わりましたが、2.7.1 で元の順番に戻されました)。

 * `Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList` は非推奨となり、Symfony 3.0で削除されます。代わりに `Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory` を使いましょう。

変更前:

```php
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;

$choiceList = new ChoiceList(
    array(Status::ENABLED, Status::DISABLED, Status::IGNORED),
    array('Enabled', 'Disabled', 'Ignored'),
    // Preferred choices
    array(Status::ENABLED),
);
```

変更後:

```php
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;

$factory = new DefaultChoiceListFactory();

$choices = array(Status::ENABLED, Status::DISABLED, Status::IGNORED);
$labels = array('Enabled', 'Disabled', 'Ignored');

$choiceList = $factory->createListFromChoices($choices);

$choiceListView = $factory->createView(
    $choiceList,
    // Preferred choices
    array(Status::ENABLED),
    // Labels
    function ($choice, $key) use ($labels) {
       return $labels[$key];
    }
);
```

 * `Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList` は非推奨となり、Symfony 3.0で削除されます。代わりに `Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface` を実装し、`Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory::createListFromLoader()` を使いましょう。

変更前:

```php
use Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList;

class MyLazyChoiceList extends LazyChoiceList
{
    public function loadChoiceList()
    {
       // load $choiceList

       return $choiceList;
    }
}

$choiceList = new MyLazyChoiceList();
```

変更後:

```php
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;

class MyChoiceLoader implements ChoiceLoaderInterface
{
    // ...
}

$factory = new DefaultChoiceListFactory();

$choiceList = $factory->createListFromLoader(new MyChoiceLoader());
```

 * `Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList` は非推奨となり、Symfony 3.0で削除されます。代わりに `Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory` を使いましょう.

変更前:

```php
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;

$choiceList = new ObjectChoiceList(
    array(Status::getInstance(Status::ENABLED), Status::getInstance(Status::DISABLED)),
    // Label property
    'name'
);
```

変更後:

```php
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;

$factory = new DefaultChoiceListFactory();

$choiceList = $factory->createListFromChoices(array(
    Status::getInstance(Status::ENABLED),
    Status::getInstance(Status::DISABLED),
));

$choiceListView = $factory->createView(
    $choiceList,
    // Preferred choices
    array(),
    // Label property
    'name'
);
```

 * `Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList` は非推奨となり、Symfony 3.0で削除されます。代わりに `Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory` を使いましょう。

変更前:

```php
use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;

$choiceList = new SimpleChoiceList(array(
    Status::ENABLED => 'Enabled',
    Status::DISABLED => 'Disabled',
));
```

変更後:

```php
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;

$factory = new DefaultChoiceListFactory();

$choices = array(Status::ENABLED, Status::DISABLED);
$labels = array('Enabled', 'Disabled');

$choiceList = $factory->createListFromChoices($choices);

$choiceListView = $factory->createView(
    $choiceList,
    // Preferred choices
    array(),
    // Label
    function ($choice, $key) use ($labels) {
       return $labels[$key];
    }
);
```

 * `DoctrineType` の "property" オプションは非推奨となりました。代わりに "choice_label" を使いましょう。

変更前:

```php
$form->add('tags', 'entity', array(
    'class' => 'Acme\Entity\MyTag',
    'property' => 'name',
))
```

変更後:

```php
$form->add('tags', 'entity', array(
    'class' => 'Acme\Entity\MyTag',
    'choice_label' => 'name',
))
```

 * `DoctrineType` の "loader" オプションは非推奨となり、Symfony 3.0で削除されます。代わりに拡張クラス内で `getLoader()` メソッドをオーバーライドして下さい。

変更前:

```php
$form->add('tags', 'entity', array(
    'class' => 'Acme\Entity\MyTag',
    'loader' => new MyEntityLoader(),
))
```

変更後:

```php
class MyEntityType extends DoctrineType
{
    // ...

    public function getLoader()
    {
       return new MyEntityLoader();
    }
}
```

 * `Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList` は非推奨となり、Symfony 3.0で削除されます。 代わりに `Symfony\Bridge\Doctrine\Form\ChoiceList\DoctrineChoiceLoader` を使いましょう。

変更前:

```php
use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;

$choiceList = new EntityChoiceList($em, 'Acme\Entity\MyEntity');
```

変更後:

```php
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;

$factory = new DefaultChoiceListFactory();

$choices = array(Status::ENABLED, Status::DISABLED);
$labels = array('Enabled', 'Disabled');

$choiceLoader = new DoctrineChoiceLoader($factory, $em, 'Acme\Entity\MyEntity');
$choiceList = $factory->createListFromLoader($choiceLoader);
```

 * `ORMQueryBuilderLoader` にQueryBuilderを返すクロージャを渡す方法は非推奨となり、Symfony 3.0では使えなくなります。今後はQueryBuilderを直接渡して下さい。

    これに伴い、`ORMQueryBuilderLoader` の引数 `$manager` および、`$class` は非推奨となりました。

    なお `DoctrineType` の "query_builder" オプションはクロージャを*サポートしています*が、今後はクロージャはloaderではなくtypeで解決されるようになります。

変更前:

```php
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;

$queryBuilder = function () {
    // return QueryBuilder
};
$loader = new ORMQueryBuilderLoader($queryBuilder);
```

変更後:

```php
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;

// create $queryBuilder
$loader = new ORMQueryBuilderLoader($queryBuilder);
```

 * `ChoiceToBooleanArrayTransformer`、`ChoicesToBooleanArrayTransformer`、`FixRadioInputListener`、`FixCheckboxInputListener` クラスは非推奨となり、Symfony 3.0で削除されます。
    今後これらの機能は、新しく追加された `RadioListMapper` および、`CheckboxListMapper` でサポートされます。

 * TranslatorコンポーネントによるDoctrineエンティティの翻訳機能はデフォルトで無効となりました。この機能を引き続き使う場合は "choice_translation_domain" オプションを明示的に `true` にする必要があります。

変更前:

```php
$form->add('products', 'entity', array(
    'class' => 'AppBundle/Entity/Product',
));
```

変更後:

```php
$form->add('products', 'entity', array(
    'class' => 'AppBundle/Entity/Product',
    'choice_translation_domain' => true,
));
```

 * `choice_widget_options` ブロック内の `translation_domain` 変数は、`choice_translation_domain` にリネームされました。

変更前:

```jinja
{{ choice.label|trans({}, translation_domain) }}
```

変更後:

```jinja
{{ choice_translation_domain is sameas(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}
```

Serializer
----------

 * `Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer` の `setCamelizedAttributes()` メソッドおよび、`Symfony\Component\Serializer\Normalizer\PropertyNormalizer` クラスは非推奨となりました。今後は NameConverter を使いましょう。

変更前:

```php
$normalizer->setCamelizedAttributes(array('foo_bar', 'bar_foo'));
```

変更後:

```php
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;

$nameConverter = new CamelCaseToSnakeCaseNameConverter(array('fooBar', 'barFoo'));
$normalizer = new GetSetMethodNormalizer(null, $nameConverter);
```

 * インターフェース `Symfony\Component\Serializer\Exception\Exception` は非推奨となりました。代わりに `Symfony\Component\Serializer\Exception\ExceptionInterface` を使いましょう。

PropertyAccess
--------------

 * `UnexpectedTypeException` は引数を3つ (無効なプロパティ値、`PropertyPathInterface` オブジェクト、プロパティパスの現在のインデックス) 取るようになりました。

変更前:

```php
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;

new UnexpectedTypeException($value, $expectedType);
```

変更後:

```php
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;

new UnexpectedTypeException($value, $path, $pathIndex);
```

Config
--------------

 * `\Symfony\Component\Config\ConfigCache` の `__toString()` メソッドは非推奨となりました。代わりに新たに追加された `getPath()` メソッドを使いましょう。

Validator
---------

 * PHP7 と互換性の無い制約クラス(`Null`, `True`, `False`) およびそれらのバリデータ (`NullValidator`, `TrueValidator`, `FalseValidator`) は非推奨となりました。代わりに、 `Is` から始まる名前の、同じ機能を持つ制約とバリデータを使いましょう。

Console
-------

 * `Symfony\Component\Console\Input\InputDefinition::getSynopsis()` メソッドに省略可能な引数が追加されました (これまで引数はありませんでした)。このメソッドをオーバーライドしている場合、メソッドのシグニチャーを合わせるために引数を追加しなければなりません。

変更前:

```php
public function getSynopsis()
{
    // ...
}
```

変更後:

```php
public function getSynopsis($short = false)
{
    // ...
}
```

TwigBundle
----------

 * 非推奨となった`Symfony\Bundle\TwigBundle\TwigDefaultEscapingStrategy` はもう使われておらず、代わりに `Twig_FileExtensionEscapingStrategy` が使われるようになりました。つまり、 CSS ファイルには自動的に CSS エスケープの strategy が適用されるようになります。この変更により、予約語を出力する際の振る舞いが変わります。

変更前:

```css
{# styles.css.twig #}

{# with brand_color: '#123456' #}
body {
    background: {{ brand_color }};
}
```

変更後:

```css
{# styles.css.twig #}

{# with brand_color: '#123456' #}
body {
    background: {{ brand_color|raw }};
}
```

FrameworkBundle
---------------

 * リファクタリングの結果、 `templating.helper.assets` が `Symfony\Component\Templating\Helper\CoreAssetsHelper` の代わりに `Symfony\Bundle\FrameworkBundle\Templating\Helper\AssetsHelper` のインスタンスを返すようになりました。クラス定義を変更するか、あるいは `assets.packages` サービスを代わりに使う必要があります。お勧めは `assets.packages` サービスの使用です。 `templating.helper.assets` サービスは Symfony 3.0 で削除されます。

変更前:

```php
use Symfony\Component\Templating\Helper\CoreAssetsHelper;

class DemoService
{
    private $assetsHelper;

    public function __construct(CoreAssetsHelper $assetsHelper)
    {
       $this->assetsHelper = $assetsHelper;
    }

    public function testMethod()
    {
       return $this->assetsHelper->getUrl('thumbnail.png', null, $this->assetsHelper->getVersion());
    }
}
```

変更後:

```php
use Symfony\Component\Asset\Packages;

class DemoService
{
    private $assetPackages;

    public function __construct(Packages $assetPackages)
    {
       $this->assetPackages = $assetPackages;
    }

    public function testMethod()
    {
       return $this->assetPackages->getUrl('thumbnail.png').$this->assetPackages->getVersion();
    }
}
```

Security
---------------

 `security.context` サービスのインジェクションは必要最小限まで縮小されました。これにより `SecurityContext` または `SecurityContextInterface` としてタイプヒンティングされている引数は `TokenStorageInterface` あるいは `AuthorizationCheckerInterface` のどちらかの型に変更される必要があります。下記クラス群は `security.context` の代わりに `security.token_storage` サービスを使うように変更されました。自分で拡張しているクラスも、同様に変更される必要があります。

 * `AbstractAuthenticationListener`
 * `AnonymousAuthenticationListener`
 * `ContextListener`
 * `SimplePreAuthenticationListener`
 * `X509AuthenticationListener`
 * `RemoteUserAuthenticationListener`
 * `BasicAuthenticationListener`
 * `DigestAuthenticationListener`
 * `ExceptionListener`
 * `SwitchUserListener`
 * `AccessListener`
 * `RememberMeListener`


2.7.1 から 2.7.2 への移行
===========================

Form
----

新しい `ChoiceList` 実装の不具合をいくつか修正するため、2.7 以降に次の点が変更されました。

 * 古い `Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface` は、もう新しい `Symfony\Component\Form\ChoiceList\ChoiceListInterface` を継承しないようになりました。新しいインターフェイスを必要としている箇所に古いインターフェイスの実装を渡している場合には、リストを `LegacyChoiceListAdapter` でラップしてください。


変更前:

```php
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;

function doSomething(ChoiceListInterface $choiceList)
{
    // ...
}

doSomething($legacyList);
```

変更後:

```php
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
use Symfony\Component\Form\ChoiceList\LegacyChoiceListAdapter;

function doSomething(ChoiceListInterface $choiceList)
{
    // ...
}

doSomething(new LegacyChoiceListAdapter($legacyList));
```

 * 新しい `ChoiceListInterface` に対して、さらに二つのメソッド (`getStructuredValues()`, `getOriginalKeys()`) が追加されました。このインターフェイスを実装している場合、メソッドの実装を追加しなければなりません。詳しくはドキュメンテーションコメントや choice list のコア実装を参考にしてください。

 * `ArrayKeyChoiceList::toArrayKey()` メソッドは内部実装扱いになりました。今後このメソッドがこのクラス外から使われることは想定されません。

 * `ChoiceListFactoryInterface::createView()` メソッドの `$groupBy` パラメータは配列や `Traversable` のインスタンスを渡せないようになりました。代わりに `callable` を渡してください。