Vue SPA x Laravelでつくる実務パチモンアプリその1:アプリの概要と環境構築
技術スタック LaravelPHPJavascriptVue.js

Vue SPA x Laravelでつくる実務パチモンアプリその1:アプリの概要と環境構築

2022.03.02

こんにちはjunです。仕事で中規模プロジェクトのディレクターとしてアサインされて、半年ほどブログを書けませんでした。ようやく最近時間が出てきたので新しいシリーズ記事を作成しようと思いました。とにかく最近1年はシステムばっかり作っていました。それぞのれプロジェクトでは

  • CRUDなAPI
  • 管理画面の構築
  • ユーザー権限によるアクセス制限
  • ログイン・ログアウト
  • ジョブ・キューを用いた長い処理

など使用するシステムの構築を多く行い、いろいろ学ぶことできました。その中で「CRUDなAPI」を考えた「管理画面」の構築をすることが多くありました。バックエンドはLaravelを、フロントエンドはVue.jsを使用していました。Vue.jsのおかげで高速にリッチなUIを構築し、システムを開発することができました。

この知見を共有し、まとめるためにも今回は

  • 管理画面はVue.js SPA
  • web APIによるCRUD操作
  • ルーティング設計
  • バリデーション
  • MVCによるアプリケーション設計
  • laravel/permissionを用いたユーザー権限

以上の様な機能を持ったデモアプリを作ろうと思います。Laravelを用いたシステム開発と、Vue.jsによる管理画面フロントエンド開発を解説していきます。

作るアプリの概要

今回のアプリはn○teみたいなブログサービスを作ります。CRUDや管理画面の構築をメインに行いたいのでシンプルにいきます。

機能概要

ざっくりとした機能概要は以下のとおりです。

ユーザー系の特徴

  • 利用する際にはユーザーとしてアカウントを作る(今回は全てゲストとする)。
  • ログインはアドレスとパスワードを使用する。
  • アプリを利用する一般ユーザーと管理を行う管理ユーザーが存在する。
  • 管理ユーザーは特定の管理用ルートから入る。
  • 退会可能。退会時は関連するデータは削除される。
  • プロフィールでは以下の項目を持つ
    • ユーザー名(仮名)
    • プロフィール文
    • アバター写真

ブログ機能

  • ブログを作成することができ、公開することができる。
  • ブログは以下の項目を持つ
    • タイトル
    • 内容(リッチテキスト)
    • タグ(任意)
    • 公開日時
  • 下書きとして保存することができる。更新時も下書き可能。
  • 任意数のタグを添付できる。タグはユーザーが新しく作成できる。
  • 削除可能
  • 画像の添付が可能。
  • アップロードした画像は管理できる。

一覧検索機能

  • サイトトップは投稿された記事が新着順に並ぶ。
  • 任意のタグを選んで一覧表示することが可能。
  • 部分一致検索も一応可能とする。

アプリケーションアーキテクチャー

バックエンドにはLaravel9、管理画面はVue.js(2系)を使用して構築します。なおVue.jsはSPA構成とします。記事の一覧や詳細画面などの公開側はLaravelのレンダリングで表示します。

デザインに関してはセンスが皆無なので管理画面・公開側ともにBootstrapを使用します。

環境構築

ではまずは環境構築を行っていきましょう。環境構築にはDockerを使用してLAMP環境を作ります。こちらの記事を参考にし、

  • mysql5.7
  • phpmyadmin
  • apache2.4
  • php8.1

以上の構成を作成したいと思います。ディレクトリを作成してdocker-compose.yamlを作成します。

mkdir ~/laravel_vue
cd  ~/laravel_vue

touch docker-compose.yaml
mkdir html
mkdir web_1
cd web_1
touch Dockerfile

html/という名前で作成したディレクトリにLaravelのソースが作成され、Dockerコンテナにマウントされる様にします。web_1/ディレクトリにはphpとapacheが構築できるDockerfileを作成してビルドします。

docker-compose.yamlでDBとapache+phpと連結したいと思います。

Dockerfile設定

まずはapacheとphpのイメージをDockerfileを作成します。

web_1/Dockerfile
FROM php:8.1-apache
RUN apt update \
        && apt install -y g++ libicu-dev libpq-dev libzip-dev zip zlib1g-dev \
        && mv /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled
RUN docker-php-ext-install pdo pdo_mysql
WORKDIR /var/www/html
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \
    && apt-get install -y nodejs

このファイルではphpとapacheが入った環境にてLaravelの依存PHPモジュールのインストールとcomposerをインストールする内容を記述しています。そしてLaravelのアセットビルドにはnode.jsを使用するのでそのインストールも記述しています。

apacheの設定ファイルを作成

Laravelのドキュメントルートを設定するためにapacheの設定ファイル作成して、マウントできる様にします。

cd web_1
touch default.conf
default.conf
<VirtualHost *:80>
    ServerName laravel_docker
    DocumentRoot /var/www/html/public

    <Directory "/var/www/html/public">
        AllowOverride All
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

このファイルはコンテナの/etc/apache2/sites-enabled/000-default.confにマウントされます。

docker-compose.yamlを作成

次にdocker-comose.yamlを作成してDBとphpmyadmin

docker-comose.yaml
version: '3'
services: 
  web_1:
    build: ./web_1
    depends_on: 
      - db
    volumes: 
      - ./html/:/var/www/html/
      - ./web_1/default.conf:/etc/apache2/sites-enabled/000-default.conf
    ports: 
      - "8005:80"
  phpmyadmin:
    image: phpmyadmin
    restart: always
    ports:
      - "8080:80"
    environment:
     - PMA_ARBITRARY=1
     - PMA_HOST=db:3306
     - PMA_USER=root
     - PMA_PASSWORD=rootroot
  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    environment:
      MYSQL_DATABASE: preform
      MYSQL_USER: test
      MYSQL_PASSWORD: testtest
      MYSQL_ROOT_PASSWORD: rootroot
      TZ: Asia/Tokyo
    ports: 
      - "3306:3306"
    volumes: 
      - vue_laravel:/var/lib/mysql
volumes: 
  vue_laravel: {}

web_1サービスでapacheとphpの環境をビルドします。そしてhtml/をコンテナ内の/var/www/html/にマウントされます。ubuntuのapacheは/etc/apache2/sites-enabled/配下にconfファイルを設置することで設定を追加したりオーバーライドできます。

phpmyadminサービスでphpmyadminを起動してDBの内容を編集しやすくします。dbサービスではmysqlの環境を作成します。ボリュームの設定をして永続化を行います。以上の設定を行ったらコンテナを立ち上げます。

docker-compose up -d

Creating laravel_vue_phpmyadmin_1 ... done
Creating laravel_vue_db_1         ... done
Creating laravel_vue_web_1_1      ... done

そしてコンテナ内に入ってLaravelをインストールしていきます。

docker exec -it laravel_vue_web_1_1 /bin/bash

root@a790844c74d6:/var/www/html# composer 
root@a790844c74d6:/var/www/html# composer create-project laravel/laravel ./

これで/var/www/html配下にLaravelプロジェクトが入ります。コンテナの /var/www/htmlはホストマシンのhtml/に同期されます。

html/配下にソースが生成されたのを確認しましたら、.envファイルにDBの接続設定を記述します。

.env
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=rootroot

phpmyadminとかでlaravelデータベースは作成しておいてください。DB_HOSTはdockerのDBのサービス名を入力します。設定したらブラウザでlocalhost:8005にアクセスします。以下の様なウェルカムページが表示されれば成功です。

(特に断りがない限り、以降ではDockerコンテナ内の操作とします。)

LaravelとVueセットアップ

それではアセットと認証機能のセットアップをしましょう。今回はlaravel/breezeをスターターキットとして利用します。

composer require laravel/breeze --dev

php artisan breeze:install
Breeze scaffolding installed successfully.
Please execute the "npm install && npm run dev" command to build your assets.

npm install
npm run dev
php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (23.69ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (10.45ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (10.60ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (14.54ms)

マイグレーションが完了したので登録などができる様になっているはずです。ひとまずLaravelのセットアップは以上となります。

とりあえずSPA構成ができるかチェック

次は管理画面のフロントエンドのセットアップをしていきます。管理画面はvue.jsで作成し、公開側コンテンツはLaravelのサーバーサイドレンダリングをします。ここではSPA構成のセットアップをします。

SPAのビューとルートの設定

/system配下を管理画面として構築していきます。以下の様なビューテンプレートとルートを作成します。

routes/web.php
Route::get('/system/{path?}', function () {
    return view('admin');
})->where('path', '.*')->name('admin');

このルートは/system配下すべてのルートに対してadminビューを返すことを示しています。

resources/view/admin.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="csrf-token" content="{{ csrf_token() }}">

        <title>{{ config('app.name', 'Laravel') }}</title>

        <!-- Fonts -->
        <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap">

        <!-- Styles -->
        <link rel="stylesheet" href="{{ asset('css/app.css') }}">

    </head>
    <body>
        <div class="font-sans text-gray-900 antialiased">
            <div id="app">
                <router-view/>
            </div>
        </div>
    </body>
    <!-- Scripts -->
    <script src="{{ asset('js/admin/index.js') }}" defer></script>
</html>

テンプレートは上記の様にして<div id="app"><router-view/></div>を設置して、vueのエントリーポイントと、vueのビルドファイルを読み込む様にします。実際はヘッダーなどを分けたほうがいいですが、今はとりあえずこんな感じでOKです。 次に'js/admin/index.jsで読み込ませるjsファイルを作成していきます。

必要なライブラリをインストール

一昔前のlaravel/uiの時はvuebootstrapの設定がインストール時に自動設定されますが、今回のlaravel/breezealpinejstailwindcssが入っているので、vue一式を自分でインストールする必要があります。まずはVue・Vuex・Vue-Routerをインストールしましょう。

この記事を作成した2021年3月現在、Vue3がリリースされておりバージョンを指定しないと、それぞれ最新版がインストールされる可能性があります。この記事はVue2を用いて解説しますのでバージョンを指定してインストールしています。
npm install vue@2 vue-loader@15 vue-template-compiler@2 --save-dev
npm install vuex@3 vue-router@3

SPA用のJSファイルを作成する

それではresources/js配下にSPAのファイルを作成を行います。以下の様にファイルとディレクトリを作成してください。

js
├── admin
│   ├── index.js
│   ├── router.js
│   └── store.js
└── vue
    └── page
        ├── Home.vue
        └── Profile.vue

store.jsとrouter.jsは以下の様にします。

store.js
export default {
    state:{},
    getters: {},
    mutations: {},
    actions: {}
}

storeはひとまず必要な型だけ準備します。

router.js
import Home from '~js/vue/page/Home.vue';
import Profile from '~js/vue/page/Profile.vue';

const routes = [
    { path: '/system', component: Home },
    { path: '/system/profile', component: Profile },
]

export default routes;

router.jsでは指定のパスに対してどのコンポーネントを出すかを定義します。~jsという記述は後で解説しますので、ひとまず記述してください。

router.jsで参照しているコンポーネントは以下の様にしておきます。

Home.vue
<template>
    <div>
        home
        <router-link to="/system/profile">profile</router-link>
    </div>
</template>
<script>
export default {
    name:'home'
}
</script>
Profile.vue
<template>
    <div>
        profile
    </div>
</template>
<script>
export default {
    name:'profile'
}
</script>

index.jsは以下の様に記述します。

index.js
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

import Vue from 'vue';

import Vuex from 'vuex';
import index from './store';
Vue.use(Vuex);
const store = new Vuex.Store(index);

import VueRouter from 'vue-router'
import routes from './router';
Vue.use(VueRouter)
const router =  new VueRouter({mode: 'history',routes})

const app = new Vue({
    store,
    router,
}).$mount("#app");

axiosはLaravelインストール時に入っているのでそのまま利用しています。このファイルではVuexとVue-routerの連携を行い、最終的に<div id="app"></div>にレンダリングされる様にします。

上記のファイルを作成した後、webpac.mix.jsを修正します。

mixファイルの作成

このようなVueのプロジェクトwebpackを使用しますがLaravelは簡単な記述でresources配下を簡単にpublic/配下に出力してくれます。またvueやsassのコンパイル設定をwebpack.config.jsの様に書く必要がありません。どのファイルをコンパイル対象にするかなどはwebpack.mix.jsに記載します。以下の様に修正します。

webpack.config.js
const mix = require('laravel-mix');
const path = require('path');

mix.webpackConfig({
    resolve: {
      alias: {
        '~js': path.resolve('./resources/js'),
      }
    }
});
mix.js('resources/js/admin/index.js', 'public/js/admin').vue();

mix.webpackConfigはのようにwebpack.config.jsに書く様な他の細かいwebpackの設定を定義でき、ここではエイリアスを定義しています。

'~js': path.resolve('./resources/js')という記述は~jsというパスの記載があった場合は「resources/jsまでの絶対ルート」であるとwebpackに支持しています。この様にエイリアスを定義することで相対パスによるファイルの参照がなくなります。router.jsで以下の様に定義していましたが、

router.js
import Home from '~js/vue/page/Home.vue';
import Profile from '~js/vue/page/Profile.vue';

もしエイリアスが使えない場合は

router.js
import Home from '../vue/page/Home.vue';
import Profile from '../vue/page/Profile.vue';

このように相対パスになってしまい、もし構成を変えようとした時に相対関係の修正が必要となります。その対策としてエイリアスを定めておくと今後の管理がしやすいです。'~js': path.resolve('./resources/js')はjsディレクトリを参照する様にしています。

mix.js('resources/js/admin/index.js', 'public/js/admin').vue(); にてindex.jsをソースとして'public/js/admin'配下に出力し、vueコンパイルを行う様に定義してます。

問題なければnpm run prodをプロジェクト ルートでコマンドを叩いてコンパイルを行います。完了後にpublic/js/admin/index.jsというものが出力されていることを確認してください。

反映の確認

jsファイルが出力されましたらhttp://localhost:8005/systemにアクセスします。以下の様に表示され、profileというリンクをクリックした際にURLが変わり、Profile.vueに書かれた内容が表示されればSPAはできています。

profileというリンクをクリック後 or http://localhost:8005/system/profileにアクセスしますと以下の様になります。

これでSPAが設定できたことを確認できました。

次回は..

今回は環境構築とLaravel、Vue SPAのセットアップまでとなります。来週はweb apiを通じたSPAでの認証と簡単なプロフィールの更新機能を作成してみます。

コメント

コメント読み込み中..

Copyright © 2021 jun. All rights reserved.