未経験からエンジニア転職をするための最強ロードマップロードマップ

【Laravel教材④】Laravelでブログシステム構築!〜全記事一覧画面実装から記事詳細画面実装編〜

ファド

こんにちは!
PHPのLaravelやJavaScriptでWeb開発をしているフリラーンスエンジニアのファドと申します!

こちらの記事はLaravel教材の第4回目の記事になります。

その他のLaravel教材を学習したい方は下記リンクから直接教材へ飛ぶことができます。

目次

全ての記事を取得して一覧で表示

ここまでで記事一覧画面をHTMLのみで作成しましたが、これからは記事のデータをデータベースから取得して、取得したデータを表示するようにしていきます。

今回初めてLaravelを使用してデータベースからデータを取得するので、どのようにデータを取得して表示させるのかの流れを確認していきます。

流れは下記のようになっています。

  1. モデルを使用してデータベースから記事データを取得する
  2. コントローラーでモデルを呼び出してビューにデータを渡す
  3. ビュー(Bladeファイル)で記事データを全て表示する

それでは流れに沿って一つひとつ解説していきます。
なお、コードは後ほど書き換えるので下記の説明時には変更しなくて大丈夫です。

記事データを取得する方法

Laravelのモデルを使用してデータを取得する方法はいくつかありますが、全てのデータを取得したい場合にはallメソッドを使用することができます。

allメソッドの使い方は下記の通りです。

$変数名 = モデルクラス名::all();

データを格納するための変数を用意し、モデルクラス名に:all()と記述するだけで、モデルに紐付いたテーブルのデータが全て変数に格納することができます。

今回作成しているArticleモデルを使用する場合は下記のようになります。

$articles = Article::all();

データを格納するための変数名は、データが複数あることが考えられるのでarticlesと複数形にしています。
また、モデルクラス名はfirst-app/app/Models/Article.phpファイルのクラス名になるので、Articleになります。

それに::all()を記述するだけです。
とても簡単ですね!

コントローラーでモデル呼び出してデータを渡す方法

それでは、先ほど学んだデータの取得方法のallメソッドをコントローラーのメソッド内で実行していきます。

まずfirst-app/app/Http/Controllers/ArticleController.phpを確認してみましょう。
その中にshowArticlesというメソッドがあります。
このメソッドこそが記事一覧を表示するためのメソッドです。

そのため、このメソッド内でallメソッドを使用してデータを取得し、ビュー(Bladeファイル)へデータを渡すことになります。

ビューへデータを渡す方法はいくつかありますが、まずは配列で渡す場合を説明します。

$articles = Article::all();

return view('articles.index', [
    'articles' => $articles,
]);

viewメソッドの第二引数として配列を記述し、その中に'Bladeで受け取る時の名前' => 渡したいデータの変数名とすることでBladeファイルへデータを渡すことができます。

今回の例だとindex.blade.phpのBladeファイルで変数articlesのデータを受け取る時は、$articlesと記述することで受け取れるようになります。

次に配列ではなくcompact関数を使用した場合も説明します。

$articles = Article::all();

return view('articles.index', compact('articles'));

viewメソッドの使い方は同じですが、第二引数に配列ではなくcompact関数を使用しています。
compact('渡したいデータの変数名')を記述することでBladeファイルへデータを渡すことができます。
配列よりもコードがコンパクトになるので、こちらをおすすめします。

また、今回の例もindex.blade.phpのBladeファイルで変数articlesのデータを受け取る時は、$articlesと記述することで受け取れるようになります。

Bladeでデータを表示する方法

BladeファイルにはPHPを直接記述することができます。
その機能とBladeの構文を使用することで簡単にデータを表示することができます。

今回Bladeファイルで受け取るデータはarticlesテーブルの全データなので、複数あることが予想されます。
そのためforeachを使用したループ処理を使用して、全ての記事データを表示していきます。

Bladeでは@foreach~@endforeachというループ処理用の構文が用意されているので、そちらを使用してデータを表示させることができます。

今回の場合は下記のようになります。

@foreach($articles as $article)
    {{ $article->id }}
@endforeach

@foreach($articles as $article)とすることで、変数articlesの要素を変数articleとして取り出すことができます。

Bladeファイル内でPHPを記述する場合は{{}}で囲んでください。
{{}}で囲うことでブラウザに値を出力することができます。

$article->idについては実装時に説明します。

実装

実際に手を動かしながら実装していきましょう。

まずはfirst-app/app/Http/Controllers/ArticleController.phpを下記の通り編集してください。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Article; // ここを追加

class ArticleController extends Controller
{
    /**
     * 記事一覧を表示する
     */
    public function showArticles()
    {
        // 全ての記事データを取得
        $articles = Article::all();

        dd($articles);
    }
}

まず追加したのは下記コードです。

use App\Models\Article;

このようにuse文を使用することで、Articleモデルを他ファイルで使用することができるようになります。

use文の使い方はuseと記述してから、使用したいファイルのnamespace部分とクラス名を記述します。
例えば、今回の場合はfirst-app/app/Models/Article.phpnamespaceを確認します。
するとnamespace App\Models;と記述されており、クラス名はArticleとなっています。

つまり、Articleモデルを他ファイルで使用したい場合はuse App\Models\Articleと記述することになります。

これでArticleコントローラー内でArticleモデルを使用できるようになったので、Article::all()と記述することで、Articleモデルを通してarticlesテーブルから全てのデータを取得することができます。
取得したデータを変数articlesへ格納するために$articles = Article::all();と記述しています。
これでデータベースに保存されている全ての記事データを変数articlesに格納することができました。

実はLaravelには変数内にどのような値が入っているのかを確認するためのヘルパーメソッドが用意されています。
それがddメソッドです。
このddメソッドを使用すると、第一引数に記述した変数の内容をブラウザで視覚的に確認することができます。
また、ddメソッド以降の処理は実行されないので、ある時点での変数の中身を確認したい時に重宝します。

今回は全ての記事データが入っている変数articlesを確認するためにdd('articles')と記述してみました。

それではhttp://localhost/articlesへアクセスしてみましょう。
ddメソッドを使用すると、下記画像のような画面が出てきます。

#items: array:3[▶]となっているをクリックしてみてください。
そうすると下記画像のように中身が展開されます。

現在articlesテーブルには、テストデータとして作成した3つのデータが入っています。
その3つのデータが配列で入っていることがこれで確認できました。

次に0 => App\Mo…\Article{#319 ▶}をクリックしてみましょう。
※ #319という番号は人によって違う場合がございます。

するとさらに展開され、その中に#attributes: array5 [▶]があると思います。
そのをクリックしてみてください。

attributesが展開され、中に入っているデータを確認することができます。

これはシーダーを使用して追加した1番目のテストデータですね。
このように、モデルで取得したデータの内容はattributesに格納されるので、覚えておきましょう。

2番目や3番目のデータも同じようにをクリックして展開していくことでデータ内容を確認することができます。

このようにddメソッドを使用すると、変数の内容をブラウザで簡単に確認することができます。
デバッグや実装中にどのような値が入っているか一旦確認したい場合に使用してみましょう。

次はコントローラーからBladeファイルに値を渡すための処理を記述しましょう。
first-app/app/Http/Controllers/ArticleController.phpを下記の通り編集してください。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Article;

class ArticleController extends Controller
{
    /**
     * 記事一覧を表示する
     */
    public function showArticles()
    {
        // 全ての記事データを取得
        $articles = Article::all();

        // compact関数で渡す場合
        return view('articles.index', compact('articles'));
    }
}

先ほど説明した通り、コントローラーからBladeファイルへ値を渡すためにcompact関数を使っています。

return view('articles.index', compact('articles'));と記述することでindex.blade.phpに全ての記事データが入っている変数articlesを渡すことができます。

それでは渡した変数をindex.blade.phpで表示するようにしましょう。

first-app/resources/views/articles/index.blade.phpを下記の通り編集してください。

@extends('layout')

@section('title')
    記事一覧
@endsection

@section('content')
    <div class="row">
        <h2>記事一覧</h2>
        <table class="table table-bordered table-hover ">
            <thead class="bg-info text-light">
                <tr>
                    <th scope="col">#</th>
                    <th scope="col">タイトル</th>
                    <th scope="col">内容</th>
                    <th scope="col">日付</th>
                </tr>
            </thead>
            <tbody>
                @foreach ($articles as $article)
                    <tr>
                        <td>{{ $article->id }}</td>
                        <td>{{ $article->title }}</td>
                        <td>{{ $article->content }}</td>
                        <td>{{ $article->updated_at }}</td>
                    </tr>
                @endforeach
            </tbody>
        </table>
    </div>
@endsection

ArticleコントローラーのshowArticlesメソッドから全ての記事データ入った変数articlesが渡されてきたので、Bladeファイルではループ処理を使用して1つずつ表示させていきます。

Laravelでループ処理を実装したい場合は@foreach()~@endforeachを使用することで、簡単にループ処理が実装できます。

下記の通りddメソッドを使用して、変数articlesの一つひとつのデータを確認すると、テーブルのカラム名がそのままキーとして設定されていることがわかります。

そのため、記事のIDを取得したい場合は$article->id、タイトルを取得したい場合は$article->title、内容を取得したい場合は$article->content、更新日を取得したい場合は$article->updated_atと記述すればいいことになります。

また、今回は使用していませんが、作成日を取得したい場合は$article->created_atとなります。

Bladeでは、それらを{{}}で囲むことで安全にブラウザに表示することができます。

それではhttp://localhost/articlesへアクセスしてみてください。

下記のようにデータベースから取得した3つのデータが表示できていればOKです!


データ取得から表示までの流れの確認

最後にデータベースからデータを取得した後、データを表示させるまでの流れをMVCの画像を見ながら確認していきましょう。

まず、下記の画像がMVCにルートを追加した画像です。

http://localhost/articlesへアクセスがあった時に最初に読まれるファイルはfirst-app/routes/web.phpです。
これが①のアクセスです。

その中のRoute::get('/articles', [ArticleController::class, 'showArticles'])->name('showArticles');が実行されることで、ArticleコントローラーshowArticlesメソッドが実行されます。

そのため次は、first-app/app/Http/Controllers/ArticleController.phpshowArticlesメソッドの中身の処理を確認しましょう。

showArticlesメソッドには$articles = Article::all();という処理が記述されています。
これはArticleモデルが継承しているModelクラスが持つallメソッドを実行しています。

allメソッドを実行するとモデルがデータベースへ接続しにいき、取得したarticlesテーブルの全データをコントローラーの変数articlesに格納します。
つまり②のデータ処理がここで行われており、③のDB接続も同時に行っています。

そして、return view('articles.index', compact('articles'));と記述することで、コントローラーからビューであるfirst-app/resources/views/articles/index.blade.phpというBladeファイルへ変数articlesを渡しています。
これが④のデータ譲渡です。

そして最後にfirst-app/resources/views/articles/index.blade.php@foreachを使用して全てのデータを一つひとつ表示しているという流れです。
これが⑤のサイト表示です。

Laravelでは、このように①→②→③→②→④→⑤のような流れでデータを取得し、表示することができます。
これがMVCの基本的な流れになるので、ぜひ覚えておきましょう!

★検索ワード
・Laravel 全てのデータを取得
・Laravel Eloquent all
・Laravel ddメソッド
・Laravel compact
・Laravel View データを渡す

記事詳細を取得して表示

ここまでで全ての記事を一覧で表示できるようになりましたが、今回は一つひとつの記事の詳細画面を作成していきます。

記事詳細画面を作成する流れは下記のようになります。

  1. 詳細を表示する記事のIDでリンクを作成する
  2. ルートでIDを受け取りコントローラーへ渡す
  3. 受け取ったIDのデータをモデルを使用して取り出す
  4. ビューで表示する

それでは流れに沿って一つひとつ実装していきましょう。
なお、コードは後ほど書き換えるので下記の説明時には変更しなくて大丈夫です。

詳細表示する記事のIDでリンクを作成する

特定の記事を取得するためにはIDを使用します。
IDを使用する理由は、IDとは記事一つひとつに与えられた固有の値であり、同一テーブル内でIDがかぶることがないからです。

例えばIDが1の記事を取得する場合は下記のようなURLにします。
http://localhost/article/1
こうすることでURL内の1とテーブル内のIDが1のデータが紐付けられるので、IDが1のデータを取得することができます。

ルートでIDを受け取りコントローラーへ渡す

では、http://localhost/article/1というURLへアクセスされると、ルート(web.php)へ処理が移動します。

なので、ルートでIDを受け取り、その後コントローラーにもIDを渡すことが必要になります。
そのためのルートの記述は下記のようになります。

Route::get('/article/{id}', [ArticleController::class, 'showArticle']);

このような記述をすることで、http://localhost/article/1へアクセスされるとArticleコントローラーshowArticleメソッドが実行されるようになります。
ちなみに、showArticleメソッドは後ほど作成します。

また、'/article/{id}'{id}についてですが、ルートパラメーターと呼ばれていて、{}で囲むことで定義することができます。

今回の例だと$idという変数で値をコントローラーへ渡すことができます。
つまり、http://localhost/article/1へアクセスがあった場合、1を引数idとしてshowArticleメソッドに渡すことができるということです。

受け取ったIDのデータを取り出す

showArticleメソッドでIDを受け取った後は、そのIDを使用してarticlesテーブルからIDが1のデータを取得します。

1つのデータを取得するときはallメソッドではなく、findメソッドを使用します。
具体的な使い方は下記の通りです。

$article = Article::find(1);

このようにArticle::find(1)と記述することでIDが1の記事を取得することができます。
つまり、allメソッドでは全てのデータを取得していましたが、findメソッドを使用することで特定のデータを取得することができます。

また、別の方法としてSQLのWhere句のような記述方法もあります。

$article = Article::where('id' => '1')->first();

whereメソッドfirstメソッドを使用することで、記事IDが1のデータを取得することができます。
whereメソッドの第一引数には検索するカラム名を取得し、第二引数には検索するための値を指定します。
今回の記事IDが1のデータを取得するためには、where('id' => '1')となります。
また、whereメソッドで検索条件を決めた後にfirstメソッド->で繋げることで、検索条件に合うデータを1つ取得することができます。

ビューで表示する

あとはコントローラーで取得したデータをビューに渡して表示するだけです。
詳細表示用のBladeファイルも後ほどlayout.blade.phpを継承して作成していきます。

実装

それでは記事詳細画面を作成する流れを説明したので、実際に手を動かしながら実装していきましょう。

まずはfirst-app/routes/web.phpを下記の通り編集してください。

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ArticleController;

Route::get('/', function () {
    return view('welcome');
});

// 記事一覧を表示
Route::get('/articles', [ArticleController::class, 'showArticles'])->name('showArticles');

// 記事詳細を表示
Route::get('/article/{id}', [ArticleController::class, 'showArticle'])->name('showArticle'); // ここを追加

これで記事詳細画面を表示するルートを記述することができました。
先ほど説明した通り、ルートパラメーターを使用して記事IDをルートで受け取り、コントローラーへ渡せるようにしています。

次にfirst-app/resources/views/articles/index.blade.phpを下記の通り編集してください。

@extends('layout')

@section('title')
    記事一覧
@endsection

@section('content')
    <div class="row">
        <h2>記事一覧</h2>
        <table class="table table-bordered table-hover ">
            <thead class="bg-info text-light">
                <tr>
                    <th scope="col">#</th>
                    <th scope="col">タイトル</th>
                    <th scope="col">内容</th>
                    <th scope="col">日付</th>
                </tr>
            </thead>
            <tbody>
                @foreach ($articles as $article)
                    <tr>
                        <td>{{ $article->id }}</td>
                        <td>
                            <a href="{{ route('showArticle', $article->id) }}">
                                {{ $article->title }}
                            </a>
                        </td>
                        <td>{{ $article->content }}</td>
                        <td>{{ $article->updated_at }}</td>
                    </tr>
                @endforeach
            </tbody>
        </table>
    </div>
@endsection

変更したコードは下記の通りです。

<td>
    <a href="{{ route('showArticle', $article->id) }}">
        {{ $article->title }}
    </a>
</td>

上記のコードを見ていただくとわかるように、記事タイトルをaタグで囲ってリンクにしています。
今回は記事タイトルをリンクにし、クリックされた時に記事詳細画面を表示するようにしていきます。

先ほど、記事詳細画面を作成する流れでも説明した通り、まずは記事の詳細を表示するための記事IDに結びついたリンクを作成しています。

aタグのリンク先を決めるためにはhref属性を使用しますが、そのhref属性にLaravelのヘルパーメソッドであるrouteメソッドを使用します。

routeメソッドの第一引数を見てみるとshowArticleとなっています。
このshowArticleはルーティングでshowArticleメソッドを実行するルートのルート名です。
なんとなくルーティング時に指定していたルート名ですが、ここでようやく使用するときがやってきました。

それではweb.phpshowArticleメソッドを実行するためのルートを見てください。
Route::get('/article/{id}', [ArticleController::class, 'showArticle'])->name('showArticle');
ルート名を指定していたのはname('showArticle');です。

このルート名をrouteメソッドの第一引数に指定することで、指定したルートへのリンクが作成できるようになります

次に第二引数を見てみると$article->idとなっています。
これは記事IDを第二引数に指定しているということです。

このように第二引数に紐付けたい値を記述することでルートに記事ID渡すことができます。

では、実際にhttp://localhost/articlesへアクセスしてから1番目の投稿をクリックしてください。
下記のようなエラー画面が表示されますが、URLを確認してみましょう。
http://localhost/articles/1になっているはずです。

今回は記事IDが1である記事タイトル1番目の投稿をクリックしたので、URLには1が表示されています。
ちなみに、エラー内容はArticleコントローラーshowArticleメソッドがありませんというエラーです。
なので、次はshowArticleメソッドを作成していきましょう!

受け取ったIDのデータを取り出す

まずはfirst-app/app/Http/Controllers/ArticleController.phpを下記の通り編集してください。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Article;

class ArticleController extends Controller
{
    /**
     * 記事一覧を表示する
     */
    public function showArticles()
    {
        // 全ての記事データを取得
        $articles = Article::all();

        // compact関数で渡す場合
        return view('articles.index', compact('articles'));
    }

    /**
     * 記事詳細を表示する
     */
    public function showArticle($id)
    {
        // 渡されてきた記事IDのデータを取得
        $article = Article::find($id);

        dd($article);
    }
}

追加したコードは下記の通りです。

/**
 * 記事詳細を表示する
 */
public function showArticle($id)
{
    // 渡されてきた記事IDのデータを取得
    $article = Article::find($id);

    dd($article);
}

まず、ルートから渡されてきた記事IDはshowArticleメソッドの第一引数として取得することができます。
そのため、public function showArticle($id){}としましょう。

次に、受け取った記事IDの記事データを取得したいので下記コードのようにfindメソッドを使用します。
Article::find($id)

そしてddメソッドを使用して、取得したデータを一度ブラウザで確認しておきます。
http://localhost/article/1へアクセスしてみてください。

上記のようなデータが表示されるので、先ほどと同じようにattributesを展開するとデータの中身を確認することができます。

無事に記事IDが1のデータが取得できていますね!

データが確認できたので、改めてfirst-app/app/Http/Controllers/ArticleController.phpを下記の通り編集してビューに値を渡しましょう。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Article;

class ArticleController extends Controller
{
    /**
     * 記事一覧を表示する
     */
    public function showArticles()
    {
        // 全ての記事データを取得
        $articles = Article::all();

        // compact関数で渡す場合
        return view('articles.index', compact('articles'));
    }

    /**
     * 記事詳細を表示する
     */
    public function showArticle($id)
    {
        // 渡されてきた記事IDのデータを取得
        $article = Article::find($id);

        return view('articles.detail', compact('article'));
    }
}

ここは記事一覧を表示させた時と同じように、viewメソッドを使用してdetail.blade.phpへ値を渡しています。

もちろんhttp://localhost/article/1へアクセスしても、detail.blade.phpが存在しないので、View[articles.detail] not foundというdetail.blade.phpが見つからないよ!というエラーが発生します。

ビューで表示する

最後にコントローラーから渡されてきた記事データを表示するための画面を作成しましょう。

articlesディレクトリにdetail.blade.phpを作成してください。
コマンドで作成する場合は、ターミナルで下記コマンドをfirst-appディレクトリ上で実行してください。

$ touch resources/views/articles/detail.blade.php

作成したdetail.blade.phpを開いて、下記の通り編集してください。

@extends('layout')

@section('title')
    記事詳細
@endsection

@section('content')
    <h2>{{ $article->title }}</h2>
    <div class="d-flex">
        <span class="mr-2">作成日:{{ $article->created_at }}</span>
        <span>更新日:{{ $article->updated_at }}</span>
    </div>
    <p class="mt-4">{{ $article->content }}</p>
    <a href="{{ route('showArticles') }}" class="mt-3 btn btn-secondary">戻る</a>
@endsection

index.blade.phpと同じようにlayout.blade.phpを継承することで簡単にページを作成できました。
変えたのは@sectionの中身だけで、titleには記事一覧として、contentには記事のデータが表示できるようにしています。

コントローラーから記事IDが1の記事を変数articleで渡されているので$article->titleと記述すると記事のタイトルが取得できます。
その他の作成日や更新日、内容なども変数articleを使用すれば、簡単に表示させることができます。

また、今回は受け取った記事は記事IDが1の記事1つだけなのでループ処理はいりません。

そして、最後に戻るボタンを実装しています。

先ほどは記事IDに紐付いたリンクを生成しましたが、戻るボタンの実装では記事一覧画面へ飛べるリンクを生成するだけなので、特に第二引数は必要ありません。

記事一覧画面を表示させるルート名showArticlesrouteメソッドの第一引数に記述するだけで、記事一覧画面に遷移することができます。

動作確認

それでは念の為、正しく実装できているか動作確認をしてみましょう。
まずはhttp://localhost/articlesへアクセスして、1番目の投稿をクリックしてください。
そうすると下記のように記事IDが1の記事詳細画面が表示されます。

次に戻るボタンをクリックしてみましょう。
そうすると記事一覧画面に戻ります。
最後に3番目の投稿をクリックしてみましょう。
下記のように記事IDが3の記事詳細画面が表示されればOKです。

★検索ワード
・Laravel 詳細ページ
・Laravel Eloquent find
・Laravel Eloquent where
・Laravel Eloquent first

次の教材

次の教材は下記から簡単に飛ぶことができます!
引き続きプログラミングを楽しんでいきましょう!

あわせて読みたい
【Laravel教材⑤】Laravelでブログシステム構築!〜記事投稿機能実装編〜 こちらの記事はLaravel教材の第5回目の記事になります。 その他のLaravel教材を学習したい方は下記リンクから直接教材へ飛ぶことができます。 【記事投稿】 ここまで記...

プログラミング学習サポートについて

「独学で挫折した。。。」

「一人でのプログラミング学習がしんどい。。。」

「未経験からエンジニア転職をしたいけど何をしたら良いかわからない。。。」

このような悩みをお持ちの方向けに、本教材作成者のファドがMENTAという学習サイトにてあなたのプログラミング学習とエンジニア転職を徹底サポートいたします!

サポート価格はなんと1日あたりたったの約300円!

教材で分からない箇所のサポートはもちろんのこと、本サイトで公開しているすべての課題の解答も公開しております。
また、MENTAで学習を終わらせていただいた方限定で懇意にしていただいている企業さんを紹介することもあります!

なお、サポート内容の詳細は下記の通りです。

  • 目標設定
  • マインドセット
  • オリジナル教材見放題
  • オリジナル課題見放題
  • オリジナル課題の解答見放題
  • 課題コードレビュー
  • 教材への無制限質問
  • 課題への無制限質問
  • ポートフォリオ作成アドバイス
  • 褒めのコーチング

いくつかのプランを用意させていただいておりますので、下記より一度ご覧ください!

あわせて読みたい
【プログラミング学習】1日あたりたったの「300円」のみでプログラミングを学び、最短で転職or稼ぐ!|【ME... プログラミングを学びたいすべての方へこれからの時代は格安でプログラミングを学び、最短で稼げ自己紹介はじめまして!この度はプランをご覧いただき、誠にありがとうござ...

コメント

    この記事が気に入ったら
    フォローしてね!

    よかったらシェアしてね!
    • URLをコピーしました!

    コメント

    コメントする

    目次