LoginSignup
13
14

More than 1 year has passed since last update.

EC2 を PHP8 ,Laravel9 にバージョン アップ デート(version up)

Last updated at Posted at 2022-03-17

はじめに

AWS EC2サーバーのPHPとLaravelを最新バージョンに、アップデートする方法についてまとめました。

環境

現環境

  • Amazon Linux 2
  • PHP 7.2.8
  • Laravel 5.7.9
  • nginx 1.12.2
  • composer 1.10.15 (なくても可)

アップデート後

  • Amazon Linux 2
  • PHP 8.0.16
  • Laravel 9.5.1
  • nginx 1.20.0
  • composer 2.2.7

PHPバージョンアップ

PHPバージョンは7.2なので、PHP8にバージョンアップします。

PHPをバージョンアップする前に、/etc/php.iniファイルをローカルにコピーしておいてください。
バージョンアップすると、/etc/php.iniファイルは、デフォルトに書き換えられます。

$ php -v
PHP 7.2.8

PHPのバージョンを変える場合、PHPのパッケージをすべてアンインストールしてから PHP8を有効化する流れになります。

// パッケージアップデート
$ sudo yum update -y

// PHPのパッケージをすべてアンインストール
$ sudo yum -y remove php-*

// amazon-linux-extrasをアップデート
$ sudo yum update -y amazon-linux-extras

// amazon-linux-extrasで使用中のパッケージと使えるパッケージを確認
$ amazon-linux-extras

// php7.2を無効化
$ sudo amazon-linux-extras disable php7.2

// PHP8.0を有効化
$ sudo amazon-linux-extras enable php8.0

// PHP8.0をインストール
sudo amazon-linux-extras install -y php8.0

// インストールするパッケージの案内があったので、表示されたコマンドを実行
$ sudo yum clean metadata && sudo yum install -y php-cli php-pdo php-fpm php-mysqlnd

// webサーバーを再起動します。(apacheの場合)
$ sudo systemctl restart httpd.service
$ sudo systemctl restart php-fpm.service

// webサーバーを再起動します。(nginxの場合)
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

$ php -v
PHP 8.0.16

PHP8にバージョンアップできました。

phpモジュール

phpのバージョンアップ後に、phpモジュールがなくなる場合がありますので、バージョンアップ前にモジュールを確認しておきます。
確認する内容として、rpm -qa|grep phpphp -mの2つがあります。
今回は、例としてバージョンアップ後にphp-mbstringが無くなったと仮定し、再度インストールする方法について記述します。
Laravelだとphp-mbstringは必須かと思います。

バージョンアップ前
$ rpm -qa|grep php
php-mbstring-7.2.8-3.amzn2.0.2.x86_64
などなど

$ php -m
[PHP Modules]
mbstring
バージョンアップ後
$ rpm -qa|grep php
//php-mbstringなし

$ php -m
[PHP Modules]
//php-mbstringなし

以下のコマンドでphp-mbstringをインストールします。

バージョンアップ後
$ sudo yum install -y php-mbstring

$ rpm -qa|grep php
php-mbstring-8.0.16-1.amzn2.x86_64.rpm

$ php -m
[PHP Modules]
mbstring

//再起動を忘れずに
$ sudo nginx -s reload
$ sudo systemctl restart php-fpm

php-mbstringをインストールできました。

php.ini修正

以下の修正をしました。

$ sudo vim /etc/php.ini
/etc/php.ini
- expose_php = On
+ expose_php = Off

# 下記は、お好きに
max_execution_time = 30
upload_max_filesize = 64M
post_max_size = 128M
memory_limit = -1
error_reporting = E_ALL
display_errors = off
display_startup_errors = off
log_errors = on
default_charset = UTF-8

date.timezone = Asia/Tokyo

nginxバージョンアップ

PHPと同様に、パッケージをすべてアンインストールしてから nginxの最新バージョンを有効化する流れになります。

nginxをバージョンアップする前に、/etc/nginx/nginx.confファイルをローカルにコピーしておいてください。
バージョンアップすると、/etc/nginx/nginx.confファイルがデフォルトに書き換えられます。

$ nginx -v
nginx version: nginx/1.12.2

$ rpm -qa|grep nginx
nginx-all-modules-1.12.2-2.amzn2.0.2.noarch
nginx-mod-mail-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-stream-1.12.2-2.amzn2.0.2.x86_64
nginx-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-http-xslt-filter-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-http-perl-1.12.2-2.amzn2.0.2.x86_64
nginx-filesystem-1.12.2-2.amzn2.0.2.noarch
nginx-mod-http-image-filter-1.12.2-2.amzn2.0.2.x86_64
nginx-mod-http-geoip-1.12.2-2.amzn2.0.2.x86_64

$ sudo yum -y remove nginx-mod*

$ sudo amazon-linux-extras disable nginx1.12
$ sudo amazon-linux-extras install nginx1

$ rpm -qa|grep nginx
nginx-1.20.0-2.amzn2.0.4.x86_64
nginx-filesystem-1.20.0-2.amzn2.0.4.noarch

$ rpm -qa|grep nginx
nginx-filesystem-1.22.0-1.amzn2.0.1.noarch
nginx-core-1.22.0-1.amzn2.0.1.x86_64
nginx-1.22.0-1.amzn2.0.1.x86_64

$ nginx -v
nginx version: nginx/1.20.0

// nginx.confファイルを修正します。
$ sudo vim /etc/nginx/nginx.conf

//設定ファイルのチェック
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

// webサーバーを再起動します。(nginxの場合)
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

モジュールが必要であれば以下のコマンドでインストールも可能です。

ただ、私の場合エラーがでました。

// nginx-modをインストール
$ sudo yum -y install nginx-mod*

$ rpm -qa|grep nginx
nginx-mod-http-xslt-filter-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-http-geoip-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-mail-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-stream-1.20.0-2.amzn2.0.4.x86_64
nginx-filesystem-1.20.0-2.amzn2.0.4.noarch
nginx-mod-http-image-filter-1.20.0-2.amzn2.0.4.x86_64
nginx-1.20.0-2.amzn2.0.4.x86_64
nginx-mod-http-perl-1.20.0-2.amzn2.0.4.x86_64

$ sudo nginx -t
nginx: [emerg] module "/usr/lib64/nginx/modules/ngx_http_geoip_module.so" version 1020000 instead of 1022000 in /usr/share/nginx/modules/mod-http-geoip.conf:1
nginx: configuration file /etc/nginx/nginx.conf test failed

対処法がこちらです。よって、上記のモジュールはインストールしませんでした。

nginx.confの設定ファイル

nginx.confファイルの修正は、特に、server内がデフォルトになっているため、元に戻す必要があります。
下記のserver_name,root,location(3行)は、必ず修正してください。

/etc/nginx/nginx.conf
    server {
        listen       80;
        listen       [::]:80;
        server_name  example.com;
        root         /usr/share/nginx/html;
        include /etc/nginx/default.d/*.conf;

        location / {
             try_files $uri $uri/ /index.php?$query_string;
        }

参考として、Laravelのドキュメントにnginxのnginx.confの一例が記載されています。
コピーする必要はありません。

ちなみに、私の場合、nginx.confを最小限の記述で以下の設定になりました。

/etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
	    server_name example.com;
        root         /var/www/html/public;
        include /etc/nginx/default.d/*.conf;

        location / {
                try_files $uri $uri/ /index.php?$query_string;
        }
    }
}

nginx.confでは、デフォルトでconf設定ファイルに関するincludeを以下の2箇所使用されておりましたので、そちらもファイルも記載しておきます。

  • include /etc/nginx/conf.d/*.conf;
  • include /etc/nginx/default.d/*.conf;
/etc/nginx/conf.d/php-fpm.conf
# PHP-FPM FastCGI server
# network or unix domain socket configuration

upstream php-fpm {
        server unix:/run/php-fpm/www.sock;
}
/etc/nginx/default.d/php.conf
# pass the PHP scripts to FastCGI server
#
# See conf.d/php-fpm.conf for socket configuration
#
index index.php index.html index.htm;

location ~ \.(php|phar)(/.*)?$ {
    fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;

    fastcgi_intercept_errors on;
    fastcgi_index  index.php;
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
    fastcgi_pass   php-fpm;
}

index index.php index.html index.htm;などは、/etc/nginx/default.d/php.confに記載されているため、nginx.confに記載する必要がないことが分かりますね。

php-fpmの設定ファイル修正

php-fpmの設定ファイルもデフォルトに上書きされるため、修正します。

$ sudo vim /etc/php-fpm.d/www.conf
/etc/php-fpm.d/www.conf
- user = apache
- group = apache
- ;listen.owner = nobody
- ;listen.group = nobody
- ;listen.mode = 0660

+ user = nginx
+ group = nginx
+ listen.owner = nginx
+ listen.group = nginx
+ listen.mode = 0660

再起動

$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

composerバージョンアップ

composerをインストールしていない場合

こちらの記事を参考に最新版をインストールしましょう

$ composer -V
Composer version 2.2.9 2022-03-15 22:13:37

composerがインストール済みの場合

// 現在のバージョン
$ composer -V
Composer version 2.1.9

// パーミッションエラーでバージョンアップデートできない
$ composer self-update
Upgrading to version 2.2.7 (stable channel).
                                                                                                   
  [Composer\Downloader\FilesystemException]                                                            
  Filesystem exception:                                                                                
  Composer update failed: "/usr/local/bin/composer" could not be written.                              
  rename(/home/ec2-user/.cache/composer/composer-temp.phar,/usr/local/bin/composer): Permission denied

$ ls -la /usr/local/bin
-rwxr-xr-x 1 ec2-user ec2-user 2268732 10月 12 18:07 /usr/local/bin

// パーミッションを変更
$ sudo chmod 0777 /usr/local/bin

$ composer self-update
Upgrading to version 2.2.7 (stable channel).
   
Use composer self-update --rollback to return to version 2.1.9

$ composer -V
Composer version 2.2.9 2022-03-15 22:13:37

// パーミッションを元に戻す
$ sudo chmod 0755 /usr/local/bin/

Laravelのバージョンアップ

Laravelは5系から9系にバージョンアップします。

まず、依存パッケージのアップデートが必要です。
今回、5系から9系にアップデートするため、composer.jsonファイルを修正します。

$ php artisan --version
Laravel Framework 5.7.9

$ vim composer.json

Laravelのドキュメントに、必要なアップデート情報が記載されていました。
7系、8系、9系を確認すると、以下のように、アップデートする必要があります。

下記の中で、元々パッケージが入っていないものは、入れる必要がありません。

composer.json
"php": "^8.0"
"laravel/framework": "^9.0"
"nunomaduro/collision": "^6.1"
"guzzlehttp/guzzle": "^7.0.1"
"laravel/ui": "^3.0"
"phpunit/phpunit": "^9.0"
"laravel/tinker": "^2.0"

また、facade/ignitionがcomposer.jsonにある場合、下記に書き換える

composer.json
- "facade/ignition"
+ "spatie/laravel-ignition": "^1.0"

fideloper/proxyがある場合、Laravel9系では使用できないため、削除しましょう。

composer.json
- "fideloper/proxy"

また、composerにphpのバージョンを伝えておくと、合わせてくれるため、以下のコマンドを実行します。
ちなみに、composerはlaravelプロジェクトのルートディレクトリで実行してください。(appディレクトリがあるところ)

$ composer config platform.php 8.0.16

composer.json に以下が追記されました。

composer.json
    "config": {
        "platform": {
            "php": "8.0.16"
        },

では、composer updateし、パッケージをインストールしましょう。

エラー対応1

$ composer update

  Problem 1
    - phpunit/phpunit[9.3.0, ..., 9.5.x-dev] require ext-dom * -> it is missing from your system. Install or enable PHP's dom extension.
    - Root composer.json requires phpunit/phpunit ^9.3 -> satisfiable by phpunit/phpunit[9.3.0, ..., 9.5.x-dev].

どうやら、ext-domが必要なようです。

$ sudo yum -y install php-xml

$ composer update

無事インストールできました。バージョンを確認してみましょう。

エラー対応2

$ php artisan -V

PHP Fatal error:  Declaration of App\Exceptions\Handler::report(Exception $exception) must be compatible with Illuminate\Foundation\Exceptions\Handler::report(Throwable $e) in /usr/share/nginx/html/user_html/app/Exceptions/Handler.php on line 35

app/Exceptions/Handler.php の Exception の処理が 6.x から 7.x で変更されているため、修正が必要なようです。

$ vim app/Exceptions/Handler.php

修正

app/Exceptions/Handler.php
namespace App\Exceptions;

- use Exception;
+ use Throwable;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    ...
-     public function report(Exception $exception)
+     public function report(Throwable $throwable)
    {
-        parent::report($exception);
+        parent::report($throwable);
    }
    ...
-    public function render($request, Exception $exception)
+    public function render($request, Throwable $throwable)
    {
-        return parent::render($request, $exception);
+        return parent::render($request, $throwable);
    }

エラー対応3

$ php artisan -V

In cache.php line 91:
                                         
  Call to undefined function str_slug()  

Laravel6系から、ヘルパー関数がフレームワークから削除されたため、設定ファイルでエラーが発生しているようです。

laravel/helpersパッケージを追加すると、今までどおり利用できるので、追加しましょう。

$ composer require laravel/helpers

エラー対応4

以下のエラーが出ました。

$ php artisan --version


   Error

  Undefined constant Illuminate\Http\Request::HEADER_X_FORWARDED_ALL

  at vendor/fideloper/proxy/config/trustedproxy.php:48
     44▕      * - 'HEADER_X_FORWARDED_AWS_ELB' (If you are using AWS Elastic Load Balancer)
     45▕      *
     46▕      * @link https://symfony.com/doc/current/deployment/proxies.html
     47▕      */
  ➜  48▕     'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_ALL,
     49▕
     50▕ ];
     51▕

もしくは、laravelのアプリケーションの動作確認時、strage/logs/laravel.logファイルで以下のエラーが出る場合があります。
原因としては、アプリケーションの「信頼できるプロキシ」ミドルウェアを更新する必要があるためです。
下記参考記事

 local.ERROR: Class "Fideloper\Proxy\TrustProxies" not found 
{"exception":"[object] (Error(code: 0)
: Class \"Fideloper\\Proxy\\TrustProxies\" not found at 
/usr/share/nginx/html/xxxxx/app/Http/Middleware/TrustProxies.php:8)
[stacktrace]

ファイルを修正します。

$ vim app/Http/Middleware/TrustProxies.php

修正

app/Http/Middleware/TrustProxies.php
- use Fideloper\Proxy\TrustProxies as Middleware;
+ use Illuminate\Http\Middleware\TrustProxies as Middleware;

- protected $headers = Request::HEADER_X_FORWARDED_ALL;

+ protected $headers =
+   Request::HEADER_X_FORWARDED_FOR |
+   Request::HEADER_X_FORWARDED_HOST |
+   Request::HEADER_X_FORWARDED_PORT |
+   Request::HEADER_X_FORWARDED_PROTO |
+   Request::HEADER_X_FORWARDED_AWS_ELB;

念の為、fideloper/proxyの依存関係をアプリケーションから削除するコマンドを実行しておきます。

$ composer remove fideloper/proxy

再度、Laravelのバージョンを確認しましょう。

$ php artisan --version
Laravel Framework 9.5.1

Laravel9にバージョンアップできました!

エラー対応5

ちなみに、以下のバージョンになった場合、composer.jsonを以下のように修正しましょう。

$ php artisan --version
Laravel Framework 9.x-dev
composer.json

- "minimum-stability": "dev"
+ "minimum-stability": “stable”
- "prefer-stable": true

$ composer update

$ php artisan --version
Laravel Framework 9.5.1

バージョンアップできました!

エラー対応6

login機能のあるLaravelですと、storage/logs/laravel.logで以下のエラーが出力されました。

storage/logs/laravel.log
staging.ERROR: Trait "Illuminate\Foundation\Auth\AuthenticatesUsers" not found 
{"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0):
 Trait \"Illuminate\\Foundation\\Auth\\AuthenticatesUsers\" not found 
at /var/www/html/app/Http/Controllers/Admin/Auth/LoginController.php:9)

laravel/uiをインストールするとエラーが解消されます。

$ composer require laravel/ui 

エラー対応7

storage/logs/laravel.logで以下のエラーが出力されました。

In aws.php line 28:
                                                    
  Class "Aws\Laravel\AwsServiceProvider" not found  
                                                    

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

AWS-SDKをインストールするとよいです。

$ composer require aws/aws-sdk-php-laravel

Amazon ElastiCache の Redisを使用している場合

バージョンをあげることで、以下のエラーが出ました。

local.ERROR: Class "RedisCluster" not found {"exception":"[object] 
(Error(code: 0): Class \"RedisCluster\" not found at

PHP8では、peclredisをインストールする必要があります。
ちなみに、yumだとインストールできませんでした。

$ sudo yum install php-pecl-redis
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                                                                                                                                 | 3.7 kB  00:00:00    
amzn2extra-docker                                                                                                                                          | 3.0 kB  00:00:00    
amzn2extra-nginx1                                                                                                                                          | 3.0 kB  00:00:00    
amzn2extra-php8.0                                                                                                                                          | 3.0 kB  00:00:00    
パッケージ php-pecl-redis は利用できません。
エラー: 何もしません
// peclでインストールしますので、pearをインストールします
$ sudo yum install -y php-pear

// phpredisをインストールすると、ビルドエラーが起きるので、その前にphp-develとgccをインストールします
$ sudo yum install -y gcc
$ sudo yum install -y php-devel

// php.iniに追加
$ sudo su
# echo "extension=redis.so" > /etc/php.d/redis.ini
# exit 

// peclでphpredisをインストールします。3つ聞かれますが、デフォルトでよいので、Enterを押しましょう。
$ sudo pecl install redis

enable igbinary serializer support? [no] :
enable lzf compression support? [no] :
enable zstd compression support? [no] :

$ sudo pecl list | grep redis
redis   5.3.7   stable

// webサーバーを再起動します。(apacheの場合)
$ sudo systemctl restart httpd.service
$ sudo systemctl restart php-fpm.service

// webサーバーを再起動します。(nginxの場合)
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

動作確認時のエラー対応方法

上記の対応後も、動作がうまく行かない場合、下記の観点でエラー対応します。

  • logの確認
  • 設定ファイルの確認
  • キャッシュクリア
  • ファイルとディレクトリの権限

log確認コマンド

$ sudo tail -100 storage/logs/laravel.log

$ sudo tail -100 /var/log/php-fpm/www-error.log

// nginxの場合
$ sudo tail -100 /var/log/nginx/access.log
$ sudo tail -100 /var/log/nginx/error.log

// apacheの場合
$ sudo tail -100 /var/log/apache2/access.log
$ sudo tail -100 /var/log/apache2/error.log
もしくは
$ sudo tail -100 /var/log/httpd/access.log
$ sudo tail -100 /var/log/httpd/error.log

設定ファイルの確認

また、エラー原因となりやすい設定ファイルを確認・修正しましょう。


$ sudo vim .env

$ sudo vim /etc/nginx/nginx.conf 

$ sudo vim /etc/php.ini

$ sudo vim /etc/php-fpm.d/www.conf

// 修正後は、webサーバーを再起動します。
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm

キャッシュクリア

キャッシュされていることが原因で、エラーのままになることがあります。

$ php artisan cache:clear
$ php artisan config:clear
$ php artisan route:clear
$ php artisan view:clear

キャッシュクリアエラー

php artisan cache:clearで以下のエラーが起きましたので、対応します。
エラー原因は、storage/framework/cacheディレクトリ以下にdataディレクトリが存在しないためですので、作成するだけです。

$ php artisan cache:clear
Failed to clear cache. Make sure you have the appropriate permissions.

$ sudo mkdir storage/framework/cache/data
$ touch storage/framework/cache/data/.gitkeep
$ sudo vim storage/framework/cache/.gitignore

.gitignoreにdataは、反映するよう設定します。

storage/framework/cache/.gitignore
/*
!.gitignore
!data
$ php artisan cache:clear
Application cache cleared!

キャッシュクリアできました。

ファイルとディレクトリの権限

Laravelの権限は、laravelのプロジェクトディレクトリに移動し、基本的に以下でよいです。

$ sudo chown -R nginx:nginx ./
$ sudo find ./ -type d -exec chmod 755 {} +
$ sudo find ./ -type f -exec chmod 664 {} +
$ sudo chmod 777 -R storage bootstrap/cache

ただし、EC2にファイルをアップロードするため、SFTP接続する場合、SSH接続時のユーザーに権限を持たせる必要があるたえ、以下の権限の方がよいです。
ユーザー名がec2-userと仮定します。

$ sudo chown -R nginx:ec2-user ./
$ sudo find ./ -type d -exec chmod 775 {} +
$ sudo find ./ -type f -exec chmod 664 {} +
$ sudo chmod 777 -R storage bootstrap/cache

Laravel9からLaravel8系にバージョンを下げる

Laravel9だと修正箇所が多いため、Laravel8系にしたい場合もあるかと思います。
composer.jsonを修正し、composer updateするだけです。

composer.json
"laravel/framework": "^9.0"      "laravel/framework": "8.83.5"
"nunomaduro/collision": "^6.1"  →    "nunomaduro/collision": "^5.0"
$ composer update

$ php artisan --version
Laravel Framework 8.83.5

参考記事

13
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14