15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel / PHP】研修期間に受けたコードレビューから学んだ事

Posted at

はじめに

今回が初投稿となります。
今回は、入社してから約1ヶ月間の研修で頂いたコードレビューから
アプリケーションを作る上で大切だと学んだことについてまとめたいと思います。
* 言語/フレームワークはLaravel(PHP)Vue(JavaScript)です。

1. コメント

誰が見てもわかりやすく書く

今回作成したSNSアプリケーションの中で、ログインユーザがフォローしているユーザリストを表示する画面を作成するために、以下のような手順を取りました。

1. フォロー関係を表すfollowerテーブルを作成

migrations/2023_02_01_xxxxxx_create_follower_table.php
public function up()
{
    Schema::create('follower', function (Blueprint $table) {
        $table->unsignedBigInteger('following_id')->nullable(false)->comment('フォローしているユーザID');
        $table->unsignedBigInteger('followed_id')->nullable(false)->comment('フォローされているユーザID');
    });
}

2. ログインユーザ自身がフォロー中のユーザを取得

Services/AccountService.php
public function getFollowings(int $userId)
{
    return Follower::select('followed_id')
                    ->where('following_id', $userId)
                    ->get();
}

3. 2で取得した値をコレクションメソッドpluckを使ってfollowed_id(フォローされているユーザid)のみを取り出す

Controllers/AccountController.php
$followings = $accountService->getFollowings(Auth::id());
$followingIds = collect($followings)->pluck("followed_id");

この時、取得した値をログインユーザの目線フォローしているアカウントという意味でfollowingIdsという変数に格納しました。
しかし取得したデータベースのカラム名はフォローされたを意味するfollowed_idです。
このような内容は、読み手は書き手と同じ認識レベルであるとは限らない為わかりにくい状態です。
誰が見てもわかりやすいようにコメントを記載する必要があります。

// データベースのカラム名はfollowed(フォローされた)ですが、主語が変わるので変数名はfollowing(フォローしている)になっている

PHPdoc(ドキュメントコメント)を書く

PHPdocとは

Docブロックはコードに詳細な情報を記述することができる、特別な種類のコメント文です。
このコメントは機能についての理解を促進させる情報を提供するために利用されます。 DocコメントをもとにIDEが自動補完の手がかりとしたり、phpDocumentorがAPIドキュメントを生成します。
引用:phpDocumentor

PHPdocを書くことで、自分だけではなく他の開発メンバーもコードを理解するのにとても役立ちます。

コメントは全ての開発する人にとって、ソースの意図を理解する助けになり、プログラムを読みやすくするため、とても重要である。

2. 安全なアプリケーション

CSRF対策

CSRF(クロスサイトリクエストフォージェリ)とは

クロスサイトリクエストフォージェリは、認証済みユーザーに代わって不正なコマンドを実行する、悪意のある攻撃の一種です。
引用:CSRF保護 9.x Laravel

CSRF対策のためには、処理が実行される前に認証済みユーザからのリクエストであるかを確認する必要があります。

Laravelは、アプリケーションによって管理されているアクティブなユーザーセッションごとにCSRF「トークン」を自動的に生成します。このトークンは、認証済みユーザーが実際にアプリケーションへリクエストを行っているユーザーであることを確認するために使用されます。このトークンはユーザーのセッションに保存され、セッションが再生成されるたびに変更されるため、悪意のあるアプリケーションはこのトークンへアクセスできません。
引用:CSRF保護 9.x Laravel

このセッションに保存されたトークンを使って、認証済みユーザからのリクエストであるかを確認します。

login.blade.php
<form method="POST" action="{{ route('login') }}">
    @csrf
</form>

Bladeディレクティブの@csrfを使って、以下の内容となる非表示のinputフィールドを生成します。

login.blade.php
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<!-- csrf_token() : 現在のセッションのCSRFトークンを取得 -->

formに@csrfを記載することで、リクエストにトークンが含まれ、その値とセッションに保存されたトークンが一致することにより認証済みユーザからのリクエストだと確認でき、CSRF対策ができます。
(一致したかどうかはApp\Http\Middleware\VerificationCsrfTokenミドルウェアが自動的に検証)

CSRFのみならず、安全なWEBアプリケーションの開発のために対策が必要である。

3. 無駄のない、綺麗で可読性の高いソースコード

値の利用頻度を考える

下記のようなソースコードがある場合

HomeController.php
$isLogged = Auth::check();
if ($isLogged) {
    $postNum = $postService->countUserPost(Auth::id());
    $favoriteNum = $postService->countUserFavorite(Auth::id());
}

if文の条件として一度しか使わないAuth::check()は変数$isLoggedに格納され、
Serviceのメソッドの引数としてAuth::id()が複数回呼び出されています。
このような場合は複数回呼び出されるものを変数として定義し、一度しか利用されないものは直接呼び出します。

HomeController.php
$id = Auth::id();
if(Auth::check()) {
    $postNum = $postService->countUserPost($id);
    $favoriteNum = $postService->countUserFavorite($id);
}

利用頻度は低くてもあえて変数に定義することにより可読性が上がることもあるので、その状況に合わせることが必要。

ソースコードを簡略化する

ControllerからViewに下記のような複数の値を渡す場合

HomeController.php
return view('home.index',[
    'title' => $title,
    'posts' => $posts,
    'followee' => $followee,
    'follower' => $follower,
    'favorite' => $favorite,
]);

Viewで使う変数名と値となるphpの変数名が同じ場合はcompact関数を使うと簡略化できます。

HomeController.php
return view('home.index', compact('title', 'posts', 'followee', 'follower', 'favorite'));

アクセサを利用する

テーブルから取得したcreated_atY年m月d日のフォーマットで表示するために下記のように実装していました。

index.blade.php
<div class="date">{{ $tweet->created_at->format('Y年m月d日') }}</div>

このような場合、データベースからデータを取得した際に実行されるアクセサを使うと、画面側の実装がより簡潔化できます。

アクセサとは

アクセサは、Eloquentの属性値にアクセスが合った時に、その値を変換するものです。
引用:Eloquent:ミューテタ/キャスト Laravel 9.x

モデルにcreated_atY年m月d日の形にフォーマットするアクセサを定義します。

Tweet.php
protected function formatedCreatedAt(): Attribute
{
    return Attribute::make(
        get: fn ($value, $attributes) => Carbon::parse($attributes['created_at'])->format('Y年m月d日')
    );
}

アクセサでフォーマット処理を実装したことにより、画面側ではアクセサを呼び出す処理だけで同じことが実現できます。

index.blade.php
<div class="date">{{ $tweet->formatedCreatedAt }}</div>

実装方法はその時々の状況によりますが、無駄のない可読性の高いコードは自分にとってもチーム開発において重要である。

まとめ

初めて自分の学びを投稿してみましたが、記事を書く中で改めて知ることも多く、アウトプットの大切さを実感しています。
まだまだ学ぶことがたくさんあるので、引き続きアウトプットしていきたいと思います!!

15
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?