1
1

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+Inertia+Vueを利用したプロジェクトでのコーディングルール

Last updated at Posted at 2024-02-16

コーディングルール

  • Laravel+Inertia+Vueを利用したプロジェクトを立ち上げた時のコーディングルール備忘録
  • 基本的なところだけを定めているので、チームの方針によって少し編集するだけで使えると思う
  • 型定義のチェック関連に関しては、別途定義した方がわかりやすかったため、ここでは記載しない

共通

  • フロントエンドのコードにおけるタブは2スペースで作成する(原則Tabを使用する)
  • バックエンドのコードにおけるタブは4スペースで作成する(原則Tabを使用する)
  • 文字列などは基本的に下手打ちせずに、定数を利用する
    • Laravelのlangディレクトリにファイルを作成する
    • 画面側の文字列も基本的にLaravelのlangを利用する

langファイルへの文字切り出しについて

  • langファイルの第一階層はテーブル名、第二階層名はカラム名に準じる
    • 最大第二階層までの階層分けとする
  • DBに無い項目については、下記のような名称付けルールとする
    • ページのタイトル:title
    • ページの説明:titleDescription

バックエンドのデータの流れと役割

  1. Model:テーブルと1対1になる。テーブルの情報だけを管理(リレーションやアクセサなど)
  2. Repository:テーブルに対するCRUD処理を管理
  3. Service:データの加工を管理
  4. Controller:viewに返却する用としてのデータ加工&返却値を管理

サーバーサイド→フロントエンドへのデータの受け渡しについて

  • 本プロジェクトにおいてはInertiaを使用して構築するため、LaravelではコントローラーからVueに値を渡し、Vue.jsはその値をPorpsとして受け取る
  • この際、フロントエンドにおけるコーディング規約である変数をローワーキャメルケースで取り扱う仕様を踏襲するため、下記のようにする
    • Laravelはフロントエンドに値を渡す際、対象の変数名に関してのみローワーキャメルケースで記載する
      • ただし、lang系ファイルのように、オブジェクト(ディクショナリー系)を渡す際は、下階層まで全てローワーキャメルケースに変換するのは冗長であるため、最上階層の変数名のみローワーキャメルケースとすることで事足りることとする

return Inertia::render(
    '{ページ名}',
     [
         'title' => $title,
         emailPlaceholder' => $email _placeholder, //  PHPの変数名はスネークケース、Vue.jsに渡す変数名はローワーキャメルケース
         'lang' => $lang, // langには、下階層に`lang.error_message`や`lang.success_message`などが紐づくが、最上階層のみローワーキャメルケースとするため、問題ない
      ]
);

サーバーサイド

メソッドや変数の命名規則

対象 命名規則 書き方の例
メソッド名 (ローワー)キャメルケース userProfile
変数名 スネークケース user_profile
定数名 スネークケース API_URL
クラス(クラスファイル)名 パスカルケース(アッパーキャメル) UserProfile
インターフェース(インターフェースファイル)名 パスカルケース(アッパーキャメル) UserProfile
viewファイル名 スネークケース user_profile

リポジトリパターンにおけるインターフェースとリポジトリの命名規則について

対象 命名規則 書き方の例
インターフェース名 〇〇RepositoryInterface UserRepositoryInterface
リポジトリ名 〇〇Repository UserRepository

各ファイルの役割

  • Controllerファイルに肥大化を避けるため下記の通り定義する
ファイル種類 役割
Requestクラス リクエストパラメータ関連の処理を記載する。バリデーションもここで行う
MiddleWare Controllerに行く前に行いたい処理をする。IP制限や認証制限などを行う
Repositoryクラス インターフェースに従って、データベースからユーザーデータの取得や保存などを行う
Serviceクラス ユーザーに関連するビジネスロジックを実装する。リポジトリからデータを取得し、必要な処理を行う

基本ディレクトリ構成

src
└ app
  ├ Http
  | ├ Controllers
  | | ├ Api  // API用
  | | ├ Auth // 認証関連用
  | | ├ Web  // Web用
  | | | ├ WithToken // 認証トークンが必要な処理群
  | | | | ├ Admin  // Admin権限用の処理
  | | | | | ├ AdminUserController.php
  | | | | | └ ・・・
  | | | | ├ UserController.php // 一般権限用の処理
  | | | | └  ・・・
  | | | └ WithoutToken // 認証トークン不要な処理群
  | | | | ├  GetLogidomainInfoController.php
  | | | | └  ・・・
  | ├ MiddleWare
  | ├ Requests
  | | | ├ WithToken // 認証トークンが必要な処理群
  | | | | ├ Admin // Admin権限用の処理
  | | | | | ├ AdminUserRequest.php
  | | | | | └ ・・・
  | | | | ├ GetLogidomainInfoRequest.php
  | | | | └  ・・・
  | | | └ WithoutToken // 認証トークン不要な処理群
  | | | | ├ GetPublicLogidomainInfoRequest.php
  | | | | └  ・・・
  | | ├ User
  | | | └ UserRequest.php
  | | └ ・・・
  ├ Repositories
  | ├ User
  | | ├ UserRepository.php 
  | | └ UserRepositoryInterface.php // interface
  | └ ・・・
  ├ Models
  | ├ User.php
  | ├ Product.php
  | └ ...
  ├ Services
  | ├ User
  | | ├ UserServices.php
  | ├ Product
  | | └ ProductServices.php
  | └ ...
  |
  ├ lang // バリデーションやバックエンド/フロントエンド共通文言管理
  

リレーションの命名規則

  • テーブルリレーションに関してもメソッド同様にローワーキャメルケースを用いて命名する
public function userProfile()
{
    $user = User::find(1);
    // ローワーキャメルケース
    $address = $user->userProfile->address;
}

routeの記述法

web.php / api.php

  • 基本的に関心事でまとめるようにする
  • 例として、UserとAdminで分ける場合は、下記のようになるイメージ
Route::prefix('user')->name('user.')->group(['middleware' => ['auth.api']], function () {
 // user関連の各ルーティングをまとめて記述
});
Route::prefix('admin')->name('admin.')->group(['middleware' => ['admin.auth.api']], function () {
 // admin関連の各ルーティングをまとめて記述
});


Controller系

  • ファイルはnamespaceをフルパスで記述数形式ではなく、useを利用してインポートするようにする
  • ディレクトリ違いで同名のControllerが存在する場合は、asを利用して別名で定義する
    • ※基本的に名称がかぶることはない想定なので、厳密な定義は割愛
  • 下記のようになるイメージ
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
Route::get('/home', [HomeController::class, 'index'])->name('home');

Controllerの種類

コントローラの生成ルール

  • 基本的に下記とする
    • CRUD機能はリソースコントローラを利用する
    • その他、CRUD処理以外の機能に関してはシングルアクションコントローラを利用する

リソースコントローラの生成

  • デフォルトの各アクションの引数が$idになっているものではなく、直接Modelを注入する形式で生成する
php artisan make:controller UserProfileController --model=UserProfile

フロントエンド

メソッドや変数の命名規則

対象 記法名
コンポーネント名 アッパーキャメルケース UserForm
変数名 ローワーキャメルケース sampleFunction
定数名 スネークケース API_URL
メソッド名 ローワーキャメルケース addNumber
プロパティ名 ローワーキャメルケース userName
クラス名 アッパーキャメルケース MyCar
CSSのclass名 ※具体的な名称はクラスの命名ルールを参照 ケバブケース add- number
インターフェース(インターフェースファイル)・型定義名 パスカルケース(アッパーキャメル) UserProfile

各ファイルの役割

  • ロジックの切り分けを下記の通り定義する
ファイル種類 役割
composables 共通のロジックを抽象化し、コンポーネント固有のロジックや状態を再利用可能な形で提供
components 機能とUIを切り出した単一コンポーネント。基本的に2回以上登場する同要素はcomponentにする
pages バックエンドから渡されたデータをもとにページを構成する
layouts ページ構成に関して、共通の画面構成を担うベースコンポーネントを担う
plugins アプリケーション全体に対して影響を与えるロジックを管理する
const フロントエンド全体を通じて管理する定数の管理を行う

基本ディレクトリ構成

resources
├ js
| ├ components
| | ├ Ui
| | ├ User // User関連で使用しているコンポーネント
| | └ ・・・
| ├ composables
| | ├ Api // Api関連
| | | └ useApi.js // APIをコールする関する
| | ├ User // User情報関連
| | └ ・・・
| ├ const
| | ├ droneCompanyOptions.js // SD/DCが選択できる製造機体情報のオブジェクト
| | └ ・・・
| ├ pages
| | ├ User  // userディレクトリ配下のページ群
| | | ├ Show.vue // UserControllerのshowメソッドの内容を表示する
| | | ├ Edit.vue // UserControllerのeditメソッドの内容を表示する
| | └ ・・・
| ├ layouts
| | ├ TheSidebar.vue
| | ├ TheHeader.vue
| | └ ・・・
| ├ plugins
| | ├ GoogleMapsApi.js
| | ├ Firebase.js
| | └ ・・・
| |
| └ ・・・
├ sass
└ ・・・

クラスの命名ルール

  • 基本はBEM記法に則る
  • ただし、ディレクトリ構成に則ってプレフィックスをつける
  • 各ファイルで共通するスタイルの場合はassets/sass/base.scssに定義する
// 例えば、コンポーネント内でscoped属性をつけて定義されたスタイルのクラス名は下記のようになる
pages -> p-xxx
layout -> l-xxx
components -> c-xxx
  • 意図1:base.scssで定義されたCSSか、コンポーネント内で定義されたCSSか一眼で見分けることができるようにするため
  • 意図2:Vuetifyの利用を想定し、デフォルトでグローバル宣言するクラスとの重複を避けるため

Vueの定義ルール

  • コンポーネントはパスカル(アッパーキャメル)ケースで作成し、呼び出しもパスカル(アッパーキャメルケース)で行う
  • vueのscriptタグ内は各プロパティごとにアルファベット順で並べる
    • 特にmethodsの中でもasync(非同期処理)は重要な処理のケースが多いので、methods内でも区別して上にまとめる
  • vuexは基本的に使用しない
  • styleは原則scopedで記載する
  • scriptの記載原則setup構文で記載する
  • templete, script, styleの順は下記のようにtemplateから記述する
<template>...</template>
<script>/* ... */</script>
<style>/* ... */</style>
  • scriptタグ内では、下記のように、どこからどこまでがどの処理なのかわかるようにコメントを入れる
    • ※尚、記載の順番も下記の通りの順番で記載する
<script>
  /* ===============================
   * types
   * =============================== */
  type Props = {
    title: string;
  }
   
  /* ===============================
   * data ※ABC順に記載すること
   * =============================== */
  const accountId = ref("")
  const accountIdMaxLength = ref(14)
  const password = ref("")
  
  /* ===============================
   * computed
   * =============================== */
  
  /* ===============================
   * lifecycle
   * =============================== */
  onMounted(() => {
  })
  
  /* ===============================
   * methods ※ asyncは重要な処理のケースが多いので上にまとめる
   * =============================== */
   const async login = () => {
    //
  }

</script>

コンポーネントの命名規則

  • 原則、単一ファイルコンポーネントの名称は、すべてパスカルケース (PascalCase) とする

基底コンポーネントの名前

  • 接頭辞としてBaseを付与する
// 例
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue

単一インスタンスのコンポーネント名

  • 常に1つのアクティブなインスタンスしかもたないコンポーネントは、1つしか存在しえないことを示すために The という接頭辞で始める
  • 単一インスタンスという意味は「ページごとに 1 回しか使われない」という意味
    • アプリに対して固有となるため、propsが設定されることはない
      • 設定される場合、それは単一インスタンスのコンポーネントではなく再利用可能なコンポーネントとなるため、本章の対象としない
components/
|- TheHeading.vue
|- TheSidebar.vue

props名の型式

  • props 名は、定義の時は常にキャメルケース(camelCase)を使用する
    • ※テンプレート内では、ケバブケース(kebab-case)を使用する
<WelcomeMessage greeting-text="hi"/>

ディレクティブの短縮記法について

  • 原則、ディレクティブは短縮記法で記載する
// v-bind
<input
  :value="newTodoText"
  :placeholder="newTodoInstructions"
>

// v-on
<input
  @input="onInput"
  @focus="onFocus"
>

// v-slot
<template #header>
  <h1>Here might be a page title</h1>
</template>

TypeScriptの型定義に関して

  • 原則typeを使用して定義する
  • そのファイル内でしか使用しない方は、ファイル内に記載し、複数ファイルで使い回す関数などの型については、型定義ファイルを作成する
  • 原則anyは使用しない

フォーム作成時の登録画面・編集画面・完了画面の生成について

  • 原則、フロントエンド側は1つのviewのみを作成することとする(登録・編集・完了が同じ画面)
    • disabledやreadonlyなどで制御する
  • バックエンド側も登録/編集/完了でコントローラーを分けない
1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?