PHP5.6+Laravel5.1からPHP7+Laravel5.2へアップデート


PHP7が公開されたので現状のサーバーをPHP5.6からPHP7にアップデートしたので手順を書いてみました。  
結果としてプロジェクトのソースコードの変更は特に必要なく、PHP7へ移行することが出来たので
PHP7への移行コストはかなり少なかったです。  
## 環境
- CentOS 6.6 64bit  
- PHP 5.6
- Laravel 5.1

# 手順
## 1.準備
### 1.1 現在の状態を確認

    # yum list installed | grep php
    php56u.x86_64         5.6.16-1.ius.centos6
    php56u-cli.x86_64     5.6.16-1.ius.centos6
    php56u-common.x86_64  5.6.16-1.ius.centos6
    php56u-mbstring.x86_64
    php56u-mcrypt.x86_64  5.6.16-1.ius.centos6
    php56u-mysqlnd.x86_64 5.6.16-1.ius.centos6
    php56u-pdo.x86_64     5.6.16-1.ius.centos6
    php56u-pear.noarch    1:1.10.1-2.ius.centos6
    php56u-pecl-jsonc.x86_64
    php56u-pgsql.x86_64   5.6.16-1.ius.centos6
    php56u-process.x86_64 5.6.16-1.ius.centos6
    php56u-xml.x86_64     5.6.16-1.ius.centos6
    
    # php artisan --version
	Laravel Framework version 5.1.19 (LTS)

### 1.2 レポジトリを追加
yumリポジトリにEPELとremiリポジトリを追加

	# yum install epel-release
	# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
	
## 2.PHP7インストール
### 2.1 PHP5.6の削除
1.1で確認したパッケージを削除

	# yum remove php56u*
	
### 2.2 PHP7のインストール
remi-php70を有効にしてインストール

	# yum -y install --enablerepo=remi-php70 php php-mbstring php-pear php-fpm php-mcrypt php-devel php-xml php-pdo
	
### 2.3 PHPのバージョンを確認

	# php -v
	PHP 7.0.2 (cli) (built: Jan  6 2016 15:33:31) ( NTS )
	Copyright (c) 1997-2015 The PHP Group
	Zend Engine v3.0.0, Copyright (c) 1998-2015 Zend Technologies

### 2.4 PHPモジュール確認
		
	# yum list installed | grep php
	php.x86_64             7.0.2-1.el6.remi @remi-php70
	php-cli.x86_64         7.0.2-1.el6.remi @remi-php70
	php-common.x86_64      7.0.2-1.el6.remi @remi-php70
	php-devel.x86_64       7.0.2-1.el6.remi @remi-php70
	php-fpm.x86_64         7.0.2-1.el6.remi @remi-php70
	php-json.x86_64        7.0.2-1.el6.remi @remi-php70
	php-mbstring.x86_64    7.0.2-1.el6.remi @remi-php70
	php-mcrypt.x86_64      7.0.2-1.el6.remi @remi-php70
	php-pear.noarch        1:1.10.1-1.el6.remi
                                        @remi-php70
	php-process.x86_64     7.0.2-1.el6.remi @remi-php70
	php-xml.x86_64         7.0.2-1.el6.remi @remi-php70
	
## 3.Laravel5.2インストール
### 3.1 composerの設定変更
Laravelの公式ページに従って設定を変更
https://laravel.com/docs/5.2/upgrade#upgrade-5.2.0

require内の`laravel/framework`を`5.2.*`に変更
require-dev内に`"symfony/dom-crawler": "~3.0"`と`"symfony/css-selector": "~3.0"`を追記

```composer.json
{
    "name": "laravel/laravel",
    "description": "The Laravel Framework.",
    "keywords": ["framework", "laravel"],
    "license": "MIT",
    "type": "project",
    "require": {
        "php": ">=5.5.9",
        "laravel/framework": "5.2.*"
    },
    "require-dev": {
        "fzaninotto/faker": "~1.4",
        "mockery/mockery": "0.9.*",
        "phpunit/phpunit": "~4.0",
        "symfony/css-selector": "~3.0",
        "symfony/dom-crawler": "~3.0"
    },
    "autoload": {
        "classmap": [
            "database"
        ],
        "psr-4": {
            "App\\": "app/"
        }
    },
    "autoload-dev": {
        "classmap": [
            "tests/TestCase.php"
        ]
    },
    "scripts": {
        "post-root-package-install": [
            "php -r \"copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "php artisan key:generate"
        ],
        "post-install-cmd": [
            "php artisan clear-compiled",
            "php artisan optimize"
        ],
        "pre-update-cmd": [
            "php artisan clear-compiled"
        ],
        "post-update-cmd": [
            "php artisan optimize"
        ]
    },
    "config": {
        "preferred-install": "dist"
    }
}
```

### 3.2 Laravel5.1削除
vendorフォルダとcomposer.lockファイルを削除

	# rm -rf vendor
	# rm -f composer.lock

### 3.3 Laravel5.2インストール

	# composer install
	Loading composer repositories with package information
	Installing dependencies (including require-dev)
	Your requirements could not be resolved to an installable set of packages.
	
	Problem 1
		- Conclusion: don't install laravel/framework v5.2.10
	    - Conclusion: don't install laravel/framework v5.2.9
	    - Conclusion: don't install laravel/framework v5.2.8
	    - Conclusion: don't install symfony/finder v3.0.1
	    - Conclusion: don't install laravel/framework v5.2.7
	    - Conclusion: don't install symfony/finder v3.0.0
	    - Conclusion: don't install laravel/framework v5.2.6
	    - Conclusion: don't install symfony/finder v2.8.2
	    - Conclusion: don't install laravel/framework v5.2.5
	    - Conclusion: don't install symfony/finder v2.8.1
	    - Installation request for rcrowe/twigbridge 0.7.x -> satisfiable by rcrowe/twigbridge[v0.7.0, v0.7.1, v0.7.2].
	    - Conclusion: don't install laravel/framework v5.2.4
	    - laravel/framework v5.2.0 requires symfony/finder 2.8.*|3.0.* -> satisfiable by symfony/finder[v2.8.0, v2.8.1, v2.8.2, v3.0.0, v3.0.1].
	    - laravel/framework v5.2.1 requires symfony/finder 2.8.*|3.0.* -> satisfiable by symfony/finder[v2.8.0, v2.8.1, v2.8.2, v3.0.0, v3.0.1].
	    - laravel/framework v5.2.2 requires symfony/finder 2.8.*|3.0.* -> satisfiable by symfony/finder[v2.8.0, v2.8.1, v2.8.2, v3.0.0, v3.0.1].
	    - laravel/framework v5.2.3 requires symfony/finder 2.8.*|3.0.* -> satisfiable by symfony/finder[v2.8.0, v2.8.1, v2.8.2, v3.0.0, v3.0.1].
	    - Conclusion: don't install symfony/finder v2.8.0
	    - Installation request for laravel/framework 5.2.* -> satisfiable by laravel/framework[v5.2.0, v5.2.1, v5.2.10, v5.2.2, v5.2.3, v5.2.4, v5.2.5, v5.2.6, v5.2.7, v5.2.8, v5.2.9].

パッケージを追加している場合は上記のようなエラーが出ることがある
composer.jsonの該当パッケージのバージョンを最新にする
各パッケージの情報は下記のサイトを参照
https://packagist.org/

### 3.4 Service Providersの変更
Laravel5.2より`Illuminate\Foundation\Providers\ArtisanServiceProvider`と`Illuminate\Routing\ControllerServiceProvider`はなくなったので`config/app.php`から削除

```config/app.php
	︙
	'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        // Illuminate\Foundation\Providers\ArtisanServiceProvider::class,
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        // Illuminate\Routing\ControllerServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        Illuminate\Database\DatabaseServiceProvider::class,
        Illuminate\Encryption\EncryptionServiceProvider::class,
        Illuminate\Filesystem\FilesystemServiceProvider::class,
        Illuminate\Foundation\Providers\FoundationServiceProvider::class,
        Illuminate\Hashing\HashServiceProvider::class,
        Illuminate\Mail\MailServiceProvider::class,
        Illuminate\Pagination\PaginationServiceProvider::class,
        Illuminate\Pipeline\PipelineServiceProvider::class,
        Illuminate\Queue\QueueServiceProvider::class,
        Illuminate\Redis\RedisServiceProvider::class,
        Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        Illuminate\Session\SessionServiceProvider::class,
        Illuminate\Translation\TranslationServiceProvider::class,
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,
	︙
```

`Generating autoload files`の段階でcomposerのインストールは終わっているので`update`コマンドを叩く

	# composer update
	> php artisan clear-compiled
	Loading composer repositories with package information
	Updating dependencies (including require-dev)
	Nothing to install or update
	Generating autoload files
	> php artisan optimize
	Generating optimized class loader



# 4.遭遇したエラー
## 4.1 エクステンション不足
	# composer install
	Loading composer repositories with package information
	Installing dependencies (including require-dev)
	︙
	Writing lock file
	Generating autoload files
	> php artisan clear-compiled
	PHP Fatal error:  Uncaught ReflectionException: Class log does not exist in /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:738
	Stack trace:
	#0 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php(738): ReflectionClass->__construct('log')
	#1 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php(633): Illuminate\Container\Container->build('log', Array)
	#2 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(674): Illuminate\Container\Container->make('log', Array)
	#3 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php(853): Illuminate\Foundation\Application->make('log')
	#4 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php(808): Illuminate\Container\Container->resolveClass(Object(ReflectionParameter))
	#5 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php(777): Illuminate\Container\Container->getDe in /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php on line 738
	
PDOエクステンションがなかったためエラーが出ていたので追加でインストール

	# yum -y --enablerepo=remi-php70 install php-pdo

参考：http://laravel.io/forum/12-03-2015-is-laravel-php7-compatible
	
## 4.2 パッケージの変更内容対応	
今回は`Collective\Html`をパッケージ追加していた。
`Collective\Html`の`FormBuilder`関数の引数が増えているので対応

```app/Libraries/TwigExtension.php
<?php

namespace App\Libraries;

use App\Http\DataTransfers\CoreDatatransfer;
use App\Libraries\HttpHelper;
use Twig_Extension;
use Twig_SimpleFunction;
use Collective\Html\FormBuilder;

class TwigExtension extends Twig_Extension
{
    private $form_builder;

    public function __construct()
    {
        $app = app();
        $this->form_builder = new FormBuilder($app['html'], $app['url'],  $app['session.store']->getToken());
    }
    
    ↓
    
<?php

namespace App\Libraries;

use App\Http\DataTransfers\CoreDatatransfer;
use App\Libraries\HttpHelper;
use Twig_Extension;
use Twig_SimpleFunction;
use Collective\Html\FormBuilder;

class TwigExtension extends Twig_Extension
{
    private $form_builder;

    public function __construct()
    {
        $app = app();
        $this->form_builder = new FormBuilder($app['html'], $app['url'], $app['view'], $app['session.store']->getToken());
    }
```