PHPを読むことを諦める瞬間
昔のPHPのコードはなぜか読みにくい。
Laravelが出る前の「フレームワーク乱立」が原因の1つではあるんですが、
それ以外に、
「これって、このフレームワーク独自の書き方なのか…?」と思ったら、
コーディング規約が(ない・古い・ゆるい)だけだったりします。
「僕の知ってるPHPじゃない」が結構ある
Laravel とか Symfony を見た後に、それ以外のフレームワークを見ると
抽象化されてないので、native な PHP という印象を受ける事があります。
知らないPHPフレームワークのコードをいざ読む時、
まず何からやったら良いのか、わからなくないですか?
例えば、こんな感じのPHPが書かれてるとします。
例文
$param = [':user_id' => Yii::$app-> users -> user_id];
$query = "SELECT COUNT(*) FROM user_log WHERE mid = :user_id";
$count = Yii::$app->db_component->createCommand($query, $param)->queryScalar() ?: 0;
3行くらいならまだ読めるんですが、これが100行続いてると
「もう読めない」となってきます。そういう時の、地道な解決策です。
(1)とにかくバラしてみる
メソッドチェーンも、コンポーネントを変数に代入しておくと、読んで理解できます。
三項演算子も、わざわざ省略しないで書いてみました。
$userComponent = Yii::$app->users;
$userId = $userComponent->user_id;
$param = [':user_id' => $userId];
$query = "SELECT COUNT(*) FROM user_log WHERE mid = :user_id";
$dbComponent = Yii::$app->db_component;
$command = $dbComponent->createCommand($query, $param);
$count = $command->queryScalar();
$count = ($count !== null && $count !== false) ? $count : 0;
(2)とにかく改行する
配列の代入がわかりますし、SQLもっと長い場合適切に改行することでSQLが読めるようになります。
$userComponent = Yii::$app->users;
$userId = $userComponent->user_id;
$param = [
':user_id' => $userId
];
$query = "
SELECT
COUNT(*)
FROM
user_log
WHERE
user_id = :user_id
";
$dbComponent = Yii::$app->db_component;
$command = $dbComponent->createCommand($query, $param);
$count = $command->queryScalar();
$count = ($count !== null && $count !== false) ? $count : 0;
(3)とにかく説明を書いてみる
データ型もちゃんと分かるように書いてみる。
/** @var UserComponent $userComponent */
$userComponent = Yii::$app->users;
/** @var int|string|null $userId */
$userId = $userComponent->user_id;
// パラメータを個別に変数へ
$param = [
':user_id' => $userId
];
// SQLクエリを作成、確認しやすいようにフォーマット
$query = "
SELECT
COUNT(*)
FROM
user_log
WHERE
user_id = :user_id
";
// DBコンポーネントを取得し変数に代入
/** @var DbComponent $dbComponent データベースコンポーネントインスタンス */
$dbComponent = Yii::$app->db_component;
// createCommandメソッドを使ってコマンドを作成
/** @var \yii\db\Command $command SQLコマンドオブジェクト */
$command = $dbComponent->createCommand($query, $param);
// queryScalarメソッドの結果を取得し、nullをチェックして0をデフォルトに設定
/** @var int|string|false|null $count COUNT結果の型 */
$count = $command->queryScalar();
$count = ($count !== null && $count !== false) ? (int)$count : 0;
(4)ORMに変換してみる
ORMに慣れてる人であれば、ORMで書き直したほうがわかりやすい。
どうやらこのフレームワークには、Eloquent的なライブラリがあるらしい。
use app\models\UserLog;
$userComponent = Yii::$app->users;
$userId = $userComponent->user_id;
$count = UserLog::find()
->where(['user_id' => $userId])
->count();
見比べてみよう
当初は、「これ $count
ってことは int
で返るよな…?」と半信半疑でしたが
$count = Yii::$app->db_component->createCommand($query, $param)->queryScalar() ?: 0;
説明を付けることで int
で返っている事が、わかりますし
// queryScalarメソッドの結果を取得し、nullをチェックして0をデフォルトに設定
/** @var int|string|false|null $count COUNT結果の型 */
$count = $command->queryScalar();
$count = ($count !== null && $count !== false) ? (int)$count : 0;
ORMの方が何をやってるのか分かりやすい、気がします。
$count = UserLog::find()
->where(['user_id' => $userId])
->count();
理解できたら、書き直せる範囲で書き直す
もし書き直して良ければ書き直します。
古い書き方
$param = [':user_id' => Yii::$app-> users -> user_id];
$query = "SELECT COUNT(*) FROM user_log WHERE user_id = :user_id";
$count = Yii::$app->db_component->createCommand($query, $param)->queryScalar() ?: 0;
Yii の Active Record
use app\models\UserLog;
$userId = Yii::$app->users->user_id;
$count = UserLog::find()->where(['user_id' => $userId])->count() ?: 0;
もしも Laravel の Eloquent に置き換えるとしたらこうなる。
use App\Models\UserLog;
$userId = auth()->user()->id;
$count = UserLog::where('user_id', $userId)->count() ?: 0;
結論
今更 Laravel に置き換えるのかどうかは別として、昔の古いPHPのコードは読んでみたら
実は、ほとんど今とやってる事は変わってない事がわかります。
「ちゃんとチューニングしてある」っていう見方もあるんですが、
コードを読み解く工夫が必要な時点で、開発体験が悪くなるので、
こまめなアップデート、もしくは大胆なリプレイスが必要と、個人的には考えています。