Ikeda's Blog

Laravelでブログサイトを作る 16. 管理機能・記事一覧の絞り込みと検索

はじめに

前回で記事一覧を作成した続きになります。

Model

app/Models/Article.php
前回作成した一覧取得メソッドを拡張します。
引数に、今回追加分が未指定の場合の初期値を設定しているので、既存の呼び出し箇所に変更は不要となります。

// ...省略...

    /**
     * 一覧取得
     *
     * @param int    $num      件数
     * @param bool   $delete   削除済みを含めるか(true => 含める)
     * @param int    $parent   親カテゴリID 【今回追加】
     * @param int    $children 子カテゴリID 【今回追加】
     * @param string $search   検索ワード   【今回追加】
     * @return mixed
     */
    public function getList(
        int $num,
        bool $delete = false,
        int $parent = 0,
        int $children = 0,
        string $search = '')
    {
        $article = $this;

        // 【今回追加】親カテゴリが指定されている場合、記事テーブルのカラムと一致するものを抽出する
        if ($parent !== 0) {
            $article = $article->where('articles.parent', '=', $parent);
        }

        // 【今回追加】子カテゴリが指定されている場合、テーブルをJOINする
        if ($children !== 0) {
            $article = $article
                // 記事テーブルと、記事-子カテゴリ関連付けテーブルをJOIN
                ->leftJoin('article_children', function ($join) {
                    $join->on('articles.id', '=', 'article_children.article')
                        ->where('article_children.deleted_at', '=', NULL);
                })
                // 子カテゴリテーブルと、記事-子カテゴリ関連付けテーブルをJOIN
                ->leftJoin('child_categories', function ($join) {
                    $join->on('child_categories.id', '=', 'article_children.children');
                })
                // 子カテゴリの一致するものを抽出する
                ->where('child_categories.id', '=', $children);
        }

        // 【今回追加】検索ワードが指定されている場合
        if ($search !== '') {
            $article = $article
                // タイトルか本文のどこかに検索ワードが含まれていれる記事を抽出する
                ->where(function($query) use ($search) {
                    $query->where('articles.title', 'like', '%'.$search.'%')
                        ->orWhere('articles.body', 'like', '%'.$search.'%')
                    ;
                });
        }

        // 削除済みを含む場合は`withTrashed()`
        if ($delete !== true) {
            $article = $article->withTrashed();
        }

        // ソートは、新しい記事を上位表示
        $article = $article->orderBy('open', 'desc');

        // 取得
        return $article->paginate($num);
    }

// ...省略...

Controller

ルーティングで設定したメソッドを用意し、それぞれのパラメータを変更して一覧取得します。
その後は、表示用メソッドlistView()を実行するだけです。

// ...省略...


    /**
     * 管理画面・親カテゴリ別記事一覧
     *
     * @param string $parent
     * @return mixed
     */
    public function adminParentList(string $parent) {
        // ブログ記事一覧を取得
        $articleData = $this->article->getList($this->ADMIN_LIST_NUM, true, (int)$parent);

        return $this->listView($articleData, 'admin');
    }

    /**
     * 管理画面・子カテゴリ別記事一覧
     *
     * @param string $child
     * @return mixed
     */
    public function adminChildList(string $child) {
        // ブログ記事一覧を取得
        $articleData = $this->article->getList($this->ADMIN_LIST_NUM, true, 0, $child);

        return $this->listView($articleData, 'admin');
    }

    /**
     * 管理画面・記事一覧(ワード検索)
     *
     * @param Request $request
     * @return mixed
     */
    public function adminSearchList(Request $request) {
        // ブログ記事一覧を取得
        $articleData = $this->article->getList($this->ADMIN_LIST_NUM, true, 0, 0, $request['search']);

        return $this->listView($articleData, 'admin');
    }

// ...省略...

テンプレート

resources/views/admin/app.blade.php
サイドメニューに、検索ボックスとカテゴリの絞り込みリンクを設置します。

// ...省略...

    <section class="aside">
        <h3>検索</h3>
        <div id="searchWrapper">
            <form action="{{ route('admin_article_list_search') }}" method="post" name="searchForm">
                {{ csrf_field() }}
                <input type="text" id="searchTxt" name="search" placeholder="サイト内検索" />
                    <a href="javascript:searchForm.submit()" id="searchBtn">
                        <i class="fas fa-search"></i>
                    </a>
            </form>
        </div>
    </section>

    @if (isset($parentCategoryList))
    <section class="aside">
        <h3>カテゴリ</h3>
        <ul>
            @foreach ($parentCategoryList as $parent)
                <li>
                    <a href="{{ route('admin_article_list_parent', ['parent' => $parent->id]) }}">
                        {{ $parent->name }}
                    </a>
                    @if (isset($childCategoryList[$parent->id]))
                        <ul>
                            @foreach ($childCategoryList[$parent->id] as $child)
                                <li>
                                    <a href="{{ route('admin_article_list_child', ['child' => $child->id]) }}">
                                        {{ $child->name }}
                                    </a>
                                </li>
                            @endforeach
                        </ul>
                    @endif
                </li>
            @endforeach
        </ul>
    </section>
    @endif

// ...省略...