Symfony 2.7 から 2.8 への移行

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

Form
----

 * "cascade_validation" オプションが非推奨となりました。代わりに "constraints" オプションで `Valid` バリデーション制約を指定して下さい。
   "constraints" オプションは "cascade_validation" と異なり、親フォームではなく各子フォームに設定する必要があります。

   変更前:

```php
$form = $this->createFormBuilder($article, array('cascade_validation' => true))
   ->add('author', new AuthorType())
   ->getForm();
```

   変更後:

```php
use Symfony\Component\Validator\Constraints\Valid;

$form = $this->createFormBuilder($article)
   ->add('author', new AuthorType(), array(
       'constraints' => new Valid(),
   ))
   ->getForm();
```

   `Valid` バリデーション制約はモデル自身に設定しても構いません:
   
```php
use Symfony\Component\Validator\Constraints as Assert;

class Article
{
   /**
    * @Assert\Valid
    */
   private $author;
}
```

 * タイプ名は非推奨となり、3.0で削除されます。今後はタイプの参照にはタイプ名ではなく、タイプの完全修飾クラス名（FQCN）を使用する必要があります。PHP 5.5以降では "class" 定数を使用すると良いでしょう:

   変更前:

```php
$form = $this->createFormBuilder()
   ->add('name', 'text')
   ->add('age', 'integer')
   ->getForm();
```

   変更後:

```php
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

$form = $this->createFormBuilder()
   ->add('name', TextType::class)
   ->add('age', IntegerType::class)
   ->getForm();
```

   それに伴って `FormTypeInterface::getName()` メソッドも非推奨となり、3.0で削除される為、フォームタイプからこのメソッドを削除する必要があります。

   Twigで独自のblock prefixを使用する場合、今後は `FormTypeInterface::getBlockPrefix()` を実装して下さい:

   変更前:

```php
class UserProfileType extends AbstractType
{
   public function getName()
   {
       return 'profile';
   }
}
```

   変更後:

```php
class UserProfileType extends AbstractType
{
   public function getBlockPrefix()
   {
       return 'profile';
   }
}
```
   
   AbstractTypeの `getBlockPrefix()` メソッドをオーバーライドしない場合、block prefixにはクラス名から末尾の "Type" を除き、スネークケース化された文字列が使用されます（上記の場合は "user_profile" です）。

   もしSymfony 2.3〜2.8間で互換性のあるフォームタイプを作りたい場合は、DEPRECATIONエラーを発生させない為に `getName()` と `getBlockPrefix()` の**両方を**実装する必要があります:

```php
class ProfileType extends AbstractType
{
   public function getName()
   {
       return $this->getBlockPrefix();
   }

   public function getBlockPrefix()
   {
       return 'profile';
   }
}
```

   更に、フォームタイプをDependency Injectionに登録している場合は、"alias" 引数を削除する必要があります:
   
   変更前:

```xml
<service id="my.type" class="Vendor\Type\MyType">
   <tag name="form.type" alias="mytype" />
</service>
```

   変更後:

```xml
<service id="my.type" class="Vendor\Type\MyType">
   <tag name="form.type" />
</service>
```

   タイプエクステンションは、今後拡張するフォームタイプの完全修飾クラス名を返す必要があります。

   変更前:

```php
class MyTypeExtension extends AbstractTypeExtension
{
   public function getExtendedType()
   {
       return 'form';
   }
}
```

   変更後:

```php
use Symfony\Component\Form\Extension\Core\Type\FormType;

class MyTypeExtension extends AbstractTypeExtension
{
   public function getExtendedType()
   {
       return FormType::class;
   }
}
```
   
   タイプ同様、Symfony 2.3〜2.8に互換性のあるタイプエクステンションを作る場合は `getExtendedType()` メソッドを次のように実装して下さい:

```php
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FormType;

class MyTypeExtension extends AbstractTypeExtension
{
   public function getExtendedType()
   {
       return method_exists(AbstractType::class, 'getBlockPrefix') ? FormType::class : 'form';
   }
}
```

 * `FormTypeInterface::getParent()` で親のタイプインスタンスを返す事は、2.8で非推奨となり、3.0ではサポートされなくなります。
   今後は親のフォームタイプの完全修飾クラス名を返すようにしましょう。

   変更前:

```php
class MyType
{
   public function getParent()
   {
       return new ParentType();
   }
}
```

   変更後:

```php
class MyType
{
   public function getParent()
   {
       return ParentType::class;
   }
}
```

 * `Form::add()`、`FormBuilder::add()`、`FormFactory::create*()` メソッドも同様に、タイプインスタンスを渡す事は3.0以降できなくなります。
   他の変更と同様、完全修飾クラス名を渡すようにして下さい。

   変更前:

```php
$form = $this->createForm(new MyType());
```

   変更後:

```php
$form = $this->createForm(MyType::class);
```
 
 * タイプエクステンションをサービスとして登録する際、`getExtendedType()` メソッドの返り値と異なるタイプのaliasを使う事ができなくなった為、正しいタイプに修正する必要があります。

 * `form.type_extension` タグのaliasは非推奨となりました。代わりに `extended_type` または `extended-type` を使いましょう。 
 
   変更前:
   
```xml
<service id="app.type_extension" class="Vendor\Form\Extension\MyTypeExtension">
   <tag name="form.type_extension" alias="text" />
</service>
```

   変更後:
   
```xml
<service id="app.type_extension" class="Vendor\Form\Extension\MyTypeExtension">
   <tag name="form.type_extension" extended-type="Symfony\Component\Form\Extension\Core\Type\TextType" />
</service>
```

Translator
----------

 * `Symfony\Component\Translation\Translator` の `getMessages()` メソッドは非推奨となり、Symfony 3.0で削除されます。
   代わりに `Symfony\Component\Translation\TranslatorBagInterface` の `getCatalogue()` メソッドを使いましょう。

   変更前:

```php
$messages = $translator->getMessages();
```

   変更後:

```php
$catalogue = $translator->getCatalogue($locale);
$messages = $catalogue->all();

while ($catalogue = $catalogue->getFallbackCatalogue()) {
    $messages = array_replace_recursive($catalogue->all(), $messages);
}
```

DependencyInjection
-------------------

 * scopeの概念は非推奨となりました。この為、次のメソッドが非推奨になりました:

    - `Symfony\Component\DependencyInjection\ContainerBuilder::getScopes()`
    - `Symfony\Component\DependencyInjection\ContainerBuilder::getScopeChildren()`
    - `Symfony\Component\DependencyInjection\ContainerInterface::enterScope()`
    - `Symfony\Component\DependencyInjection\ContainerInterface::leaveScope()`
    - `Symfony\Component\DependencyInjection\ContainerInterface::addScope()`
    - `Symfony\Component\DependencyInjection\ContainerInterface::hasScope()`
    - `Symfony\Component\DependencyInjection\ContainerInterface::isScopeActive()`
    - `Symfony\Component\DependencyInjection\Definition::setScope()`
    - `Symfony\Component\DependencyInjection\Definition::getScope()`
    - `Symfony\Component\DependencyInjection\Reference::isStrict()`

  これに加え、`Symfony\Component\DependencyInjection\ContainerInterface::set()` の `$scope` と、 `Symfony\Component\DependencyInjection\Reference` の `$strict` パラメーターがそれぞれ非推奨となりました。

 * `prototype` スコープの代替として、サービス定義に `shared` と言う新しいフラグが追加されました。

   変更前:

```php
use Symfony\Component\DependencyInjection\ContainerBuilder;

$container = new ContainerBuilder();
$container
   ->register('foo', 'stdClass')
   ->setScope(ContainerBuilder::SCOPE_PROTOTYPE)
;
```

```yml
services:
   foo:
       class: stdClass
       scope: prototype
```

```xml
<services>
   <service id="foo" class="stdClass" scope="prototype" />
</services>
```

   変更後:

```php
use Symfony\Component\DependencyInjection\ContainerBuilder;

$container = new ContainerBuilder();
$container
   ->register('foo', 'stdClass')
   ->setShared(false)
;
```

```yml
services:
   foo:
       class: stdClass
       shared: false
```

```xml
<services>
   <service id="foo" class="stdClass" shared="false" />
</services>
```

WebProfiler
-----------

 * `profiler:import` および `profiler:export` コマンドは非推奨となり、Symfony 3.0で削除されます。

 * Webデバッグツールバーのデザインが刷新されました。これにあわせ、ツールバーのHTMLマークアップが多少変更されました。
  
   変更前:

   情報は単なる `<span>` タグで囲まれていただけでした:

```twig
{% block toolbar %}
   {% set icon %}
       <span>
           <svg ...></svg>
           <span>{{ '%.1f'|format(collector.memory / 1024 / 1024) }} MB</span>
       </span>
   {% endset %}
{% endblock %}
```

   変更後:

   今後は値とラベル毎にそれぞれ異なる `class` を持つ `<span>` にラップされます: 

```twig
{% block toolbar %}
   {% set icon %}
       <svg ...></svg>
       <span class="sf-toolbar-value">
           {{ '%.1f'|format(collector.memory / 1024 / 1024) }}
       </span>
       <span class="sf-toolbar-label">MB</span>
   {% endset %}
{% endblock %}
```

   以前のデザインで使用されていたblockの殆どが利用可能ですが、新旧両方のデザインに対応したツールバーを作成する場合は、テンプレートに渡される新しい変数 `profiler_markup_version` を利用すると良いでしょう:

```twig
{% block toolbar %}
   {% set profiler_markup_version = profiler_markup_version|default(1) %}

   {% set icon %}
       {% if profiler_markup_version == 1 %}

           {# code for the original toolbar #}

       {% else %}

           {# code for the new toolbar (Symfony 2.8+) #}

       {% endif %}
   {% endset %}
{% endblock %}
```

 * `FileProfilerStorage` 以外の全てのプロファイラーストレージは非推奨となりました。具体的には以下のクラスが該当します: 
 
    - `Symfony\Component\HttpKernel\Profiler\BaseMemcacheProfilerStorage`
    - `Symfony\Component\HttpKernel\Profiler\MemcachedProfilerStorage`
    - `Symfony\Component\HttpKernel\Profiler\MemcacheProfilerStorage`
    - `Symfony\Component\HttpKernel\Profiler\MongoDbProfilerStorage`
    - `Symfony\Component\HttpKernel\Profiler\MysqlProfilerStorage`
    - `Symfony\Component\HttpKernel\Profiler\PdoProfilerStorage`
    - `Symfony\Component\HttpKernel\Profiler\RedisProfilerStorage`
    - `Symfony\Component\HttpKernel\Profiler\SqliteProfilerStorage`

   今後は `FileProfileStorage` あるいは、`ProfileStorageInterface` を実装した独自のストレージを使いましょう。

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

 * `session`.`cookie_httponly` パラメーターのデフォルト値が `true` になりました。
   これはJavaScriptのようなスクリプト言語からのCookieへのアクセスを防ぎ、XSS攻撃によってIDを盗まれる危険性を減らせます。
   引き続きセッションのCookieにアクセスする場合はこのパラメーターをオーバーライドして下さい:
 
```yaml
framework:
   session:
       cookie_httponly: false
```

Security
--------

 * `AbstractToken::isGranted()` メソッドは非推奨となりました。代わりに `voteOnAttribute()` をオーバーライドして下さい。
   このメソッドにはユーザーの代わりにTokenInterfaceが渡されます:

   変更前:

```php
class MyCustomVoter extends AbstractVoter
{
   // ...

   protected function isGranted($attribute, $object, $user = null)
   {
       // ...
   }
}
```

   変更後:

```php
class MyCustomVoter extends AbstractVoter
{
   // ...

   protected function voteOnAttribute($attribute, $object, TokenInterface $token)
   {
       $user = $token->getUser();
       // ...
   }
}
```

Config
------

 * `\Symfony\Component\Config\Resource\ResourceInterface::isFresh()` メソッドは非推奨となり、Symfony 3.0で削除されます。
   全てのリソースの実装が必ずしも鮮度の確認を自分自身で行えるとは限らない為です。

   このメソッドを実装しているリソースは、`\Symfony\Component\Config\Resource\ResourceInterface` の代わりに、これを継承する `\Symfony\Component\Config\Resource\SelfCheckingResourceInterface` を実装して下さい。

   変更前:

```php
use Symfony\Component\Config\Resource\ResourceInterface;

class MyCustomResource implements ResourceInterface { ... }
```

   変更後:

```php
use Symfony\Component\Config\Resource\SelfCheckingResourceInterface;

class MyCustomResource implements SelfCheckingResourceInterface { ... }
```

   また、新しく追加された `ResourceChecker` ベースのキャッシュ検証システムの導入も検討してみて下さい。

---

Source: https://raw.githubusercontent.com/symfony/symfony/86b4c0536cac411cdbe7cef3c1c68f17c49d49ec/UPGRADE-2.8.md