Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ナツへの扉
Search
takeshi_sengoku
May 31, 2018
Technology
2
550
ナツへの扉
PHP5.3.3からPHP7.2.6への移行についての知見
takeshi_sengoku
May 31, 2018
Tweet
Share
Other Decks in Technology
See All in Technology
【若手エンジニア応援LT会】AWS Security Hubの活用に苦労した話
kazushi_ohata
0
150
Jr. Championsになって、強く連携しながらAWSをもっと使いたい!~AWSに対する期待と行動~
amixedcolor
0
170
生成AIとAWS CDKで実現! 自社ブログレビューの効率化
ymae
2
310
最速最小からはじめるデータプロダクト / Data Product MVP
amaotone
5
720
カメラを用いた店内計測におけるオプトインの仕組みの実現 / ai-optin-camera
cyberagentdevelopers
PRO
1
120
Emacs x Nostr
hakkadaikon
1
150
MAMを軸とした動画ハンドリングにおけるAI活用前提の整備と次世代ビジョン / abema-ai-mam
cyberagentdevelopers
PRO
1
110
LeSSに潜む「隠れWF病」とその処方箋
lycorptech_jp
PRO
2
120
[AWS JAPAN 生成AIハッカソン] Dialog の紹介
yoshimi0227
0
140
20241031_AWS_生成AIハッカソン_GenMuck
tsumita
0
100
失敗しないOpenJDKの非互換調査
tabatad
0
260
プロダクトチームへのSystem Risk Records導入・運用事例の紹介/Introduction and Case Studies on Implementing and Operating System Risk Records for Product Teams
taddy_919
1
160
Featured
See All Featured
Gamification - CAS2011
davidbonilla
80
5k
Practical Orchestrator
shlominoach
186
10k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
167
49k
Faster Mobile Websites
deanohume
304
30k
Into the Great Unknown - MozCon
thekraken
31
1.5k
Designing for humans not robots
tammielis
249
25k
Designing for Performance
lara
604
68k
Bash Introduction
62gerente
608
210k
YesSQL, Process and Tooling at Scale
rocio
167
14k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
6.9k
How GitHub (no longer) Works
holman
311
140k
Code Review Best Practice
trishagee
64
17k
Transcript
ナツへの扉 (PHP5.3.3からPHP7.2.6への移行についての知見) ©︎ 2018 PRECS Inc.
どんなひと? • 仙石 毅 • PHPでの商売歴は15年ほど • PHP3からの付き合い • 昔はJavaやC#などもやっていました
• "如何にして人間様を動かさないか"に興味があります • "(初回以降で)ロジックに触れたら負けだと思っている" • 今はサーバサイドチームでこんな事やっています • 機能改修、処理の共通・統合化 • 実装側のセキュリティに関わるあれこれ • コードレビュー、教導 • PHPのバージョンアップ ©︎ 2018 PRECS Inc.
どこのひと? 株式会社 • PRECS(プレックス) ©︎ 2018 PRECS Inc.
PHPのバージョンアップ ©︎ 2018 PRECS Inc.
PHPのバージョンアップとは言うが、何をするの? 1. PHPバージョンをなるだけ新しくする 現在のバージョンは5.3.3 計画策定時では5.6.X 最終的に7.2.6 or Upper 2. PHPのバージョンを上げても動くようにする
PHP5.3.3が全盛、あるいはそれ以前からのコードを多数収録 当然の事ながらWarningでログが肥大化し、Fatalで止まります 兎に角辻褄を合わせる事が肝要 3. 更新後のコードでも現行環境で動くようにする オンプレサーバが200台近くあり、それぞれ別のお客様向けです (お安いプランになると共有サーバとしても振舞う) そのため逐次更新が必要となります 結果、数週間の間PHP7とPHP5の実行系が平行する事になります ©︎ 2018 PRECS Inc.
おしながき 1. つらい現実 2. 後悔したこと 3. やるべき鉄板作業 4. 稀によく見る対応パターン抜粋 5.
夏への扉 ©︎ 2018 PRECS Inc.
つらい現実 ©︎ 2018 PRECS Inc.
基底現実の案件は、どうしてこんなにつらくきびしいのだろう…。 1. 自動テスト、ナシ 現在平行して作成中 2. composer、ナシ 5.3.3ですしね 3. ローカル仮想環境、ナシ ほぼフルオートビルドシェルはあるのだが名前解決の都合上
共用開発サーバ上の個人開発環境でやるしかない 破壊的テストはで き ま せ ん 4. ペアプログラマー、ナシ そんなに人回せないしね(但し、レビュー、テストの支援はある 5. 洋ナシ 実用中のPEARライブラリが複数存在する ©︎ 2018 PRECS Inc.
後悔したこと ©︎ 2018 PRECS Inc.
私公開後悔コーカイ中♪ 1. テンプレートエンジン 先に最終的バージョンをメジャーの中で最新にするべきでした ある意味動作確認が取れているため、心理的な負担が減る (そのまま動くとは言っていない) 2. ライブラリの廃棄、差し替え 時間が無かったため、PEARをモダンな物に差し替える事が 出来ませんでした
どちらにせよcomposer使えないので出来る事は限られていたが 3. 自動テスト可能な状況の用意 特に旧環境、新環境での同一のデータの用意が出来ませんでした とはいえパターンが複雑すぎてどちらにせよ間に合わなかったが ©︎ 2018 PRECS Inc.
やるべき鉄板作業 ©︎ 2018 PRECS Inc.
やるべき鉄板作業 静的解析 1. phpcsを使いましょう。 但し5.3.3で動くバージョンでは7.2系の解析が出来ないため、 一時的に7.2.Xが動く環境を用意する必要があります 次のコマンドで概要(txt)と詳細(csv)を得られます ©︎ 2018 PRECS
Inc. ./vendor/bin/phpcs -p -d memory_limit=512M --standard=PHPCompatibility ¥ --parallel=10 ¥ --runtime-set testVersion '7.2' ¥ --ignore=*.js,*.css,*/cache/*,*/public/* ¥ --report-csv=report-detail72.csv ¥ --report-summary=report72.txt ¥ /path_to_output_dir
やるべき鉄板作業 概要(各ファイルごとのError、Warning数) 詳細(どのファイルのどの行にどんなエラーがあるか) ©︎ 2018 PRECS Inc.
やるべき鉄板作業 grep 2. phpcsでは文字通りの静的解析しか行えないため、動的関数など には対応できません そのため、ereg*関数などならば、"ereg"としてかなり緩い 条件で検索するなどして、動的に構築されている箇所が無いか 調べる必要があります この場合、EclipseのCtrl+Hでの全体検索が便利です 検索結果からDeleteキーで不要な
結果を非表示に出来るため、 絞り込みが簡単になります ©︎ 2018 PRECS Inc.
やるべき鉄板作業 3. grep(その2) preg_replace関数で使える"e"修飾 PHP7.0.0で削除されたため、必ず除去する必要があります 残っているとfatalで止まります そのため、"preg"で一回、"replace"で一回、などで入念に 調査を行う必要があります なお、第一引数である$patternは文字列として加工されるケース があり、実際に次のコードのような凶悪なケースが存在するため、
一つ一つファイルを開いて読む必要がああります ©︎ 2018 PRECS Inc. $result = preg_replace($search .'e', $replacement, $subject);
やるべき鉄板作業 4. 動作確認 静的解析で割りと良い感じの分量が検出され、ツールに対する 安心感も出来るため油断しがちになりますが、動作確認は意識的 に行う必要があります 事実上の全数確認となります 可能ならば自動テストが用意されているべきです また、現バージョン環境、新バージョン環境の二つでかつ、 同内容のDBを用意して、簡単に表示上の差分を確認できるよう
にした方が良いでしょう 自動テストによっては表示したHTMLを保存させて、diffを 取るとより簡単に確認を行えます ©︎ 2018 PRECS Inc.
やるべき鉄板作業 5. phpのini設定 環境変数、httpd.conf、.htaccess、php.ini、PHPオプション/情 報関数の使用箇所を全て洗い出して確認する必要があります 昨今では環境変数を使う機会も多いため、コードの追跡のみでは 検知出来ない事が多いです php.ini以外の設定ファイルやコード上(しかも文字列操作付) の設定も見落としがちです 例によって"緩い条件"でgrepをするべきです
なお、ここが一番エグいのですが、廃止された設定を参照、設定 した場合、容赦なくfatalで落ちます ©︎ 2018 PRECS Inc.
やるべき鉄板作業 6. セッションの仕様変更対応 先のphp.ini設定の話と重複しますが、PHP7.2.0よりセッション の設定内容が大幅に変わります 例によって廃止済みの内容を設定、参照していると即死するため 修正、リリース時には注意が必要です ©︎ 2018 PRECS
Inc.
やるべき鉄板作業 コーディングルール 7. 適用 可能ならばPSR-2などでコードフォーマットを統一する事を お薦めします 今回の弊社のケースでは運よく対応を開始していたため、 差分検出などが容易でした 特にSmartyなどの外部ライブラリと比較する場合は、 Smarty側も併せてコードフォーマットを統一させ、差分を検出
すると大幅な楽が出来ます 今回は次のコマンドでフォーマットを行いました php-cs-fixerの場合、PHPの構文解析器を用いて解析、再展開を 行うため、安心して使用する事が出来ます ©︎ 2018 PRECS Inc. php-cs-fixer fix --level=psr2 /path_to_directory
やるべき鉄板作業 なお、次の警告が存在する場合、php-cs-fixerは動作しません 『【warning】Assigning the return value of new by reference
is deprecated in PHP 5.3』 その為、まず先にリファレンス渡しを行っている箇所の見直しと 修正が必要となります PHP5以降ではほぼリファレンス渡しを使う機会は無いので、 このタイミングに始末してしまいましょう リファレンスの設定の仕方によっては絶対に修正出来ないケース もあるため、注意して作業しましょう ちなみに次の正規表現で9割は対象を検知できます ©︎ 2018 PRECS Inc. /=[ ¥t]*&/
やるべき鉄板作業 8. 不要ファイルの除去 このタイミングで使わないファイルは削除してしまいましょう 残しておくと、phpcsを実行するたびに検知され、作業効率が 悪化します また手作業で除外する場合、同じような繰り返し作業となるため そのうち慣れから事故になります ©︎ 2018
PRECS Inc.
やるべき鉄板作業 9. もしもMySQL関数を使っていた場合 MySQL関数は使えなくなり、MySQLi関数を使う事になります 対象の環境でMySQLi関数が使えるかどうか、ダメならば使える 準備を行う必要があります もしも不幸な事にPEAR DBを使用していた場合は、MySQLi用の ドライバをMySQLドライバに移植するのが手っ取り早いです 副次的な効果としてDBアクセスが爆速になります
©︎ 2018 PRECS Inc.
稀によく見る対応パターン抜粋 ©︎ 2018 PRECS Inc.
稀によく見る対応パターン HTTP_SERVER_VARS 1. $HTTP_RAW_POST_DATA $GLOBALS['HTTP_RAW_POST_DATA'] $GLOBALS['HTTP_SERVER_VARS'] $GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME'] など 次のコードのようなコードがあるためgrep必須です ©︎
2018 PRECS Inc. $_globals_map = array( 'g' => 'HTTP_GET_VARS', 'p' => 'HTTP_POST_VARS', 'c' => 'HTTP_COOKIE_VARS', 's' => 'HTTP_SERVER_VARS', 'e' => 'HTTP_ENV_VARS' ); $GLOBALS[$_globals_map[$_c];
稀によく見る対応パターン 2. メソッドの引数の数 親クラスと子クラスで引数が異なるとPHP7.2.5において警告 引数の数が完全に一致し、デフォルト引数の有無、型まで 見られます ©︎ 2018 PRECS Inc.
$not_enough_args_count = 2- func_num_args(); if ($not_enough_args_count > 0) { throw new ¥ArgumentCountError(sprintf('Too few arguments to function %s(), %s passed', __METHOD__, $not_enough_args_count)); } $args = func_get_args(); $payment_total = $args[0]; $payment_class = $args[1]; $split_count = array_key_exists(2, $args) ? $args[2] : null; $use_3dsecure_flg = array_key_exists(3, $args) ? $args[3] : null;
稀によく見る対応パターン count 3. 関数に渡す値の型 PHP7.2.0よりarrayまたはカウンタブルインスタンス以外を 渡すと警告されます テンプレートエンジンで問題になるケースが多いため、 注意が必要です ©︎ 2018
PRECS Inc. function old_count($value) { if (is_array($value)) { return count($value); } return is_null($value) ? 0 : 1; }
稀によく見る対応パターン 4. session関連の処理 session_cache_limiterなど、http response headerを出力する 処理がある場合に注意が必要です 古い処理系の場合、セッション開始タイミングが早すぎて header出力できない場合があります(しかもob使えない) また、session.save_handlerがuserの場合に注意が必要
session read時に値が無い場合の返り値は空文字です 空文字以外(例えば、null)などを返している場合は 事前に修正が必要です ©︎ 2018 PRECS Inc.
稀によく見る対応パターン 代数演算 5. での型の取り扱い 文字列型の変数を直接代数演算する場合に警告されます これは静的解析では発見できません なお、「本当にintでいいのか」などの確認が必要です ©︎ 2018 PRECS
Inc. $price = 100; $count = ''; $total_price = $price * $count; // 警告 次のようにする必要がある $price = 100; $count = (int) ''; $total_price = $price * $count;
稀によく見る対応パターン 6. 改行コード、PHPとしておかしいファイル PHPのコード上で改行コードが不統一である場合や、 画像や.htaccessをなぜか.phpとしているファイルがある場合、 phpcsは警告します PHPコード上での改行コード不統一はIDEを使えば一瞬ですが、 画像などの場合は意図が不明なため、慎重に対応する必要が あります 最悪、対象のファイルをリネームし、それをincludeするだけの
ファイルを用意すればよいのですが・・・ ©︎ 2018 PRECS Inc.
稀によく見る対応パターン 7. mb_convert_variablesのバグ 第二引数に複数のencodingを指定し、第三引数が多次元の場合 に正しく動作しなくなるバグ PHP7.2.6時点でまだ直ってません 次のような割と非効率な処理に差し替える必要があります ©︎ 2018 PRECS
Inc. - mb_convert_variables('UTF-8', 'UTF-8,SJIS,SJIS-win', $param); + array_walk_recursive($param, function (&$item, $key) { + $item = mb_convert_encoding($item, 'UTF-8', 'UTF-8,SJIS,SJIS-win'); +});
稀によく見る対応パターン 8. each eachは廃止されます 次のような単純なケースの場合は良いのですが・・・ ©︎ 2018 PRECS Inc. -
while (list($name, $value) = each($_POST)) { + foreach ($_POST as $name => $value) {
稀によく見る対応パターン 次のようにトラバーサブルな振る舞いを行っているクラスなどの 場合は配列の内部ポインタを意識した修正を求められます ©︎ 2018 PRECS Inc. - $child =
each($this->children); - if ($child) { - return $child['value']; -} else { - reset($this->children); - return false; -} + if (is_null(key($this->children))) { + reset($this->children); + return false; +} + $value = current($this->children); + next($this->children); + return $value;
夏への扉 ©︎ 2018 PRECS Inc.
1分の1の確率で成功 composer 1. 導入 今までの環境ではnamespaceは導入されていませんでした 全部グローバルにある環境でも、次のcomposer設定を使えば なんとかなるかもしれません ©︎ 2018 PRECS
Inc. { "name" : "precs/rpst", "description" : "The NG Precs Cart.", "type" : "project", "autoload" : { "psr-4" : { "App¥¥rpst¥¥": "./", // 今後新しく作るApp用 "": "./" // 既存のApp用 } }, }
未来への片道切符 2. useの導入 当然の事ですが現状はrequire地獄です 先のcomposer導入でrequireを段階的にkillし、useに置き換えます この場合ありがちなのが複数のroot requireがある事 この場合、先行してroot requireの先頭に全てのroot require
から呼ばれるrequireファイルを設定しておきます 後はcomposer対応がうまくいったら、そのファイルにautoload 呼び出しを追加しておしまい、とできます 3. composer経由でのライブラリの導入 PEARライブラリをモダンな最近のものに差し替える 併せて既存環境と同居出来る類のフレームワーク (例えば、Flywheel2)を導入し、開発効率を上げるのです ©︎ 2018 PRECS Inc.