laravel6 マジックナンバーの使用を避ける

# 目的

- マジックナンバーの使用を避ける方法をまとめる。

# マジックナンバーって?

- 無職 やめ太郎さんのこちらの記事が非常にわかりやすい。
    - [Hurry Coderと魔法の数字](https://qiita.com/Yametaro/items/87130f961af294f75d60)
- 簡単に言うとソースコード内の分岐処理などで比較対象の数字をハードコーディングしてあること。
- 他の人が当該コードを読んだとき数値が直接記載されているとその数値がなんの数値化わからない。
- コメントを記載すれば良いかもしれないがステップ数が増えてしまう。
- ハードコーディングされている場所が複数箇所ある時、修正する際の手間もかかる。
- 結論あんまりいいこと無い。

# 環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.8 | Homebrewを用いてこちらの方法で導入→[Mac HomebrewでPHPをインストールする](https://qiita.com/miriwo/items/cd54077aad7e139cf518) |
| Laravel バージョン | 6.X | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

# 情報

- 筆者は環境に記載されている環境を直接Macに作成して本記事の動作確認を実施した。
- 各コマンドは特筆しない限り前のコマンドと同じディレクトリで実行するものとする。
- 下記のような仕様で機能が作成されているものとする。
    - ローカルサーバを起動して[http://127.0.0.1:8000/magic_number](http://127.0.0.1:8000/magic_number)にアクセスするとビューが表示される。
    - 当該ビューには変数`$user_type`に格納された値によって表示する内容を変更する処理がある。
    - `$user_type`に1が格納されていた場合「ようこそ管理者さん」と表示する。
    - `$user_type`に2が格納されていた場合「ようこそユーザーさん」と表示する。
    - `$user_type`に1と2以外が格納されていた場合「ようこそゲストさん」と表示する。
- 上記のビューを表示するまでのルーティングとコントローラーとビューの内容を下記に記載する。
    - ルーティング
    
        ```アプリ名ディレクトリ/routes/web.php
        <?php
        
        /*
        |--------------------------------------------------------------------------
        | Web Routes
        |--------------------------------------------------------------------------
        |
        | Here is where you can register web routes for your application. These
        | routes are loaded by the RouteServiceProvider within a group which
        | contains the "web" middleware group. Now create something great!
        |
        */
        
        Route::get('/', function () {
            return view('welcome');
        });
        
        Auth::routes();
        
        Route::get('/home', 'HomeController@index')->name('home');
        
        Route::get('/magic_number', 'MagicNumberController@index')->name('magic_number');
        ```

    - コントローラー（`$user_type = 1;`の部分もマジックナンバーとなっているが今回の検証をわかりやすくするために記載してある。）

        ```アプリ名ディレクトリ/app/Http/Controllers/MagicNumberController.php
        <?php
        
        namespace App\Http\Controllers;
        
        use Illuminate\Http\Request;
        
        class MagicNumberController extends Controller
        {
            public function index()
            {
                $user_type = 1;
                return view('magic_munbers.index', ['user_type' => $user_type]);
            }
        }
        ```

    - ビュー

        ```アプリ名ディレクトリ/resources/views/magic_munbers/index.blade.php
        <!DOCTYPE html>
        <html lang="ja">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta http-equiv="X-UA-Compatible" content="ie=edge">
            <title>マジックナンバー回避</title>
        </head>
        <body>
            <header></header>
            <main>
                @if ($user_type === 1)
                    <p>ようこそ管理者さん</p>
                @elseif ($user_type === 2)
                    <p>ようこそユーザーさん</p>
                @else
                    <p>ようこそゲストさん</p>
                @endif
            </main>
            <footer></footer>
        </body>
        </html>
        ```

- 上記の記載がなされた状態で[http://127.0.0.1:8000/magic_number](http://127.0.0.1:8000/magic_number)にアクセスすると下記のように表示される。

    画像

# マジックナンバーが使われているところ

- ビューファイルの記載に注目していただきたい。

    ```アプリ名ディレクトリ/resources/views/magic_munbers/index.blade.php
    <!DOCTYPE html>
    <html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>マジックナンバー回避</title>
    </head>
    <body>
        <header></header>
        <main>
            @if ($user_type === 1)
                <p>ようこそ管理者さん</p>
            @elseif ($user_type === 2)
                <p>ようこそユーザーさん</p>
            @else
                <p>ようこそゲストさん</p>
            @endif
        </main>
        <footer></footer>
    </body>
    </html>
    ```

- 先に記載したビューのコードの内部のifディレクティブの条件式部分に記載されている`$user_type =`のあとの数字がマジックナンバーである。

# マジックナンバーを回避しよう

- マジックナンバーの回避方法はいくつかあるが今回は専用の設定ファイルを用いることにする。
- アプリ名ディレクトリで下記コマンドを実行して専用の設定ファイルである「const.php」を作成して開く。

    ```terminal
    $ vi config/const.php
    ```

- 下記の内容を記載する。

    ```アプリ名ディレクトリ/config/const.php
    <?php
    
    return [
        'user_type' => [
            'admin' => 1,
            'user' => 2,
        ]
    ];
    ```

- 下記コマンドを実行してconfigキャッシュをクリアする。（自分へ: 設定系のファイルをいじったらこれを実行する癖をつける。）

    ```terminal
    $ php artisan config:cache
    ```

- ビューファイルの表示を切り分けている条件式部分を下記のように修正する。

    ```アプリ名ディレクトリ/views/magic_numbers/index.blade.php
    <!DOCTYPE html>
    <html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>マジックナンバー回避</title>
    </head>
    <body>
        <header></header>
        <main>
            @if ($user_type === config('const.user_type.admin'))
                <p>ようこそ管理者さん</p>
            @elseif ($user_type === config('const.user_type.user'))
                <p>ようこそユーザーさん</p>
            @else
                <p>ようこそゲストさん</p>
            @endif
            <p>{{ config('const.admin') }}</p>
        </main>
        <footer></footer>
    </body>
    </html>
    ```

- ローカルサーバを起動し[http://127.0.0.1:8000/magic_number](http://127.0.0.1:8000/magic_number)にアクセスし表示に変化がないことを確認した。
- コントローラーの`$user_type =`で指定している値を1や2、またはその他の値に変更しビューページを更新することで表示が切り替わることを確認する。

# ちょっとした解説

- `config('アプリ名ディレクトリ/configの直下の設定ファイル名.設定ファイルに記載された配列のキー')`のように記載することで設定ファイルの値を呼び出すことが可能である。
- 設定ファイルに基準となる値を記載していることにより、もし仮に管理者の値が3、ユーザーの値が5などに変更になっても修正箇所は設定ファイルのみで済む。
- ヘルパ関数である`config()`を用いる事によりbladeファイル内部でも気軽に呼び出せるため気を使わなくて良い。
    - [https://readouble.com/laravel/6.x/ja/helpers.html#method-config](https://readouble.com/laravel/6.x/ja/helpers.html#method-config)