Laravelでポートフォリオ作り vol.4【モックアップ編】

前回に引き続き、ポートフォリオ作りを進めていきます。
今回はモックアップの作成をしていきます。
細かい画面の機能は実装せずに見た目の部分だけを作成する作業になります。

前回の記事

今回作成する部分について

前回、画面表示までの流れを作成したので、今回は生徒一覧の見た目の部分を作成していきます。
単純にHTMLを書いていく作業になりますが、せっかくのLaravel開発なので少し工夫をしていきます。

何はともあれ、まずは単純なHTMLでモックアップを作成していきます。
DBからのデータ取得などの細かい処理は考えずに、見た目の部分、つまり「blade」を中心にコーディングを進めていきます。

Tailwind CSSを使用していく

Laravelの認証機能をインストールしているため、現在の画面はTailwind CSSを用いて作成されています。
Tailwind CSSはCSSフレームワークの一つです。自分で様々なクラスを用意しなくても、あらかじめ定義されているものを使用していくことで開発効率を上げることが可能です。

また、サンプルも豊富なので、今回はサンプルも活用しながら進めていこうと思います。

生徒一覧のblade作成

今回の生徒一覧は一般的な一覧ページで使用されるようなテーブル(表)ではなく、カードのようなレイアウトで作成しようと思っています。
早速Tailwind CSSのサンプルを探していきます。
Tailwind サンプル などで検索すると様々なページが出てくると思うので、自分の目的に合ったサンプルサイトを探してみると良いでしょう。

生徒一覧のblade(resources/views/student/index.blade.php)は前回作成済みなので、今回はコンテンツ部分を編集していきます。
「生徒一覧コンテンツ」の部分を書き換えていきます。
親のHTMLタグは白枠を作ってくれたりしているので、今回はこれをそのまま活かして実装していきます。

Tailwind CSSの変更を反映するために、「npm run dev」コマンドで変更検知機能を動作させておきましょう。
環境によって、正しく動作しない場合があります。その場合は「laravel 環境名 npm run dev」などで調べてみると良いと思います。

修正前

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            生徒一覧
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 text-gray-900">
                    生徒一覧コンテンツ
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

修正後(「生徒一覧コンテンツ」以外の部分は省略)

<div class="p-6 text-gray-900">
    <div class="bg-white border shadow-sm rounded-xl p-4">
        <h3 class="text-lg font-bold text-gray-800">
            生徒名
        </h3>
        <p class="mt-1 text-xs font-medium text-gray-500">
            期間(○○○○~△△△△)
        </p>
        <p class="mt-2 text-gray-800">
            生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ
        </p>
        <div class="flex mt-3">
            <a class="text-sky-500 mr-3" href="#">
                生徒詳細
            </a>
            <a class="text-orange-500" href="#">
                面談登録
            </a>
        </div>
    </div>
</div>

こんな感じで作成してみました。
生徒は複数表示されるので、カード部分をコピペして2つにしてみました。
その際、カード同士の隙間を開けるためにクラスを追加しています。

<div class="p-6 text-gray-900">
    <div class="bg-white border shadow-sm rounded-xl p-4 mb-3">
        <h3 class="text-lg font-bold text-gray-800">
            生徒名
        </h3>
        <p class="mt-1 text-xs font-medium text-gray-500">
            期間(○○○○~△△△△)
        </p>
        <p class="mt-2 text-gray-800">
            生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ
        </p>
        <div class="flex mt-3">
            <a class="text-sky-500 mr-3" href="#">
                生徒詳細
            </a>
            <a class="text-orange-500" href="#">
                面談登録
            </a>
        </div>
    </div>

    <div class="bg-white border shadow-sm rounded-xl p-4">
        <h3 class="text-lg font-bold text-gray-800">
            生徒名
        </h3>
        <p class="mt-1 text-xs font-medium text-gray-500">
            期間(○○○○~△△△△)
        </p>
        <p class="mt-2 text-gray-800">
            生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ
        </p>
        <div class="flex mt-3">
            <a class="text-sky-500 mr-3" href="#">
                生徒詳細
            </a>
            <a class="text-orange-500" href="#">
                面談登録
            </a>
        </div>
    </div>
</div>

繰り返し部分の処理化

さて、単純なモックアップであればこんな感じでHTMLを組んであげればOKかと思います。
しかし、今回はこのまま開発までつながるようなモックアップを作成していきたいと思います。

注目してもらいたいのは生徒ごとのカードの部分ですね。
この部分は生徒ごとに繰り返して処理をしてカードを作成していくことになります。
そのため、Controllerから生徒の情報を受け取ってカードを作成する処理を作成していきます。

受け取る生徒情報を定義

画面に表示している内容から、変数化する生徒情報を考えていきます。
今回のカード表示内容のうち、変数化したいもの、つまり「生徒ごとに異なる情報」となるのは

  • 生徒名
  • 期間
  • 生徒メモ
  • 生徒詳細のURL
  • 面談登録のURL

になります。URL部分については実装にもよると思いますが、今回は生徒ごとに異なるURLが発行されることを想定していきます。
異なることを想定して実装しておけば、仮に同じになったとしても修正の手間は大して発生しませんしね。

それでは、Controllerのindex関数を修正して、生徒情報の変数を作成していきましょう。

修正前

public function index()
{
    return view('student.index');
}

修正後

public function index()
{
    // 生徒の情報を作成する
    $student = [
        'student_name' => '田中太郎',  // 生徒名
        'kikan_from' => '2023-01-01',  // 期間(開始日)
        'kikan_to' => '2023-04-01',  // 期間(終了日)
        'student_memo' => '田中太郎さんは、とても優秀な生徒です。',  // 生徒メモ
        'student_detail_url' => '',  // 生徒詳細URL
        'student_mendan_url' => '',  // 面談URL
    ];
    
    return view('student.index');
}

こんな感じで、配列変数に1人分の生徒情報が格納されるようにしてみました。
URL部分が空欄になっていたり、生徒情報がDBからの取得になっていませんが、その処理を作成するためには色々と実装が不足しているので、とりあえず形だけ作っています。モックアップなので、これでOKです。

続いて、複数の生徒情報がbladeに渡せるように、処理を追加していきます。

複数人の生徒情報対応

public function index()
{
    // 複数人の生徒情報を格納するための配列を作成
    $students = [];
    
    // 生徒の情報を作成する
    $student = [
        'student_name' => '田中太郎',  // 生徒名
        'kikan_from' => '2023-01-01',  // 期間(開始日)
        'kikan_to' => '2023-04-01',  // 期間(終了日)
        'student_memo' => '田中太郎さんは、とても優秀な生徒です。',  // 生徒メモ
        'student_detail_url' => '',  // 生徒詳細URL
        'student_mendan_url' => '',  // 面談URL
    ];
    
    // 生徒情報を格納する
    $students[] = $student;
    
    // 変数を通さずに直接格納してもOK
    $students[] = [
        'student_name' => '山田花子',  // 生徒名
        'kikan_from' => '2023-02-01',  // 期間(開始日)
        'kikan_to' => '2023-08-01',  // 期間(終了日)
        'student_memo' => '山田さんは半年コースの申し込みです。',  // 生徒メモ
        'student_detail_url' => '',  // 生徒詳細URL
        'student_mendan_url' => '',  // 面談URL
    ];
    
    return view('student.index');
}

少しややこしくなってしまいましたね。
所謂、多次元配列というものを用いています。配列に配列を格納している形ですね。
一階層目の配列から要素を取り出すと、1人分の生徒情報となっています。その1人分の生徒情報要素がさらに配列になっていて、各項目の情報を保持しています。
このあたりは画面表示の処理を作成するとイメージしやすくなるかもしれません。

配列への格納方法は色々ありますので、各記述について、不明点については調べてみてください。
上記の処理でstudentsという配列の1つ目の要素は「田中太郎」さんの情報、2つ目の要素には「山田花子」さんの情報が格納されることとなります。

bladeに変数を渡す

まずはControllerからbladeに変数を渡します。withメソッドの使用など様々な方法がありますが、単純にviewメソッドの第二引数で配列で渡すこともできます。

public function index()
{
    // 複数人の生徒情報を格納するための配列を作成
    $students = [];
    
    // 生徒の情報を作成する
    $student = [
        'student_name' => '田中太郎',  // 生徒名
        'kikan_from' => '2023-01-01',  // 期間(開始日)
        'kikan_to' => '2023-04-01',  // 期間(終了日)
        'student_memo' => '田中太郎さんは、とても優秀な生徒です。',  // 生徒メモ
        'student_detail_url' => '',  // 生徒詳細URL
        'student_mendan_url' => '',  // 面談URL
    ];
    
    // 生徒情報を格納する
    $students[] = $student;
    
    // 変数を通さずに直接格納してもOK
    $students[] = [
        'student_name' => '山田花子',  // 生徒名
        'kikan_from' => '2023-02-01',  // 期間(開始日)
        'kikan_to' => '2023-08-01',  // 期間(終了日)
        'student_memo' => '山田さんは半年コースの申し込みです。',  // 生徒メモ
        'student_detail_url' => '',  // 生徒詳細URL
        'student_mendan_url' => '',  // 面談URL
    ];
    
    return view('student.index',[
        'students' => $students,
    ]);
}

return view(‘student.index’,[
    ‘students’ => $students,
]);

このように記述することで「students」という名前で変数「$students」を渡すことができます。
配列のキーの部分がbladeで使用する変数名、配列の値の部分が渡す値になるわけですね。
わざわざ名前をずらす必要もないかもしれませんが、
return view(‘student.index’,[
    ‘p_students’ => $students,
]);

と記述することで、bladeでは「p_students」という名前で変数にアクセスすることになります。

bladeで受け取った変数を展開する

続いて、受け取った変数をblade側で展開していきます。
まず、カードが受け取った生徒数分作成されるようにbladeを修正していきます。

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            生徒一覧
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 text-gray-900">
                    @foreach($students as $l_student)
                        <div class="bg-white border shadow-sm rounded-xl p-4 mb-3">
                            <h3 class="text-lg font-bold text-gray-800">
                                生徒名
                            </h3>
                            <p class="mt-1 text-xs font-medium text-gray-500">
                                期間(○○○○~△△△△)
                            </p>
                            <p class="mt-2 text-gray-800">
                                生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ生徒のメモ
                            </p>
                            <div class="flex mt-3">
                                <a class="text-sky-500 mr-3" href="#">
                                    生徒詳細
                                </a>
                                <a class="text-orange-500" href="#">
                                    面談登録
                                </a>
                            </div>
                        </div>
                    @endforeach
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

@foreach($students as $l_student) とループ文を使用することで、生徒数分のループ処理を行います。
ループ処理の中でカードを作成しているため、人数分のカードが作成されるわけですね。

これだけではカードの中身の部分が固定になってしまっているので、ここを生徒ごとの情報が出力されるようにします。
ループ処理の各要素が生徒情報になっているため、「$l_student」が生徒情報になっています。
ここから、各情報を取り出して画面に出力します。
ループ部分を修正していきます。

@foreach($students as $l_student)
    <div class="bg-white border shadow-sm rounded-xl p-4 mb-3">
        <h3 class="text-lg font-bold text-gray-800">
            {{ $l_student['student_name'] }}
        </h3>
        <p class="mt-1 text-xs font-medium text-gray-500">
            期間({{ $l_student['kikan_from'] }}~{{ $l_student['kikan_to'] }})
        </p>
        <p class="mt-2 text-gray-800">
            {{ $l_student['student_memo'] }}
        </p>
        <div class="flex mt-3">
            <a class="text-sky-500 mr-3" href="{{ $l_student['student_detail_url'] }}">
                生徒詳細
            </a>
            <a class="text-orange-500" href="{{ $l_student['student_mendan_url'] }}">
                面談登録
            </a>
        </div>
    </div>
@endforeach

このように、必要な情報を配列アクセスで取得します。
blade上で変数を使用する場合、{{ 変数名 }}とすることを忘れないように注意してください。

ここまでの実装で画面はこのようになりますね。

もし、表示する生徒情報を増やしたい場合はControllerのstudents変数に格納する値を増やしていきましょう。

なぜ、単純なHTMLではないモックアップを作成したか

私はプログラミングの進め方は様々な考え方があると思っています。そのうちの1つの考え方として読んでください。

私はモックアップ作成の際に、すでにフレームワークなどが決まって変数が使用できる場合は、このように変数を使用したモックアップを作成しています。
これは

  • モックアップ作成時点では情報が不足していることが多く完全な処理が作れない
  • なるべく開発を進めておきたい

という点により、この実装方法をおこなっています。

モックアップはユーザーの方に画面項目やレイアウトの確認のため、実装の初期段階で作成することが多いです。
そのため、まだ不明瞭な点が多いままの作業になることがおおいため、今回のようにDB処理部分が実装できないこともあります。

ここで、お客様に見せるためにHTMLでのモックアップを作成すると、どうなるでしょう?
開発時にbladeように書き換えて、変数部分の置き換えなどを進めていく必要がでてきます。

そのため、Controllerからbladeへの受け渡しの変数の定義とbladeでの変数部分の使用をプログラミングしてしまいます。
そうすることでデザインが変更されない限りはbladeの修正が発生することがありません
値部分についてはDB取得になったり、DB取得値を処理して出力用に変更した値を使用することになったりと、様々なことが想定されます。
しかし、どうなったとしてもbladeが使用する変数は変わらないので、その変数への値設定部分だけを書き換えれば対応ができるため、修正範囲を最小限にとどめることができます。

以上の理由から、今持っている情報でできる限り開発を進めようと思った結果、この実装方法にたどり着きました。

今回はここまで。
もちろん、成果物実装に当たってDB処理を並行して作成してもOKです。
しかし、私の考え方の根本は「なるべく作業を単純化する」ことにあります。
並行での作業が増えれば増えただけ、間違えるリスクも高まりますからね。

自分なりの実装手順を確立しておくことをおススメします!