Laravelで定数を使うときにConfigを使う腰抜けはもう死んだ
はじめに
どうも、チキンと呼ばれたらキレる系プログラマーのあおいくんだよ。
みんなはLaravelで定数使うときどうしてる?
僕は数ヶ月前までconfig配下にconst.phpとか作ってそこにバカスカ定義する腰抜けだったんだよね。
でも、そんな腰抜けは背後からナイフで一発、もう死んじまったって噂だよ。
今回はみんながそうならないためにLaravelで定数を定義するときのよりよい方法を紹介するよ。
環境
PHP:7.4系
Laravel:7.x系
config.phpに定義してた腰抜け時代
まるでそれがベストプラクティスかのように世の中に流布されている定数の定義方法として「config/const.phpにバカスカ定義する」ってやつがあるじゃん。
僕もアレに騙されてた腰抜けの一人だったわけ。
<?php
return [
~~~他の記述~~~
// キラメイジャーのメンバー
'Kirameiger' => [
'KIRAMEI_RED' => 1,
'KIRAMEI_YELLOW' => 2,
'KIRAMEI_GREEN' => 3,
'KIRAMEI_BLUE' => 4,
'KIRAMEI_PINK' => 5,
'KIRAMEI_SILVER' => 6,
'MEMBER_LIST' => [
'キラメイレッド' => 1,
'キラメイイエロー' => 2,
'キラメイグリーン' => 3,
'キラメイブルー' => 4,
'キラメイピンク' => 5,
'キラメイシルバー' => 6,
],
],
~~~他の記述~~~
];
これってとりあえず定義はできるけど、冷静に見たらこれはないんじゃないかなってのがなんとなく伝わってくると思うの。
僕が思うにイケてないポイントは少なくとも2つあると思うんだよね。
-
ファイルがめっちゃ長くなる
今はキラメイジャーだけだけど、例えば45戦隊シリーズ全部定義しようって思ったら、このファイルの中に45戦隊分全部定義することになって、そうすると900行くらいのファイルになっちゃうよね。
めちゃめちゃに長いファイルはめちゃめちゃ見通しが悪くなるし、正直全然イケてないよね🤷♂️ -
変更に弱い
これ、例えばやっぱ番号0からふるようにしましょうってなったとするよ。
そしたらそれぞれを定義しているところとメンバーの配列を定義してるとこの2箇所をいじらなきゃいけなくなるよね。
そうなるとうっかり変更を忘れちゃってメンバーの配列のキラメイレッドは1番始まりのままになってるとかいうことが起こりかねないよね🤷♂️
ちなみに表で呼び出すときは
@foreach (config('const.Kirameiger.MEMBER_LIST') as $name => $number)
<p>{{ $name }} => {{ $number }}</p>
@endforeach
みたいな呼び出しになるよ。まぁまぁの見た目だね。
Configの中で用途ごとに個々に分けてた腰抜け時代
バカデカファイルにうんざりした腰抜けは、「用途ごとにファイル分けたらいいんぢゃね?マジで天才ぢゃん😁」って思ったのよ。
つまりconfig/consts/kirameiger.php
にしてみたわけ。新しい戦隊が放送開始したらconfig/consts/zenkaiger.php
とかも作るわけよ。
これ前述の①は解決できると思うんだけど、結局②が残るよね。
そうなるとこれも結局あんまいい方法じゃないって腰抜けが気づくまでに数ヶ月かかったんだよね🤷♂️
そして辿り着いた定数クラスを作る時代
そんじゃあ、これどうすればいいんだよって話。
答えは簡単、app配下にConstsフォルダを作るんだよね。
その中で定数として定義して呼び出して上げればよかったんだよね。
<?php
namespace App\Consts;
// usersで使う定数
class KirameigerConsts
{
// キラメイジャーのメンバー
public const KIRAMEI_RED = 1;
public const KIRAMEI_YELLOW = 2;
public const KIRAMEI_GREEN = 3;
public const KIRAMEI_BLUE = 4;
public const KIRAMEI_PINK = 5;
public const KIRAMEI_SILVER = 6;
public const MEMBER_LIST = [
'キラメイレッド' => self::KIRAMEI_RED,
'キラメイイエロー' => self::KIRAMEI_YELLOW,
'キラメイグリーン' => self::KIRAMEI_GREEN,
'キラメイブルー' => self::KIRAMEI_BLUE,
'キラメイピンク' => self::KIRAMEI_PINK,
'キラメイシルバー' => self::KIRAMEI_SILVER,
];
}
よくない?見た目もよくない?イケてない?そうでもない?
これならファットなファイルを作らずに済むし、自分の中で定義した定数を使えるからこちゃこちゃした配列とかを定義しても変更漏れとかの問題なくない?
ちなみに表で呼び出すときは
@foreach (App\Consts\KirameigerConsts::MEMBER_LIST as $name => $number)
<p>{{ $name }} => {{ $number }}</p>
@endforeach
みたいな呼び出しになるよ。まぁまぁいいんじゃないかな。
でも、呼び出しちょっと長くない?って思うよね。僕も思う。
そういう人はapp.php
にaliasを設定してあげれば
<?php
return [
~~~いろんな記述~~~
'aliases' => [
~~~いろんな記述~~~
'KirameigerConsts' => App\Consts\KirameigerConsts::class,
],
];
とか記述してあげれば
@foreach (KirameigerConsts::MEMBER_LIST as $name => $number)
<p>{{ $name }} => {{ $number }}</p>
@endforeach
みたいな呼び出せるようになるよ。スマートになるね。
おわりに
いまのところこれが一番しっくりきてるやり方だよ。
正直aliasを登録するのもなんかちまちましててめんどくさすぎるから、実は一気に解決できる方法があるんじゃないかとは疑ってるよ。
もし知ってる人いたら出し渋らずに教えてくれよな👋
Discussion
何も考えたくない場合はconst.phpを使っています(笑)
ちなみに、enum(laravel-enumとか)を使うのはいかがでしょうか?
正直開発メンバーみんなでルール守れてたら何をどこに定義しててもいいと思います!
laravel-enumは使ったことないんでいろいろ言えないんですけど、ドキュメント見た感じもしかしたらenumの方がイケてるのか…?
使用感としてConstsから呼び出すのとここが違うみたいなのあったら知りたいです
例えば、 Gender::getKey(1); で 「男性」を取得したり、 Gender::getValue("男性")で「1」を取得したりできるのですが、 Gender::asSelectArray(); で 下記のように取得できます
これはフロント側でプルダウンの選択肢を動的に変えたい場合に、Gender::asSelectArrayの結果をフロントにわたしてあげれば、簡単にセレクトボックスに値を渡せます。
みたいな便利さもあれば、
constを使うより視覚的に優しい(
Gender::getKey(1)
って性別の値が「1」を取得してるんだなって分かりやすい)とかもあると思います !ありがとうございます🙇♂️
指摘してもらった件ですけど、functionやarrayの定義ができるのでConstsの運用でも一応同様の処理は可能だと思われます。
Gender::getKey(1)
の呼び出し方は視覚的には優しいんですけど、保守性どうなんだ問題があるかなって思います。100箇所にその呼出があったら100箇所修正するのか、とか。const使うメリットは
だと思うので、const定義した上でマジックナンバー使っちゃうと、本当か?🤔な気持ちに個人的にはなりますね。
僕もちょうどこの方法に行き着いたところでした!
僕の場合はModel(=テーブル)に関連する定数はModelのプロパティで管理して(privateも使えるので)、
逆にModelに紐づかない都道府県や性別などの定数をこの記事の定数クラスを作るやり方でやっています!
config/app.php
のように環境毎に定数をenv()
ヘルパから読み出して設定したい場合、この方法だと定数クラスの中でenv()
ヘルパを使うことになりますが Laravel のドキュメントはphp artisan config:cache
が実行された場合 config ディレクトリ以外で実行されるenv()
が常にnullを返す事を警告していますから、どのみちconfig/const.php
の利用は避けられないように見えます。そもそもPHPの配列は Ordered map とされているので、キラメイジャーの例ではマジックナンバーを振る必要性を感じませんでした。
これで記事の懸念点はすべて消えているように思うのですが。