Ikeda's Blog

Laravelでブログサイトを作る 21. 管理画面・記事のプレビュー機能

目的

記事編集途中に、プレビュー表示して確認したい。

ルーティング

routes/web.php
プレビュー用のルーティングを追加します。更新と同様に、入力値をPOST送信する予定です。

// ...省略...

Route::group(['prefix' => 'admin', 'middleware' => 'auth', 'namespace' => 'App\\Http\\Controllers\\'], function() {
    // ...省略...

    Route::post('articlePreview', 'ArticleController@preview')->name('admin_article_preview'); // プレビュー

    // ...省略...
});

テンプレート

resources/views/admin/articleEdit.blade.php
プレビューボタンを設置します。
更新する時と同じく、入力内容をsubmitします。

{{-- 省略 --}}
<form method="post">
    {{-- 省略 --}}

    <input type="button" id="preview" value="プレビュー" />
    <input type="button" id="update" value="{{ isset($articleData->id) ? '更新' : '登録' }}" />
</form>
{{-- 省略 --}}

<script>
    $(document)
        .on('click', '#preview', function(){
            $(this).parents('form').attr('action', '{{ route('admin_article_preview') }}').attr('target', '_blank');
            $(this).parents('form').submit();
        })
        .on('click', '#update', function(){
            $(this).parents('form').attr('action', '{{ route('admin_article_update') }}').attr('target', '');
            $(this).parents('form').submit();
        })
    ;
    </script>

Controller

app/Http/Controllers/ArticleController.php

記事詳細表示の共通化

フロントの記事詳細画面と、プレビュー表示で共通化できる部分が多いので、先に対応します。
(記事の詳細表示するcontent()の一部分を抜き出す。抜き出した箇所にはreturn $this->articleView($articleData, $articleChildrenData);を記述する)

    /**
     * 記事1件分のページ表示(フロントの記事詳細と、管理画面のプレビュー機能から)
     * @param $articleData
     * @param $articleChildrenData
     * @return mixed
     */
    private function articleView($articleData, $articleChildrenData) {
        // 親カテゴリを取得
        $parentCategoryList = $this->parentCategory->orderBy('number', 'asc')->orderBy('id', 'asc')->get();

        // 子カテゴリは、キーを親カテゴリIDにした連想配列にする
        $data = $this->childCategory->orderBy('number', 'asc')->orderBy('id', 'asc')->get();
        $childCategoryList = [];
        foreach ($data as $item) {
            $childCategoryList[$item->parent][] = $item;
        }

        // 目次対応
        $articleData->body = $this->makeIndex($articleData->body);

        return view('front.article', [
            'articleData' => $articleData,
            'articleChildrenData' => $articleChildrenData,
            'parentCategoryList' => $parentCategoryList,
            'childCategoryList' => $childCategoryList,
            'parentNum' => $this->getParentArticleNum(),
            'childNum' => $this->getChildArticleNum(),
            'newArticleData' => $this->getNewArticleList(),
        ]);
    }

プレビュー表示

内容はシンプルで、

  1. 入力値を取得して変数に格納する
  2. 本来はDBから取得する記事データを、入力値にする
    • JOINで取得する親カテゴリ名を別途取得してセットする
  3. 記事と関連付けられている子カテゴリは、入力値から子カテゴリのリストとして取得する
    という感じです。
    これらの情報を、先程の共通化メソッドに渡してやれば、ページ表示できます。
    /**
     * プレビュー表示更新
     *
     * @param Request $request
     * @return mixed
     */
    public function preview(Request $request)
    {
        // 入力値取得
        $id = $request['id'];
        $tiitle = $request['title'];
        $body = $request['body'];
        $parent = $request['parent'];
        $childList = $request['child'];
        $open = $request['open'];
        $private = $request['private'];
        $description = $request['description'];

        // 記事取得
        $articleData = new Article();
        $articleData->title = $tiitle;
        $articleData->body = $body;
        $articleData->parent = $parent;
        $articleData->open = $open;
        $articleData->private = $private;
        $articleData->description = $description;

        // 親カテゴリ名を保持させる
        $parentData = $this->parentCategory->where('id', $parent)->first();
        $articleData->name = $parentData->name;

        // 記事と関連付けられている子カテゴリの情報を取得
        $articleChildrenData = null;
        if (is_array($childList)) {
            $articleChildrenData = $this->childCategory->whereIn('id', array_keys($childList))->get();
        }

        return $this->articleView($articleData, $articleChildrenData);
    }