タイトルの通り、Laravelのバージョンを5.1から5.5へアップグレードしたので、その時のメモです。 ちなみにですが、5.1から5.5へのアップグレードなんてやるべきではないです。新バージョンが出るたびに細かくアップグレードしていくのがベストです。 小規模なサービスですら対応範囲は多いので、大規模サービスとなるとかなりの工数がかかると思います。

とりあえずバージョンを上げてみる

5.1から5.5となると変更点はかなりありますが、そこまで大きいプロジェクトでもなかったのでとりあえず5.5にバージョンアップしてみました。 Laravelのバージョンアップは、基本的には composer.json を書き換えて composer update を実行します。

composer.json書き換え

まずはcomposer.jsonの書き換えとなります。ほぼ全部書き換えです。 とりあえずアップグレード と言ってますが、5.5からはPHPの対応バージョンが7.0以上となっているので、サーバのPHPバージョンが5系のままだと、そもそもアップグレードができません。 今回、PHPのバージョンは7以上だったので、強行突破してます。

diff --git a/composer.json b/composer.json
index cc83e39..14321dd 100644
--- a/composer.json
+++ b/composer.json
@@ -5,15 +5,22 @@
     "license": "MIT",
     "type": "project",
     "require": {
-        "php": ">=5.5.9",
-        "laravel/framework": "5.1.*",
-        "doctrine/dbal": "^2.5"
+        "php": ">=7.0.0",
+        "fideloper/proxy": "~3.3",
+        "laravel/framework": "5.5.*",
+        "laravel/tinker": "~1.0"
     },
     "require-dev": {
+        "filp/whoops": "~2.0",
         "fzaninotto/faker": "~1.4",
         "mockery/mockery": "0.9.*",
-        "phpunit/phpunit": "~4.0",
-        "phpspec/phpspec": "~2.1"
+        "phpunit/phpunit": "~6.0"
+    },
+    "extra": {
+        "laravel": {
+            "dont-discover": [
+            ]
+        }
     },
     "autoload": {
         "classmap": [
@@ -31,18 +38,14 @@
     },
     "scripts": {
         "post-root-package-install": [
-            "php -r \"copy('.env.example', '.env');\""
+            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
         ],
         "post-create-project-cmd": [
-            "php artisan key:generate"
-        ],
-        "post-install-cmd": [
-            "Illuminate\\Foundation\\ComposerScripts::postInstall",
-            "php artisan optimize"
+            "@php artisan key:generate"
         ],
-        "post-update-cmd": [
-            "Illuminate\\Foundation\\ComposerScripts::postUpdate",
-            "php artisan optimize"
+        "post-autoload-dump": [
+            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
+            "@php artisan package:discover"
         ]
     },
     "config": {

composer update

composer.json を書き換えたら、composer update を実行します。

$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
...
...
...
Writing lock file
Generating autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover

In ProviderRepository.php line 208:

  Class 'Illuminate\Routing\ControllerServiceProvider' not found


Script @php artisan package:discover handling the post-autoload-dump event returned with error code 1

これは、5.2へのアップグレード時に対応する内容です。

config/app.php の中の 下記の記述を削除して、もう一度 composer update 実行。

Illuminate\Routing\ControllerServiceProvider::class,
$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover

In EventServiceProvider.php line 8:

  Declaration of App\Providers\EventServiceProvider::boot(Illuminate\Contract
  s\Events\Dispatcher $events) should be compatible with Illuminate\Foundatio
  n\Support\Providers\EventServiceProvider::boot()


Script @php artisan package:discover handling the post-autoload-dump event returned with error code 1

またエラーが出ました。

Declaration of App\Providers\EventServiceProvider::boot(Illuminate\Contract
s\Events\Dispatcher $events) should be compatible with Illuminate\Foundatio
n\Support\Providers\EventServiceProvider::boot()

これは、5.3へアップグレードするときの対応内容です。

app/Providers/ 以下の EventServiceProvider.php および RouteServiceProvider.phpboot()メソッドの引数を削除します。

@@ -24,9 +24,9 @@ class EventServiceProvider extends ServiceProvider
      * @param  \Illuminate\Contracts\Events\Dispatcher  $events
      * @return void
      */
-    public function boot(DispatcherContract $events)
+    public function boot()
     {
-        parent::boot($events);
+        parent::boot();

         //
     }
@@ -22,11 +22,11 @@ class RouteServiceProvider extends ServiceProvider
      * @param  \Illuminate\Routing\Router  $router
      * @return void
      */
-    public function boot(Router $router)
+    public function boot()
     {
         //

-        parent::boot($router);
+        parent::boot();
     }

     /**

再度 composer update 実行。

$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Package manifest generated successfully.

成功したようなので、バージョンを確認します。

$ php artisan --version
Laravel Framework 5.5.23

とりあえず動かしてみる

Laravel自体のアップグレードはできたので、プロジェクトのほうを修正していきます。
Laravelの公式ドキュメントは、各バージョンへのアップグレード時に何をする必要があるのかを書いてくれているので、今回のように一気にアップグレードではなく、その都度アップグレードしている場合にはこれに沿って対応してくのが基本です。

今回は、とりあえず動かしてみて、エラーと戦ってきたいと思います。

セッション

Column not found: 1054 Unknown column 'user_id' in 'field list'
セッションをDBに保持するようにしている場合、上記のようなエラーが出ます。
これは5.2へのアップグレード時に対応する内容で、ドキュメントには次のように書かれています。

ユーザID、IPアドレス、ユーザエージェントのような情報をより含む、新しいdatabaseセッションドライバが書かれました。古いドライバーを使い続けたい場合は、session.php設定ファイルへlegacy-databaseドライバを指定してください。 新しいドライバーを使用する場合、セッションのデータベーステーブルへ、user_id (NULL値を許す整数)、ip_address (NULL値を許す整数)、user_agent (テキスト)カラムを追加してください。

ということで、カラムを追加します。

$ php artisan make:migration alter_add_session
<?php
/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::table('sessions', function($t){
        $t->integer('user_id')->nullable();
        $t->integer('ip_address')->nullable();
        $t->string('user_agent');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::table('sessions', function($t){
        $t->dropColumn(['user_id', 'ip_address', 'user_agent']);
    });
}
$ php artisan migrate
**************************************
*     Application In Production!     *
**************************************

 Do you really wish to run this command? (yes/no) [no]:
 >

アプリケーションが本番だけど、大丈夫?と聞かれてしまいました。.env では APP_ENV=local となっているのに、なぜ?
これも5.2で対応内容ですが、config/app.phpenv のデフォルトオプションが追加されていました。

diff --git a/config/app.php b/config/app.php
index f013735..3f597f9 100644
--- a/config/app.php
+++ b/config/app.php
@@ -2,6 +2,8 @@

 return [

+    'env' => env('APP_ENV', 'production'),

これで local で確認無しでマイグレーションが通ります。

ルートフィルター

Method [beforeFilter] does not exist on [App\Http\Controllers\***
これは5.1の時点で非推奨、5.2で削除となったルートフィルターの使用によるエラーです。

より好ましいミドルウェアにより、ルートフィルターは非推奨となりました。

とあるように、ミドルウェアへの移行が必要です。まあ、5.1のうちに移行しておくべきだった内容ですが。

ミドルウェアの作成

今回の場合、以下のようにController内にフィルターを書いていました。

<?php
class HogeController extends Controller {

	public function __construct()
	{
		parent::__construct();

		$this->beforeFilter("@filterHoge");
	}

	public function filterHoge()
	{
		// 処理
	}
}

これを、ミドルウェアに移行します。

$ php artisan make:middleware HogeMiddleware
<?php
class HogeMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // 処理
        return $next($request);
    }
}

ヘルパ

  • url()

url()ヘルパ関数が、引数のパスの指定がない場合にIlluminate\Routing\UrlGeneratorを返すようになりました。

例えばプロジェクトのルートパスが https://hogehoge.com だった場合、5.1では

<?php
$u = url();

echo $u;

// https://hogehoge.com

でしたが、5.2以降で同じような結果を得るためには

<?php
$u = url('/');

echo $u;

// https://hogehoge.com

とする必要があります。 url() のまま放置して、その値に文字列結合をしている場合、Object of class Illuminate\Routing\UrlGenerator could not be converted to string と言われます。

Laravelの恩恵を受けきれていない?

ざっと動かした感じでは致命的なものはこれくらいでした。 おそらく、フレームワークに依存してないのが良かったと思われます。 逆に言うと、Laravelの恩恵を受けきれていないのかもしれません。

何かあれば追記していきます。


以上、よっしー (michimani) でした。

Share to ...

Follow on Feedly

comments powered by Disqus