Laravel+Vueでフォーム作成ツールを制作【ホーム画面を作ろう】
こんにちは。あきのです。一般人です。
今回は、フォーム作成ツールのホーム画面を作りましょう。
イメージはこんな感じ。
ホーム画面
ここで学べることは。。。
- Vue.jsのコンポーネント作成
- Vue.jsのrouter(URL設定)の使い方
- Laravelのコンポーネント作成
では、さっそくやっていきましょう。
・環境情報
OS: Windows10
ローカル開発環境ツール:XAMPP
サーバー:Xserver
・使用言語
PHP: 7.4.11
Laravel: 8.29.0
Vue.js: 2.6.12
MySQL: 5.7以上
tailwindcss: 2.0.3
*XAMPP, Node.js, composerはすべて用意済みという仮定で進めていきます。
*ソースコード全体はこちら
プロジェクトの作成
まず、Laravelプロジェクトの作成をしていきます。
ターミナル(Power Shell)などを開いて以下のコマンドを入力。
composer create-project laravel/laravel setform
最後の”setform”は好きな名前で大丈夫ですが、統一させたい場合はこの名前にしてください。
入力後、ファイルの作成が行われますがちょっと長いです。ゆっくりしながら待ちましょう。
作成し終えたら、エディタ(VS codeなど)で開きます。
また、以下のコマンドを実行しておきましょう。
php artisan storage:link
これはstorage
フォルダ内にあるファイルをpublic
から参照できるようにするコマンドです。
本来はpublic
フォルダにあるものしかアクセスできないのですが、これにより間接的にstorage
内にあるファイルを取り出すことができるようになります。
Vue.jsなどをインストール
ターミナルで作成したプロジェクトに移動して以下のコマンドを打ちます。
npm install
するといろいろファイルが作成されていきます。
完了した後、package.json
というファイルを開いて見てください。
その中のdevDependencies
を以下のようにしましょう。
"devDependencies": {
"autoprefixer": "^10.2.4",
"axios": "^0.21.1",
"laravel-mix": "^6.0.6",
"lodash": "^4.17.19",
"postcss": "^8.2.6",
"resolve-url-loader": "^3.1.2",
"sass": "^1.32.8",
"sass-loader": "^8.0.2",
"tailwindcss": "^2.0.3",
"vue": "^2.6.11",
"vue-loader": "^15.9.5",
"vue-template-compiler": "^2.6.11",
"vue-router": "^3.5.1"
},
その後、もう一度npm install
を実行してください。
ここでやっていることは主に…
- Vue.jsを使えるようにする
- tailwindcssを使えるようにする
- sassを使えるようにする
コンパイル設定
webpack.mix.js
を開きます。
コメントより下にあるmix.js...
の部分を編集します。
mix.js('resources/js/app.js', 'public/js')
.js('resources/js/router.js', 'public/js')
.vue()
.sass('resources/sass/main.scss', 'public/css')
.postCss('resources/css/app.css', 'public/css', [
require('tailwindcss'),
]);
ここでやっていること。
ここでは、jsファイルやcssファイルの更新です。
WebページはCSSやJavaScriptの文法でしか動きません。
なのでVue.jsの文法は、Javascriptの文法に書き換えてあげないといけないということです。
その書き換えをここでやっています。
書き換えを実行するためにはターミナルで以下のコマンドを打ちます。
npm run dev
//または
npm run watch
npm run dev
は1回だけ実行。npm run watch
はファイルが編集されるたびに自動で実行してくれます。
後者のコマンドを使った方が今後は良いと思います。
bladeでレイアウトを作成
ホーム画面の大枠を作っていきます。
まず、以下のコマンドでサーバーを立ち上げます。
php artisan serve
今こんな感じになっているかと思います。
これは、resources/views/welcome.blade.php
が表示されています。
これを完成形のホーム画面にしていきます。
共通部分のコンポーネントを作成
まずは、ヘッダーなどの共通部分をコンポーネント化していきます。
ターミナルでコマンドを打ちます。
php artisan make:component AppLayout
これでapp/View/Components/AppLayout.php
というファイルができると思います。
この中にあるrender
メソッドの中身を変更していきます。
public function render()
{
return view('layouts.app');
}
次に、resources/views/layouts/app.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', 'Set Form')}}</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.2/css/all.css" integrity="sha384-vSIIfh2YWi9wW0r9iZe7RJPrKwp6bG+s9QZMoITbCckVJqGCCRhc+ccxNcdpHuYu" crossorigin="anonymous">
<!-- Styles -->
<link rel="stylesheet" href="{{mix('css/app.css')}}">
<link rel="stylesheet" href="{{mix('css/main.css')}}">
</head>
<body class="antialiased">
<div id="app">
<x-header></x-header>
<main class="py-8 bg-gray-100">
{{$slot}}
</main>
</div>
<!-- JS -->
<script src="{{mix('js/app.js')}}" defer></script>
</body>
</html>
ここでやっていること
これは、どのページに行っても使う共通のコードを書いています。
例えば、cssファイルやjsファイルをここで読み込むことで今後作っていくファイルにいちいち読み込みコードを書く必要が無くなります。
また、body
の中では、header
とmain
に分けています。
x-header
は後程作るheaderコンポーネントを読み込むコードです。
main
タグには{{$slot}}
という記述がありますが、ここには今後作っていくページが読み込まれていきます。
あと、<div id="app">
で一部囲っていますが、これはvue.jsを使う上で大事なので勝手に変更などはしないように。
cssファイル, jsファイル, headerコンポーネントを作成
このファイルでは、cssファイル、jsファイル、headerコンポーネントを読み込んでいるのでこれらのファイルも作成します。
それぞれは以下のように作成してください。
resources/css/app.css
は以下のようにします。
//tailwind cssを利用するための記述
@tailwind base;
@tailwind components;
@tailwind utilities;
//以下にwelcome.blade.phpに書かれているstyleタグの中身を貼りつけ
最初の3行はtailwind cssを利用するためのコードです。tailwind cssというものがあまり聞きなれないかもしれませんが、bootstrapのようなものだと今は認識しておいてください。
resources/js/app.js
は以下の通りです。
require('./bootstrap');
//vueのインポート
import Vue from 'vue'
import router from './router'
//vue.jsを使うための初期設定
const app = new Vue({
el: '#app',
router: router,
})
最初の数行でvueとrouterをインポートしておきます。
そして、Vueインスタンスというものを作ります。つまり初期設定です。
el
はvue.jsを適用するタグのid属性を入れます。これは先ほどのapp.blade.php
で説明したdiv
タグです。
router
は後程説明しますがurlの設定のことです。
最後にresources/components/header.blade.php
を作成してコードを書きます。
<div class="h-16 flex items-center shadow-2xl">
<img src="/storage/img/logo.png" alt="logo" class="w-1/4">
</div>
これがx-header
タグを使うことで読み込まれます。
そして最後にresource/views/welcome.blade.php
の中身をすべて消して、以下に書き換えます。
<x-app-layout>
<router-view></router-view>
</x-app-layout>
x-app-layout
は先ほどのapp.blade.php
を読み込んでいます。
router-view
タグもとあるファイル(コンポーネント)を読み込んでいます。
これは後ほど設定するルーティングで決まるんですが、URLに応じたコンポーネントをここに入れ込むという具合です。
ここまでやると画像のように上にロゴがついたヘッダーが画面ができます。
ホーム画面用のVueコンポーネントを作成する
実際にページを作っていきます。
ここからはVueコンポーネントを作っていきます。概念はLaravelのコンポーネントと同じです。
resources/js/components/home/Index.Vue
というファイルを作成します。
そして、ひな形として以下のコードを書きましょう。
<template>
//ここにhtml
</template>
<script>
export default {
//ここにVue.js
}
</script>
template
タグの中にはhtmlを普通に書き込んでいけばOKです。
またscript
タグにはこのコンポーネントを内で適用する処理(関数)をJavascriptで書きます。
完成系は以下の通りです。
<template>
<div class="lg:container mx-auto md:px-4">
<div class="md:flex items-center justify-center">
<img src="/storage/img/header.png" alt="header" class="w-full md:w-3/4 max-w-2xl">
<div>
<p class="font-bold text-2xl lg:text-3xl text-center md:text-left">
登録不要<br>
サクッとアンケート作成
</p>
<div class="flex justify-center md:justify-start">
<router-link :to="{name: 'form.create'}" class="inline-block my-3 bg-indigo-300 py-3 px-5 rounded-full text-white font-bold focus:outline-none hover:bg-indigo-200 duration-300">今すぐ作成する</router-link>
</div>
</div>
</div>
<div class="feature my-10">
<h2 class="font-bold text-3xl text-center bg-indigo-200 py-2 rounded-md">3つの特徴</h2>
<div class="sm:grid grid-cols-3 gap-4 my-5 mx-5">
<div class="mb-20">
<h3 class="font-bold text-xl text-center">ユーザー登録不要</h3>
<div class="my-3">
<p class="sm:h-28 mb-5 sm:mb-0">登録、ログインなどの手間が省け今すぐ始めることができます。</p>
<img src="/storage/img/feature.png" alt="feature" class="w-48 sm:w-3/4 sm:h-3/4 m-auto rounded-full">
</div>
</div>
<div class="mb-20">
<h3 class="font-bold text-xl text-center">素早く作成</h3>
<div class="my-3">
<p class="sm:h-28 mb-5 sm:mb-0">シンプルなデザインで、タイトルと入力タイプを決めるだけで作れます。</p>
<img src="/storage/img/feature1.png" alt="feature1" class="w-48 sm:w-3/4 sm:h-3/4 m-auto rounded-full">
</div>
</div>
<div class="mb-20">
<h3 class="font-bold text-xl text-center">スプレッドシートで管理</h3>
<div class="my-3">
<p class="sm:h-28 mb-5 sm:mb-0">回答結果はGoogleスプレッドシートで自動で管理できます。</p>
<img src="/storage/img/feature2.png" alt="feature2" class="w-48 sm:w-3/4 sm:h-3/4 m-auto rounded-full">
</div>
</div>
</div>
</div>
<div class="guide my-5">
<h2 class="font-bold text-3xl text-center bg-indigo-200 py-2 rounded-md mb-5">作成方法</h2>
<div class="mx-5">
<div class="guide-1 my-5 p-3 max-w-2xl mx-auto border-2 border-gray-300">
<h3 class="font-bold text-lg sm:text-xl sm:text-center mb-3">アンケート作成画面で入力画面を作成</h3>
<div class="sm:flex items-center justify-center">
<img src="/storage/img/guide0.png" alt="guide0" class="w-full max-w-md">
<p class="mt-5 md:mt-0">
タイトルと入力タイプを追加します。<br>
説明など細かい設定もできます。
</p>
</div>
</div>
<img src="/storage/img/arrow.png" alt="arrow" class="w-60 m-auto">
<div class="guide-2 my-5 p-3 max-w-2xl mx-auto border-2 border-gray-300">
<h3 class="font-bold text-lg sm:text-xl sm:text-center mb-3">IDを取得</h3>
<div class="flex items-center justify-center">
<p>
フォーム作成後にIDが自動で生成されます。<br>
IDをURLに設定することでリンクを作ることができます。<br>
*URLは「https://setform.site/form/生成されたID」です。
</p>
</div>
</div>
<img src="/storage/img/arrow.png" alt="arrow" class="w-60 m-auto">
<div class="guide-3 my-5 p-3 max-w-2xl mx-auto border-2 border-gray-300">
<h3 class="font-bold text-lg sm:text-xl sm:text-center mb-3">スプレッドシートにコード貼りつけ</h3>
<div class="flex items-center justify-center">
<p>
<a href="https://gist.github.com/24820c0aa19343d37aa636d671128dc0.git" class="underline ">「こちら」</a>のコードをGoogleスプレッドシートのスクリプトエディタに貼り付けます。
</p>
</div>
</div>
</div>
<div class="flex justify-center">
<router-link :to="{name: 'form.create'}" class="inline-block my-3 mx-auto m-auto bg-indigo-300 py-3 px-5 rounded-full text-white font-bold focus:outline-none hover:bg-indigo-200 duration-300">さっそく作成</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
}
</script>
tailwind cssを使っているのでクラスが分かりづらいかもしれませんが、詳しくはtailwind cssについて調べてみてください(僕のブログでも解説しますが)。
最初のトップページなのでscript
内には特に記述は必要ないです。
ここでやっていること
ここでのポイントはrouter-link
というものです。
vue.jsにはrouter
というものがあって、URLに応じてどのコンポーネントを読み込むかを設定できます。
Laravelが分かる方はweb.php
に当たるものです。
routerはこの後出てくるのですが、動的にa
タグを生成することができるものです。
routerの設定
routerの設定をします。
resources/js/router.js
を作成します。説明はコードを書いてから説明します。
// vueおよびvue-routerの読み込み
import Vue from 'vue'
import VueRouter from 'vue-router';
Vue.use(VueRouter);
//コンポーネントの読み込み
import Index from './components/home/Index.vue'
//ルート設定
export default new VueRouter({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Index
},
]
})
ここでやっていること
重要なのはこの部分です。
routes: [
{
path: '/',
name: 'home',
component: Index
},
]
ここでルート設定を行っています。
ルートとは、「ooというURLを打ったらxxコンポーネントを読み込みますよ」というものです。
1つのルートごとに{}
で追加していきます。
書き方はこんな感じ。
{
path: URLを設定,
name: URLの代わりになる名前を設定,
component: コンポーネントの名前
},
これを設定すると「path
に設定したurlを入れたらcomponent
に設定したコンポーネントを読み込む」ということになります。
ちなみにname
については、例えばpath
を'/home/index'
としてname
を'home'
にすると、この'home'
という名前を使ってURLを指定することができます。
name
を使うことで、途中でURLを変えたとしてもname
を変更しなければリンク切れなどが起きずに済むので便利です。
今回はこのように設定しました。
routes: [
{
path: '/',
name: 'home',
component: Index
},
]
つまり「http://example.com/
にアクセスしたらIndex.Vue
ファイルを読み込む」ということになります。
そして、このファイルが最初に作ったLaravelコンポーネントapp.blade.php
の{{slot}}
にハマるということになります。
Laravelのルート設定
最後です。
このプロジェクトではLaravelのルーティングは使いません(Vue.jsですべて処理するので。)
が、1つだけ設定をつけます。
routes/web.php
の中身で、コメント以降のコードをこのように書き換えてください。
Route::get('/{any}', function () {
return view('welcome');
})->where('any', '.*');
これは、「どんなURLが入力されてもwelcome.blade.php
を読み込んでくださいね。」という命令をしています。
welcome.blade.php
はすべての起点となるファイルです。
というのも、このファイルの中にVueコンポーネントを入れ込むわけですから、どんなURLでもまずはこのファイルを読み込んで欲しいわけです。
ここまで、やるとホーム画面は完成です。
ふぅ、疲れました。ではでは、休んで次に行きましょう。
(随時更新)
スポンサードサーチ