Laravel 5.5へのアップグレード
お客様で運用されているシステムのフレームワークのバージョンアップを行いました。
システムで使用しているフレームワークがLaravel 5.4で古いものだったので、相談の結果、LTS版の5.5に移行する形となりました。
アップグレードに必要な作業自体は以下のページに書いてあるので、変更箇所を洗いだして地道に修正していきます。
https://readouble.com/laravel/5.5/ja/upgrade.html
最も影響が大きかったのがBladeの@phpディレクティブに関する変更で、従来は以下のようなインライン形式での記述ができましたが、
@php ($teamMember = true)
これを、以下のように修正する必要があります。テンプレート内でインライン形式の記述が大量にあったので地道に修正していきます。
@php $teamMember = true; @endphp
Laravel本体以外も更新が必要でした。フォームの生成にはLaravel Collectiveを使っていましたが、これも5.4 -> 5.5に移行することになります。5.4 -> 5.5で大きく変わったのは内部の比較処理において、==から===を使うようになったことです。strict comparisonになったので0(integer)と'0'(string)はマッチしなくなります。
このため、値を選択するタイプのフォーム要素(ラジオボタン、セレクトボックス、チェックボックス)では、若干面倒なことが発生します。
例えば、ブログの記事を格納するarticleテーブルがあり、記事の有効/無効を表すenableカラムをINT型で持っていて、これをラジオボタンで設定できるようなフォームがあるとします。
Articleモデルのenableプロパティ($article->enable)はテーブルのカラム型に合わせてinteger型になります。一方、入力エラーでフォームを再表示する際に参照するold inputのenableの値は文字列になります(POSTされた値は文字列として扱われるので)。
このため、ラジオボタンのvalueを以下のように値としている場合、$article->enableの値はフォームに初期値として正しく表示されますが、入力エラーでフォームを再表示させた際、選択していたラジオボタンが未選択状態になってしまいます(old inputのenableはstringなのでvalueで指定した値(integer)とは一致しないから)。
case1: valueをintegerで設定
{{ Form::model($article, ...) }} ... 略 ... <label>{{ Form::radio('enable', 1) }}有効</label> <label>{{ Form::radio('enable', 0) }}無効</label> ... 略 ... {{ Form::close() }}
入力エラー時にラジオボタンを再選択させるには、以下のようにvalueを文字列で指定すればいいのですが、このようにすると、今度はフォームを初期表示する際に、ラジオボタンが未選択状態になってしまいます($article->enableはintegerのため)。
case2: valueをstringで設定
{{ Form::model($article, ...) }} ... 略 ... <label>{{ Form::radio('enable', '1') }}有効</label> <label>{{ Form::radio('enable', '0') }}無効</label> ... 略 ... {{ Form::close() }}
というわけで、モデルのプロパティの型($article->enable)、old inputの型、Form::radioのvalueの型を全て一致させておく必要があります。色々検討しましたが、今回は影響が少なくなるように、Model($article)のプロパティをstringに変換してから{{ Form::model($article, ...) }}に渡す対応をとりました(フォームはcase2の形式で作成)。
ラジオボタン以外にもチェックボックス、セレクトボックスにおいても同様の問題が発生しうるので確認する必要があります。
あとは修正箇所と全フォームのテストを実施して完了です。
[追記と補足]
Laravel Collectiveでvalueをstrict comparisonで選択判定していた処理はやはり問題だったようで、gitの5060a664のcommitでloose comparisonに戻っています。v5.6以降なら今回のような型変換をしなくてもすんなり移行できるのではないかと思います。
src/FormBuilder.phpの関連する処理
protected function compareValues($name, $value) { return $this->getValueAttribute($name) == $value; }
投稿日:2019/03/14 01:58(最終更新:2019/03/15 11:31)