【laravel】初心者エンジニアの黒歴史

:::note warn
エンジニア初心者の投稿であるため、間違っている箇所が多くあるかと思います。
間違っているなどあればご教授いただけると幸いです。
:::

# はじめに
エンジニア最初の実務ということで、日報投稿サイトの実装を行っていました。チケットごとにレビューをいただいていたのですが、あまりにもしょぼいミスを連発しているので、記事にアウトプットすることで定着させたいと思いました。

エンジニアとして活躍されている方から見ると「なんでそんなミスするの」と思われる内容ばかりなので、温かい目で見守っていただけたらと思います。

# 黒歴史
<br>

## 抽象性が高いmodel・view・contoller名を設定しない

- 前提条件
毎日投稿する日報を保持するMVCの作成中

```php
//悪い例
Model名     : Report.php
View名      : Report.blade.php
Contoller名 : ReportConntoller.php 

//良い例
Model名     : DailyReport.php
View名      : DailyReport.blade.php
Contoller名 : DailyReportConntoller.php
```

日報は毎日(daily)で投稿する記録(report)なので、「dailyReport」にした方が具体性が増す。
「Report」のみだとさらに機能が追加されたときに利用する可能性が出てくるので良くない。

## バリテーションルールの使い方を確認

前提条件
バリテーションルールで最大文字数を指定したい。

```php
//悪い例
'title.max' => '30文字以内で入力してください。'

//良い例
'title.max' => ':max文字以内で入力してください。'
```

バリテーションの機能を利用することで二重管理が必要なくなり、修正漏れ等を防ぐことができる。

## バリテーションルールの使い方　その②

前提条件
バリテーションエラーの発生時の表示文章の定義をしたい

```php
//悪い例
'created_at.required' => '入力必須の項目です。',
'created_at.before_or_equal' => '今日以前の日付を選択してください。',
'title.required' => '入力必須の項目です。',
'title.max' => ':max以内で入力してください。',
'content.required' => '入力必須の項目です。',
'content.max' => ':max以内で入力してください。',

//良い例
'required' => '入力必須の項目です。',
'created_at' => '今日以前の日付を選択してください。',
'max' => ':max以内で入力してください。',
```

文言が同じものに関してはまとめて記載することができる。特殊な例があるときのみピリオドで場合わけをする。

## modelの命名規則の確認をする。

前提条件
DailyReportに結びつくmigrateファイルを作成したい。

```php
//悪い例
Model名   : DailyReport.php 
migrate名 : php artisan make:migrate DailyReport

//良い例
Model名   : DailyReport.php 
migrate名 : php artisan make:migrate DailyReports
```

modelとmigrateの表の名前はそれぞれ命名方として「テーブル名を複数形にして命名する」にする慣習がある。modelとmigrateの命名方を正しく行うと対応しているテーブルを自動的に探して、結びつけてくれる。

下のコードのように本来はmodelクラス内で対応するテーブル名を記載する必要があるが、結びつけることで記載する必要がなくなる。

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    // 本来はここに対応させるテーブル名記載する
    protected $table = 'UserList';
}
```

## ディレクティブの知識をつける

前提条件
バリテーションエラー時にメッセージを表示したい。

```php
//悪い例
@if($errors->has('content'))
	<span>{{ $message }}</span>
@endif

//良い例
@error('contet')
	<span>{{ $message }}</span>
@enderror
```

ifディレクティブでも正しく処理は行われるが、errorディレクティブを使用する方が簡潔にコードを書くことができる。
ディレクティブについて調べてみると他にも便利な機能がたくさんあるので調べたいと思う。

https://readouble.com/laravel/8.x/ja/blade.html

## Formファサードの使用

前提条件
formタグを利用してhttpメソッドのPOSTを行いたい。

```php
//悪い例
<form method="POST" action="{{ route('report.store', $dailyReport->id) }}">

//良い例
{{ Form::open(['route' => ['report.store', $dailyReport->id]]) }}
	//
{{ Form::close() }}
```

Formファサードを使用した時の方が圧倒的にコードが見やすい。また、methodプロパティも標準でPOSTに指定されていたり、@csrf（脆弱性対策）を書く必要もない。

FormファサードはFromタグ以外も対応しており、どれも使わない場合と比べて使い勝手がいいので利用したい。

:::note info
非常にわかりやすく書かれているサイト

[Formファサード忘備録 - OVERS](https://overs.zigexn.co.jp/technology/tech/8200/)
:::


## プルリクするときはチケットで記載がある箇所のみ変更し、無駄な変更はしない。

前提条件
チケットのレビューをお願いしたい。

git pushでリモートリポジトリにコードをあげたときに『Files Changed』を確認する。新たに追加した箇所が表示されるので、今回のチケットに関係ない箇所が変更されている場合は元に戻して、修正箇所として表示されないようにする。

レビューの際は必要箇所のみを確認するため、無駄なファイルの変更箇所があると確認のさいに非常に見にくくなってしまう。

## コーディング規約を意識した変数名を作る

前提条件
id検索をして取得できたデータを変数に格納したい。

```php
コーディング規約
今回の開発ではローワキャメルンケースで変数名を作成する

//悪い例
$serach_id

//良い例
$serachId
```

当たり前のことだが私は間違ってしまっていたため書く。命名規則にはいくつか種類があるが規約を確認してコーディングするようにすることが大切。

:::note info
命名規約についてまとめてくれている記事を見つけたので、貼っておきます。

[命名規則についてまとめてみた（キャメルケース，パスカルケース，スネークケース，ケバブケース） - Qiita](https://qiita.com/shota0616/items/4ac7a8696b3f6ccbe2bc)
:::


## 英単語を理解する

前提条件
データを格納するための変数を作成したい。

```php
//悪い例
$date

//良い例
$data
```

これは英語力の問題だと思うが、友人も間違っていたので間違える人が一定数いる。変数名をつける際は英単語の意味を調べながらつけたい。

## 不要なコメントを削除する

前提条件
リファクタリングをするときに変更前と動作を確認しながら行いたい。

```php
//<form method="POST" action="{{ route('report.store', $dailyReport->id) }}">//
{{ Form::open(['route' => ['report.store', $dailyReport->id]]) }}
```

正しく動作するかを確認するためにコードを残してしまい、そのまま消し忘れてしまう。不要なコメントはデッドコードと言って、可読性を下げる要因になってしまう。使用後は必ず消す。

## 不要な空白を削除する

不要な空白を削除し忘れてしまう場合がある。

git pushでリモートリポジトリにコードをあげたときに『Files Changed』を確認する。ここで確認すると不自然に間が空いてることを色をつけて教えてくれる。vscode上で確認するのも当然だが、このgithubの機能もうまく利用したい。


## view内のコードの記述を簡潔にする

前提条件
whereを使用して特定のデータを呼び出し、blade.phpで利用したい。

```php
//悪い例
<span class="point-color">{{ $dailyReport->comment->where('dailyReport_id', $dailyReport->id)->count() }}</span>

//良い例
<span class="point-color">{{ $dailyReport->comment->count() }}</span>
```

where() などの DB 操作を伴うロジックをview内に書かない方がよい。他の箇所で長いDB操作の記述が書かれてしまう可能性もあり、保守性に問題が出てくる。

なるべくController でコメント数を取得するロジックを記載して、view で表示するという流れにすることが大事

## 変数の付け方

前提条件
記録を取った年月を格納する変数を作成したい。

```php
//悪い例
$day = '2024-01'

//良い例
$reportingTime ='2024-01'
```

serachDayにしてしまうと日付を格納する変数だと勘違いしてしまう可能性がある。また、変数を考えるときは格納する値がどんな値なのかを考えてから行う必要がある。

## whenメソッドの使用方法

前提条件
whenメソッドを用いて場合わけをしたい。

```php
//悪い例
$dailyReports = $this->dailyReport
	->when(条件, function ($query, その他利用したい引数) {
		//行いたい処理
	})

//良い例
$dailyReports = $this->dailyReport
	->when(条件, function ($query) use (その他利用したい引数) {
	  //行いたい処理
  })
```

書き方が変わるだけで視覚的にわかりやすいコードになる。今回はwhenの内部で渡される引数とクライアントが渡す引数を分けることで可読性を高める。

## laravelのメソッドを活用する
前提条件
データが存在しないときに404のエラー文を表示したい。

```php
 //悪い例
 if ($dailyReport === null) {
	 abort(404);
	};
	
//良い例
$dailyReport = $this->dailyReport->findOrFail($id);
```

laravelのメソッドには便利な機能がたくさんある。findOrFailメソッドを使用するだけで、もし存在しない場合にエラー画面を表示してくれる。

## パラメータ名と変数名を一致させる

前提条件
httpメソッドのPOSTでバラメータ名search_wordを受け取り、変数に格納したい。

```php
//悪い例
$searchTitle = $request->input('search_word');

//良い例
$searchWord = $request->input('search_word');
```

パラメータ名と変数名を変更することにメリットはないのでどちらも同じ名前にする。下手に変更すると可読性が低くなってしまう可能性がある。

## ファイルのパスを書く場所での名前を揃える

```php
//悪い例
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\User\Request;
use App\Models\DailyReport;
use App\Models\Comment;
use Illuminate\Support\Facades\Auth;

//良い例
use App\Http\Controllers\Controller;
use App\Http\Requests\User\Request;
use App\Models\DailyReport;
use App\Models\Comment;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
```

ファイルパスを設定する箇所の順番がバラバラだと見ていて気持ちが悪い。名前の順番に揃えることで見た目も良くなる。


:::note info
useに関しては使用する際に以下の手順を踏むことでパスを自動で入力してくれる。
コード内で使用するクラスを指定し、予測変換で入力すると自動でuseを追加してくれる。
:::



## インデントを正しく空ける

```php
//悪い例
$this->comment
->fill($inputs)
->save();

//良い例
$this->comment
  ->fill($inputs)
  ->save();
```

インデント忘れが目立つ。特にメソッドチェーンの使用時にインデントを開けることを忘れないようにする。

## 処理を実行する箇所を考える

前提条件
コメントを表示をするときに作成日の降順に表示する処理を加えたい。

modelメソッドに直接並び替えのメソッドを加えている。

```php
//悪い例
class DailyReport extends Model
{
    public function comments()
    {
        return $this->hasMany(Comment::class)
        ->orderBy('created_at', 'desc');
    }
}
```

blade.phpファイル内で並び替えのメソッドを加えている。

```php
//良い例
@foreach($question->comments->sortByDesc('created_at') as $comment)
	//処理
@endforeach
```

悪い例ではcreated_at の降順で取得する必要ないところでは無駄なクエリの実行をしてしまう。並び替えのメソッドなどは必要がある箇所でのみ使うことで無駄を減らすことができる。

## メソッド名の付け方を明確にする

前提条件
コメントを新規作成するためのメソッドを作成したい。

```php
//悪い例
public function comment()
{
	//処理
}

//良い例
public function storeComment()
{
	//処理
}
```

commentだけだとコメントに対して何をする処理なのかがよくわからない。どんな処理が起きるのかが一目で理解できるように名前をつけることで可読性が高まる。

## プロパティ名の記載はメソッドより上にする

```php
//悪い例
class DailyReport extends Model
{
    use SoftDeletes;
    
      public function comments()
    {
	    //処理
    }

    protected $fillable = [
			//プロパティ
    ];  
}
```

```php
//悪い例
class DailyReport extends Model
{
    use SoftDeletes;
    
    protected $fillable = [
			//なにかしらの内容
    ];  
    
      public function comments()
    {
	    //処理
    }
}
```

クラス内でコードを書くときはプロパティを先にメソッドを後に書くことが慣習として決まっている。


# おわりに
ここまで読んでくださった猛者の方、ありがとうございました。
私と同じようなミスをしてレビューで指摘されないようになってもらえたら幸いです。

今回黒歴史を書くことで頭の中が整理できました。みなさんもぜひ自分の黒歴史をQiitaに投稿しましょう！