Silexが2018年6月にEOLになることが発表されました。

SilexのEOLは非常に残念ですが、Symfony4+Flexにより、Symfonyが小さなアプリから大規模なシステムまでカバーできるようになったため、Silexはその役割を終えた、ということなのだろうなと考えています。

今回は、Silex-SkeletonをSymfony4+Flexの構成に移行してみたので、その手順を紹介したいと思います。

前提

  • Silex-SkeletonをSymfony4+Flexの構成に移行します
  • PHP7.1.3以上の環境が必要です

環境のセットアップ

まずはSilex-Skeltonをcloneし、動かすまで。

$ git clone https://github.com/silexphp/Silex-Skeleton.git
$ cd Silex-Skeleton 
$ composer install
$ composer run
> echo 'Started web server on http://localhost:8888'
Started web server on http://localhost:8888
> php -S localhost:8888 -t web

http://localhost:8888 にアクセスし、Welcome to your new Silex Application!が表示されればOKです。単純な表示確認なので、確認できればCTRL+Cでサーバを止めてもらって構いません。

ディレクトリ構成

Symfony4+Flexのディレクトリ構成は以下のディレクトリ構成にする必要があります。

symfony+flex/
├── assets/
├── bin/
│   └── console
├── config/
│   ├── bundles.php
│   ├── packages/
│   ├── routes.yaml
│   └── services.yaml
├── public/
│   └── index.php
├── src/
│   ├── ...
│   └── Kernel.php
├── templates/
├── tests/
├── translations/
├── var/
└── vendor/

Silex-Skeltonのディレクトリ構成を見てみると、以下のようになっています。

silex-skelton/
├── bin/
│   └── console
├── config/
│   ├── dev.php
│   └── prd.php
├── web/
│   └── index.php
├── src/
│   ├── app.php
│   ├── console.php
│   └── controllers.php
├── templates/
├── tests/
├── var/
└── web/
    └── index.php

webpublicに変わっている以外は、それほど違いはありません。いったんはこのままで進めます。

composer.jsonのマージ

Upgrading Existing Applications to Flexにある通り、ディレクトリ構成はほぼ同じなので、あとは依存関係をあわせていく必要があります。

Silex-Skeletonのcomposer.jonとSymfony+Flexのcomposer.jsonをマージします。
Symfony+Flexのcomposer.jsonはcomposer create-project symfony/skeleton xxxとかで作っておくとわかりやすいです。

composer.jsonをがっちゃんこしたのが、以下になります。

// composer.json

-        "php": ">=5.5.9",
+        "php": "^7.1.3",
+        "ext-iconv": "*",
+        "symfony/console": "^4.0",
+        "symfony/flex": "^1.0",
+        "symfony/framework-bundle": "^4.0",
+        "symfony/lts": "^4@dev",
+        "symfony/yaml": "^4.0",
         "silex/silex": "~2.0",
         "silex/web-profiler": "~2.0",
         "symfony/asset": "~2.8|^3.0",
         "symfony/browser-kit": "~2.8|^3.0",
         "symfony/class-loader": "~2.8|^3.0",
         "symfony/config": "~2.8|^3.0",
-        "symfony/console": "~2.8|^3.0",
         "symfony/css-selector": "~2.8|^3.0",
         "symfony/debug": "~2.8|^3.0",
         "symfony/finder": "~2.8|^3.0",
@@ -23,8 +28,18 @@
         "symfony/twig-bridge": "~2.8|^3.0",
         "symfony/validator": "~2.8|^3.0"
     },
+    "require-dev": {
+        "symfony/dotenv": "^4.0"
+    },
     "autoload": {
-        "psr-0": { "": "src/" }
+        "psr-4": {
+            "App\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "App\\Tests\\": "tests/"
+        }
     },

ここから、composer update --devすると、いくつかのファイルやディレクトリが生成されます。

// composer update後のgit status

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   .gitignore
    modified:   composer.json

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    .env.dist
    composer.lock
    config/bundles.php
    config/packages/
    config/routes.yaml
    config/routes/
    config/services.yaml
    flex/
    public/
    src/Controller/
    src/Kernel.php
    symfony.lock
    translations/

Symfony+Flexで必要なディレクトリやファイルが生成されているのがわかります。

この状態で、php -S localhost:8000 -t publicし、http://localhost:8000/ にアクセスしてみましょう。※ドキュメントルートは、webではなくpublicを指定します。

多分こんなエラーが表示されると思います。

FileLoaderLoadException
The autoloader expected class "App\app" to be defined in file "/Users/xxx/repos/Silex-Skeleton/vendor/composer/../../src/app.php". The file was found but the class was not in it, the class name or namespace probably has a typo in /Users/xxx/repos/Silex-Skeleton/config/services.yaml (which is loaded in resource "/Users/xxx/repos/Silex-Skeleton/config/services.yaml").

これは、Symfonyがsrc以下のファイルをすべてコンテナに登録しようとしており、その際にapp.phpでエラーになっています。

config/services.yamlを編集して除外しておきます。

// config/services.yaml
    App\:
        resource: '../src/*'
-       exclude:'../src/{Entity,Migrations,Tests}'
+       exclude:'../src/{Entity,Migrations,Tests,app.php,console.php,controllers.php}'

app.phpの移行

ここから、Silexのアプリケーションを移行していきます。
Silexのエンドポイントであるweb/index.phpをみると、

// web/index.php
$app = require __DIR__.'/../src/app.php';
require __DIR__.'/../config/prod.php';
require __DIR__.'/../src/controllers.php';
$app->run();

のようになっています。

src/app.phpでは、いくつかのサービスプロバイダが有効になっています。

// src/app.php
$app->register(new ServiceControllerServiceProvider());
$app->register(new AssetServiceProvider());
$app->register(new TwigServiceProvider());
$app->register(new HttpFragmentServiceProvider());

サービスプロバイダはSymfonyでは利用できないため、バンドル等に移行していく必要がありますが、ここで必要なのはTwigServiceProviderのみです。それ以外は、FrameworkBundleに含まれているため、特に何もする必要はありません。

TwigServiceProviderに対応するTwigBundleをインストールします。

$ composer req twigでインストールします。

config/prd.phpをみると、

// config/prd.php
$app['twig.path'] = array(__DIR__.'/../templates');
$app['twig.options'] = array('cache' => __DIR__.'/../var/cache/twig');

のように定義されていますが、composer req twigで、config/twig.yamlが生成されており、twigのパスなどはすでに設定されている状態になっています。

twig:
    paths: ['%kernel.project_dir%/templates']
    debug: '%kernel.debug%'
    strict_variables: '%kernel.debug%'

ここで、http://localhost:8000/ にアクセすると、やはりエラーになりますが、NotFoundHttpExceptionにエラー内容が変わっていると思います。※あとついでにエラー画面もSilexのものよりリッチになっています。

コントローラの移行

Silexのコントローラは、src/controllers.phpに定義されています。

// src/controlelrs.php
$app->get('/', function () use ($app) {
    return $app['twig']->render('index.html.twig', array());
})
->bind('homepage')
;

Symfonyの場合、コントローラはsrc/Controller/以下にコントローラのクラスを配置します。
コントローラはコマンドで生成するのが楽なので、以下のようにMakerBundleをインストールします。

$ composer req annotations make

※MakerBundleがSensioExtraFrameworkBundleに依存するため、annotationsで合わせてインストールしています。

$ bin/console make:controllerでコントローラを作成します。

$ bin/console make:controller
Choose a name for your controller class (e.g. DeliciousGnomeController):
 > IndexController

 created: src/Controller/IndexController.php

作成されたIndexControllerをSilexのコントローラに合わせ、以下のように編集します。

// src/Contoroller/IndexController.php

 class IndexController extends Controller
 {
     /**
-     * @Route("/index", name="index")
+     * @Route("/", name="homepage")
      */
     public function index()
     {
         // replace this line with your own code!
-        return $this->render('@Maker/demoPage.html.twig', [ 'path' => str_replace($this->getParameter('kernel.project_dir').'/', '', __FILE__) ]);
+        return $this->render('index.html.twig');
     }
 }

http:localhost:8000 にアクセスし、Welcome to your new Silex Application!が表示されれば成功です。

もし更新されない場合は、キャッシュされている場合もあるので$ bin/console cache:clearでキャッシュをクリアしてみてください。

以上で、Silex-SkeletonをSymfony4+Flexの構成で動かすまでができました。

ただ、Silex-Skeletonはほんとに最小構成なので、実際に運用されているシステムの場合は、他にも色々移行する必要があるかと思います。

無理にSilexのまま移植していくよりかは、SymfonyのSkeletonの上に載せ替えていくほうが楽かな、と思いました。

次項で各種サービスプロバイダの移行先バンドル・ライブラリを調べてみたので、参考にしてみてください。

各種サービスプロバイダの移行

Silex-Skeletonは必要最小限の構成のため、各種サービスプロバイダを利用している場合は、それぞれSymfonyの各バンドルやライブラリへ移行する必要があります。

Silexの公式で紹介されているサービスプロバイダの移行先バンドルは以下になります。

AssetServiceProvider

FrameworkBundleに含まれているため、バンドルのインストールは不要です。

composer req assetasset componentをインストールすれば利用できます。

CsrfServiceProvider

FrameworkBundleに含まれているため、バンドルのインストールは不要です。

composer req symfony/security-csrfsecurity-csrfをインストールすれば利用できます。

DoctrineServiceProvider

Doctrine Bundleをインストールします。

composer req doctrineでインストールできます。

FormServiceProvider

Form Componentをインストールします。

composer req formでインストールできます。

HttpCacheServiceProvider

FrameworkBundleに含まれているため、バンドルのインストールは不要です。

HttpFragmentServiceProvider

FrameworkBundleに含まれているため、バンドルのインストールは不要です。

LocaleServiceProvider

FrameworkBundleに含まれているため、バンドルのインストールは不要です。

MonologServiceProvider

Monolog Bundleをインストールします。

composer req monologでインストールできます。

RememberMeServiceProvider

FrameworkBundleに含まれているため、バンドルのインストールは不要です。

SecurityServiceProvider

SecurityBundleをインストールします。

composer req securityでインストールできます。

SerializerServiceProvider

serializer componentをインストールします。

composer req symfony/serializerでインストールできます。

ServiceControllerServiceProvider

FrameworkBundleに含まれているため、バンドルのインストールは不要です。

SessionServiceProvider

FrameworkBundleに含まれているため、バンドルのインストールは不要です。

SwiftmailerServiceProvider

SwiftmailerBundleをインストールします。

composer req mailでインストールできます。

TranslationServiceProvider

translation componentをインストールします。

composer req symfony/translationでインストールできます。

TwigServiceProvider

TwigBundleをインストールします。

composer req twigでインストールできます。

ValidatorServiceProvider

validator comoponentをインストールします。

composer req symfony/validatorでインストールできます。

VarDumperServiceProvider

DebugBundleをインストールします。

composer req debug-packでインストールできます。

以上です。

Symfonyを触り始めてまだ2〜3週間程度なので、移行先のバンドルやライブラリについては誤りがあるかもしれません。もし間違いなどありましたらご指摘いただけるとありがたいです。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.