- 投稿日:2020-03-17T23:50:55+09:00
Laravel7.XでVue.jsを実装してみる
npmを起動してみる
npm run watchを叩くと以下のエラーメッセージが出力
terminal'cross-env' is not recognized as an internal or external command, operable program or batch file.こちらのリンクを参考にして解決
https://stackoverflow.com/questions/45034581/laravel-5-4-cross-env-is-not-recognized-as-an-internal-or-external-commandBootstrap-Vueの実装
こちらのドキュメントを参考に実施(https://bootstrap-vue.js.org/docs)
1) npmでbootstrap-vueをインストール
terminal# With npm npm install vue bootstrap-vue bootstrap2) bootstrap-vueをインポート
resources\js\bootstrap.jsimport Vue from 'vue' import { BootstrapVue, IconsPlugin } from 'bootstrap-vue' import 'bootstrap/dist/css/bootstrap.css' import 'bootstrap-vue/dist/bootstrap-vue.css'3) BladeとVueファイルをVueに合わせて構成
(作成中…)
Laravel5.xではVue環境が構築されていた気がするが(Example-component等)
7.xはない…
- 投稿日:2020-03-17T23:49:31+09:00
Laravel DBクラスを利用(SQL文を使ってDB操作)
使い方
use Illuminate\Support\Facades\DB;# 例 DB::select('select * from テーブル名') $items = DB::select('select * from people'); #この例ではpeopleテーブルを全て呼び出しパラメータ結合
# 例 id検索 $param = ['id' => $request->id]; $items = DB::select('select * from people where id = :id', $param);インサート
DB::insert(クエリ文, パラメータ配列);viewにidを渡す
下記のようにするとurlにidを含めることができる
HogeController.phppublic function edit(Request $request){ $params = ['id' => $request->id]; # select文でurlで指定したidデータを取得(今回はエラー処理していないのでidがなければコケる) $item = DB::select('select * from people where id = :id', $params); return view('hello.edit', ['form' => $item[0]]); }web.phpRoute::get('/hoge/edit/{id}', 'HogeController@edit');コントローラで
['form' => $item[0]
をviewに渡しているので$form
が使えるview.blade.php<table> <form action="/hoge/edit" method="post"> {{ csrf_field() }} <input type="hidden" name="id" value="{{ $form->id }}"> <tr> <th>name: </th> <td><input type="text" name="name" value="{{ $form->name }}"></td> </tr> <tr> <th>email: </th> <td><input type="text" name="email" value="{{ $form->email }}"></td> </tr> <tr> <th>age: </th> <td><input type="text" name="age" value="{{ $form->age }}"></td> </tr> <tr> <th></th> <td><input type="submit" value="送信"></td> </tr> </form> </table>update
HogeController.phppublic function update(Request $request){ $params = [ 'id' => $request->id, 'name' => $request->name, 'email' => $request->email, 'age' => $request->age ]; DB::update('update people set name = :name, email = :email, age = :age where id = :id', $params); return redirect('/hoge'); }web.phpRoute::post('/hoge/edit', 'HelloController@update');
- 投稿日:2020-03-17T19:44:57+09:00
Laravelでよく使うコマンド集
概要
ここでは、Laravelの初心者向けによく使うコマンドの説明をする。
基本的にはphp artisan なんとかー
が多い。Laravelで使用するコマンド集(よく使うものだけ)
composer dump-autoload
composer dump-autoload自身で作成したクラスのファイルをフレームワークに認識させる。
これを行うことでrequire('ファイル名')
やrequire_once('ファイル名')
が不要になる。
詳しくは、ここをチェック。php artisan migrate
php artisan migrateこのコマンド1発で、Laravelで使用する全テーブルのCREATE文が実行される感じ。
対象のテーブル定義は、php artisan make:migration
で作成する。php artisan db:seed
php artisan db:seedこのコマンド1発で、空っぽのテーブルに初期データを入れられる。
初期データの定義は、php artisan make:seeder
で作成する。php artisan make:migration
php artisan make:migration [テーブル名]テーブル作成用のクラスを作成する。
DB:insertなどを使用してCREATE文となる基を記述する。
Laravelは基本的にSQLを書くことはない。
詳しくは、https://readouble.com/laravel/6.x/ja/migrations.htmlが参考になる。php artisan make:seeder
php artisan make:seeder [テーブル名(アッパーキャメル記法)]Seeder ↓例(テーブル名「m_user_types」の場合)↓ php artisan make:seeder MUserTypesSeeder初期データのINSERTとなるレコードを記述する。
詳しくは、https://readouble.com/laravel/6.x/ja/seeding.htmlが参考になる。
これをやると、マスターデータなどコマンド1発で全て入る。
環境セットアップに便利!shutdown
shutdown -s -t [秒数]「お疲れ様でした。お先に失礼します。」って言う直前によく打つコマンド
指定した秒数が経過すると、自動でシャットダウンされます。
あとは、気が向いたらまた続きを書きます。
コントローラや他のことについて。。。
- 投稿日:2020-03-17T18:26:15+09:00
Laravelでネストが深いバリデーションエラーメッセージを返す
今回はLaravelのバリデーションのエラーメッセージの話です。
Laravel で確認していますがでも同じだと思います。https://laravel.com/docs/7.x/validation
https://readouble.com/laravel/7.x/ja/validation.html通常のバリデーション
Laravelでは、普通に作ると以下のような構造で
$errors
にエラーメッセージが保存され、それをビューで使用します。// 例えば、 $request->validate([ 'title' => 'required|string|max:100', 'body' => 'required|string|max:255', ]); // というバリデーションだと、$errorsには、 $errors = [ 'title' => ['The title field is required.'], 'body' => ['The body field is required.'] ] // それぞれのフィールドに対してメッセージの配列が作られます。通常は、ビューでこれをそのまま使えば問題ありません。
上記は$request->validate()
を書くだけで、エラーの場合は自動でエラーメッセージを含むレスポンスを作成してくれますが(フォームリクエストも然り)、何かしら複雑な事情があって手動でレスポンスを作りたい場合も、ありますよね
その場合は、use Illuminate\Validation\ValidationException; use Illuminate\Support\Facades\Validator; ... $validator = Validator::make([], []); $validator->errors()->add('title', 'タイトルのエラーです。'); throw new ValidationException($validator); // もしくは throw ValidationException::withMessages(['title' => 'タイトルのエラーです。']); ...こうやって
$validator->errors()->add($key, $message)
することで、自由にメッセージを追加することができます。ネストが深いバリデーションエラーメッセージ
ここからが本題です
上で見たように、エラーメッセージは基本的に2次元配列です。
しかし、エラーメッセージの構造をもっと階層的にしたい場合もあります。// 例えば、 [ 'この' => [ 'エラーメッセージは' => [ 'とても' => [ '深いです' => [ 'とてもとても深いエラーメッセージ' ] ] ] ] ]これを上記の
add()
またはwithMessages()
でやってもうまくいきません。
ダンプして確認してみます。$errors = [ 'この' => [ 'エラーメッセージは' => [ 'とても' => [ '深いです' => [ 'とてもとても深いエラーメッセージ' ] ] ] ] ]; $validator = Validator::make([], []); $validator->errors()->add('この', $errors['この']); dd($validator->errors()); /** Illuminate\Support\MessageBag {#263 ▼ #messages: array:1 [▼ "この" => array:1 [▼ 0 => array:1 [▼ "エラーメッセージは" => array:1 [▼ "とても" => array:1 [▼ "深いです" => array:1 [▼ 0 => "とてもとても深いエラーメッセージ" ] ] ] ] ] ] #format: ":message" } */何故か、「この」と「エラーメッセージは」の間に配列が挟まっていますね
withMessages()
でも同様になります。
どういうことでしょうか。
$validator->errors()->add()
のadd()
はMessageBag
のadd()
です。
それを調べてみます。vendor/laravel/framework/src/Illuminate/Support/MessageBag.php/** * Add a message to the message bag. * * @param string $key * @param string $message * @return $this */ public function add($key, $message) { if ($this->isUnique($key, $message)) { $this->messages[$key][] = $message; } return $this; }
$this->messages[$key] = $message;
ではなくて、$key
で配列を作って、その中に$message
を入れています。
だから配列が挟まっていたのです。
ValidationException::withMessages()
では、vendor/laravel/framework/src/Illuminate/Validation/ValidationException.php/** * Create a new validation exception from a plain array of messages. * * @param array $messages * @return static */ public static function withMessages(array $messages) { return new static(tap(ValidatorFacade::make([], []), function ($validator) use ($messages) { foreach ($messages as $key => $value) { foreach (Arr::wrap($value) as $message) { $validator->errors()->add($key, $message); } } })); }こちらでも、
MessageBag
のadd()
を使っています。
従って同様に配列が差し込まれます。
どうしたらいいのでしょうか。解決策はmerge()
merge()
を使いましょう。
これなら余計な配列は作られません。$errors = [ 'この' => [ 'エラーメッセージは' => [ 'とても' => [ '深いです' => [ 'とてもとても深いエラーメッセージ' ] ] ] ] ]; $validator = Validator::make([], []); $validator->errors()->merge($errors); dd($validator->errors()); throw new ValidationException($validator); /** Illuminate\Support\MessageBag {#263 ▼ #messages: array:1 [▼ "この" => array:1 [▼ "エラーメッセージは" => array:1 [▼ "とても" => array:1 [▼ "深いです" => array:1 [▼ 0 => "とてもとても深いエラーメッセージ" ] ] ] ] ] #format: ":message" } */
merge()
を使うことでエラーメッセージの構造を崩すことなく、深い階層構造を持つエラーメッセージを返すことができました
- 投稿日:2020-03-17T17:47:36+09:00
LaravelのQueryBuilderのfirst()で結果が無かった時の処理と空判定
はじめに: LaravelのQuerybuilderのfirst()がどんな動きをしているか確認
書きの記事を参考にしてLaravelのQuerybuilderのfirst()がどんな動きをしているか確認します。
QueryBuilderのfirst()の動きを調べてみた結果が無い場合の返り値
結果が無かったら
5.1ではnull
5.3から collect([])が返ってくるようですバージョンによって少し異なるようですがLaraevl6.4でlogger()で吐かせたところ
Objectの{}
が返却されていました。isEmpty()とかempty()で判定したい
colectionでもarrayでも無いのでできません。
さえ、どうしましょう。。。if (!$res->count()) { // coentが0の場合の処理 }今回はこんな感じにしました。
時間が無いので検証などできませんでしたが、今度時間がある時にもう少し理解を深めたいと思います。
- 投稿日:2020-03-17T17:29:12+09:00
Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part4
前回のパート
前回は、全ページで使用するヘッダーの作成と会員登録の処理の実装を行いました
前回のパートはこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part3
今回は、前回実装し登録をした内容を利用してログイン機能の実装をしていこうと思いますログインフォームの実装(Vue側)
まずはログインフォームのview側の実装をしていきます
client/components
にLogin.vue
を作成して下記を追加してくださいLogin.vue<template> <div> <Header /> <div class="main-container"> <v-form v-model="valid"> <v-text-field v-model="form.email" :rules="emailRules" label="E-mail" required></v-text-field> <v-text-field v-model="form.password" :rules="passwordRules" label="Password" required type="password"></v-text-field> <v-btn small>submit</v-btn> </v-form> </div> </div> </template> <script> import Header from './Header'; export default { components: { Header }, metaInfo: { title: 'ログイン', htmlAttrs: { lang: 'ja' } }, created () { const user = this.$store.getters['auth/user']; if (user !== null) { this.$router.push('/todo'); } }, data () { return { form: { email: '', password: '', }, emailRules: [ v => !!v || 'E-mailを入力してください', v => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mailを正しく入力してください' ], passwordRules: [ v => !!v || 'パスワードを入力してください' ] } } } </script> <style> .main-container { width: 500px; margin: auto; } </style>前回の
Register.vue
と内容はほとんど同じなので
特に説明は必要ないかと思いますので、割愛します
説明が必要な方は、前回のパートに戻って確認してみてくださいではここにmethodを追加していきます
Register.vue<template> <div> <Header /> <div class="main-container"> <v-form v-model="valid"> <v-text-field v-model="form.email" :rules="emailRules" label="E-mail" required></v-text-field> <v-text-field v-model="form.password" :rules="passwordRules" label="Password" required type="password"></v-text-field> <v-btn small @click="login">submit</v-btn> //追加 </v-form> </div> </div> </template> <script> import Header from './Header'; export default { components: { Header }, metaInfo: { title: 'ログイン', htmlAttrs: { lang: 'ja' } }, created () { const user = this.$store.getters['auth/user']; if (user !== null) { this.$router.push('/todo'); } }, data () { return { form: { email: '', password: '', }, emailRules: [ v => !!v || 'E-mailを入力してください', v => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mailを正しく入力してください' ], passwordRules: [ v => !!v || 'パスワードを入力してください' ] } }, methods: { //追加 async login() { await this.$store.dispatch('auth/login', this.form); this.$router.push('/todo'); } } } </script> <style> .main-container { width: 500px; margin: auto; } </style>ログイン時のmethodを追加しました
内容は、auth.js
のlogin
アクションにフォームに入力された内容を渡しdipatchしています
その処理が終われば、/todo
のTodoページに遷移する様に設定してますでは次に、
auth.js
のlogin
アクションを定義していきます
'auth.js`に下記を追加してくださいauth.jsimport axios from 'axios'; const state = { user: null } const getters = { user: state => state.user } const mutations = { setUser (state, user) { state.user = user; } } const actions = { async register({ commit }, data) { const response = await axios.post('/api/register', data) commit('setUser', response.data); }, async searchUser({ commit }) { const response = await axios.get('/api/user'); const user = response.data ? response.data : null; commit('setUser', user); }, async login({ commit }, data) { //追加 const response = await axios.post('/api/login', data); commit('setUser', response.data); } } export default { namespaced: true, state, getters, mutations, actions }今回追加したアクションはLaravelで定義した、
/login
のルートに対して入力されたデータをPOSTし
その、情報を変数responseに格納しています
そして、その値をsetUser
mutationに対してcommitしstateのuserの値をセットしています
registerの時と同じ流れになります次に、Laravel側の実装をしていきます
Laravel側の実装
Vue側での
auth.js
でPOSTしていた/login
をルートに定義していきます
api.php
に下記を追加してくださいapi.phpRoute::post('/register', 'Auth\RegisterController@register')->name('register'); Route::post('/login', 'Auth\LoginController@login')->name('login'); //追加 Route::get('/user', function(){ return Auth::user(); });これで
auth.js
のlogin
アクションからaxiosでリクエストを投げられる様になりましたそして、part3で下記の記述を
LoginController.php
に追加してますのでこれでLaravel側での実装は完了ですLoginController.phpprotected function authenticated(Request $request, $user) //追加 { return $user; }上記までの記述で一通りログイン機能の実装が終わりました
ただ遷移する画面の/todo
をまだ用意していないので正常に画面が遷移することができないので
ここで、Todo.vue
コンポーネントを追加しておきましょう
client/components
にTodo.vue
ファイルを新規で作成してください
中身はこの様にしておいてくださいTodo.vue<template></template> <script></script> <style></style>次に
router.js
にコンポーネントを登録しておきます
router.js
に下記を追加してくださいrouter.jsimport Vue from 'vue'; import Router from 'vue-router'; import Login from '../components/Login'; import Register from '../components/Register'; import Todo from '../components/Todo'; //追加 Vue.use(Router); export default new Router({ mode: 'history', routes: [ { path: '/login', component: Login }, { path: '/signup', component: Register }, { path: '/todo', //追加 component: Todo } ] })ここまでできたらログインを試してみてください
正常であれば、ログイン後/todo
に遷移し真っ白な画面が表示されるかと思います終わりに
今回はログイン機能の実装を行いました
それに加えて、/todo
ページの用意も行いました次回は、ログアウト機能を実装したいと思います
次回のログアウト機能が終われば認証周りの実装は終わりですので、Todoを作っていく実装に入っていきます次回のパートはこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part5
- 投稿日:2020-03-17T17:28:37+09:00
Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part3
前回のパート
前回は、Authの導入とマイグレーションファイルを作成し
今回のTodoアプリで使用するテーブルの作成まで行いました
前回のパートはこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part2
今回は、全てのページで使うヘッダーの作成と認証周りの実装をやっていきますヘッダーコンポーネントの作成
全てのページで共通で使うヘッダーを作成していきます
Vuetifyで実装しますので、Vuetifyを使用しない方は自作での実装をしてください
まず、client/components
にHeader.vue
を作成し下記を追加してくださいHeader.vue<template> <v-card color="grey lighten-4" flat height="200px" tile> <v-toolbar dense> <v-app-bar-nav-icon></v-app-bar-nav-icon> <v-toolbar-title>Todo-List</v-toolbar-title> <v-spacer></v-spacer> <router-link to="/signup"> <v-btn icon> <v-icon>mdi-account</v-icon> </v-btn> </router-link> <router-link to="/todo"> <v-btn icon> <v-icon>mdi-align-horizontal-left</v-icon> </v-btn> </router-link> <router-link to="/login"> <v-btn icon> <v-icon>mdi-login</v-icon> </v-btn> </router-link> <v-btn icon> <v-icon>mdi-logout</v-icon> </v-btn> </v-toolbar> </v-card> </template>templateのみのシンプルな物です
各<v-btn>
を<router-link>
で囲み、会員登録やログインやログアウト、Todoページのリンクを設定しています
全てVuetifyになります
詳しく知りたい方はこちらを参照ください→こちら
これでヘッダーの用意は終わりです会員登録の実装
まずはVue側でフォームの実装をしていきます
client/components
にRegister.vue
を作成してください
Register.vue
にを下記の様に下記を追加してくださいRegister.vue<template> <div> <Header /> <div class="main-container"> <v-form v-model="valid"> //・・・① <v-text-field v-model="form.name" :rules="nameRules" label="Name" required></v-text-field> //・・・② <v-text-field v-model="form.email" :rules="emailRules" label="E-mail" required></v-text-field> <v-text-field v-model="form.password" :rules="passwordRules" label="Password" required type="password"></v-text-field> <v-text-field v-model="form.password_confirmation" :rules="repasswordRules" label="Confirm Password" required type="password"></v-text-field> <v-btn small>submit</v-btn> </v-form> </div> </div> </template> <script> import Header from './Header'; export default { components: { Header }, metaInfo: { //・・・③ title: '会員登録', htmlAttrs: { lang: 'ja' } }, data () { return { form : { name: '', email: '', password: '', password_confirmation: '', }, nameRules: [ v => !!v || '名前を入力してください', //・・・④ ], emailRules: [ v => !!v || 'E-mailを入力してください', v => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mailを正しく入力してください' //・・・⑤ ], passwordRules: [ v => !!v || 'パスワードを入力してください', v => v.length >= 8 || 'パスワードは8文字以上で入力してください' //・・・⑥ ], repasswordRules: [ v => !!v || 'パスワードの再入力を行ってください', v => v == this.form.password || 'パスワードが一致しません' //・・・⑦ ] } } } </script> <style> .main-container { width: 500px; margin: auto; } </style>①ここは全てVuetifyになります
ここでは簡単な説明はしますが、もっと詳しく知りたい方は、こちらをご覧ください→こちら②Vuetifyのフォームになります
:rules
この部分で下の④⑤⑥⑦のルールとバインディングしており、フロント側でのバリデーションを行っています
require
は入力必須を意味します
label
でフォームのラベル名に設定できます
②で設定しているものはどれも同じ要領です
次に設定しているバリデーションのルールについて軽く触れておきます
④入力の値が存在しているかどうか(未入力でないか)をチェックしています
⑤正規表現でEmailの形式かどうかをチェックしています
⑥パスワードが8文字以上で入力されているかをチェックしています
⑦passwordの入力値を一致しているかをチェックしています③part1でインストールしたVue Metaです
ここでは、titleを【会員登録】としてlangをjaに設定しています
Vue Metaをこの様な設定を行うために使用しますこれで、Vuetifyを使って簡単にフォームを用意できバリデーションまで行えました
次に会員登録機能の実装を行っていきます会員登録機能の実装(Laravel側)
まずは、
routes/api.php
を開きルートを定義していきます
/register
は会員登録用のルート
/user
はログインをしているのかを常時チェックするために用意したルートになります(この後のVue側の実装で再度説明します)api.php<?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::post('/register', 'Auth\RegisterController@register')->name('register'); //追加 Route::get('/user', function(){ //追加 return Auth::user(); });次に
app/Http/Controllers/Auth/RegisterCOntroller.php
を開いて下記を追加しますRegisterController.phpprotected function registered(Request $request, $user) //追加 { return $user; }
registerd()
メソッドをオーバーライドすることで
登録処理をした際にUser情報を返却できる様に設定できます
この値を使って今後認証を行うので、上記を追加しましたこのついでに
ログイン時にとログアウト時にも必要になる処理を先にやっておきます
app/Http/Controllers/Auth/LoginController.php
を開いて下記を追加してくださいLoginController.phpprotected function authenticated(Request $request, $user) //追加 { return $user; }こちらの追加の内容も、
registerd()
メソッドのオーバーライドをした際と同じ理由になり
ログイン時にUserの情報を返却する様に設定しています次に
LoginController.php
でさらにloggedOut()
メソッドを追加してくださいLoginController.phpprotected function loggedOut(Request $request) { $request->session()->regenerate(); return response('', 200); }こちらは、ログアウト時に呼ばれるメソッドになり
ログアウト時にセッションを再生成を行い、レスポンスを返す様にしてあります上記3つの追加点については、本記事作成でも参考にさせて頂いたこちらの記事を参照してください→こちら
以上で会員登録に必要なLaravel側の処理の実装は終わりです(ログイン時とログアウト時の設定も行いました)
会員登録処理(Vue側)
まず
Register.vue
に下記を追加してくださいRegister.vue<template> <div> <Header /> <div class="main-container"> <v-form v-model="valid"> <v-text-field v-model="form.name" :rules="nameRules" :counter="10" label="Name" required></v-text-field> <v-text-field v-model="form.email" :rules="emailRules" label="E-mail" required></v-text-field> <v-text-field v-model="form.password" :rules="passwordRules" label="Password" required type="password"></v-text-field> <v-text-field v-model="form.password_confirmation" :rules="repasswordRules" label="Confirm Password" required type="password"></v-text-field> <v-btn small @click="register">submit</v-btn> //追加 </v-form> </div> </div> </template> <script> import Header from './Header'; export default { components: { Header }, metaInfo: { title: '会員登録', htmlAttrs: { lang: 'ja' } }, created () { const user = this.$store.getters['auth/user']; if (user !== null) { this.$router.push('/todo'); } }, data () { return { form : { name: '', email: '', password: '', password_confirmation: '', }, nameRules: [ v => !!v || '名前を入力してください', ], emailRules: [ v => !!v || 'E-mailを入力してください', v => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mailを正しく入力してください' ], passwordRules: [ v => !!v || 'パスワードを入力してください', v => v.length >= 8 || 'パスワードは8文字以上で入力してください' ], repasswordRules: [ v => !!v || 'パスワードの再入力を行ってください', v => v == this.form.password || 'パスワードが一致しません' ] } }, methods: { //追加 async register() { await this.$store.dispatch('auth/register', this.form); this.$router.push('/todo'); } } } </script> <style> .main-container { width: 500px; margin: auto; } </style>①クリックイベントを追加しています
クリックすることでregister
メソッドを呼び出します②このメソッドによって登録処理を実行します
厳密に言うと、登録処理をするアクションを呼び出しています(auth.jsについてはこの後実装します)
会員登録の処理後に、Todoページに遷移する様にしています次に、
register()
でdispatchしているauth.js
のregister
の実装をしていきますauth.jsimport axios from 'axios'; const state = { user: null //追加 } const getters = { user: state => state.user //追加 } const mutations = { setUser (state, user) { //追加 state.user = user; } } const actions = { async register({ commit }, data) { //追加 const response = await axios.post('/api/register', data) commit('setUser', response.data); }, async searchUser({ commit }) { //追加 const response = await axios.get('/api/user'); const user = response.data ? response.data : null commit('setUser', user); }, } export default { namespaced: true, state, getters, mutations, actions }main.jsimport Vue from 'vue'; import App from './App.vue'; import router from './router/router'; import store from './store/store'; import vuetify from './plugins/vuetify'; import axios from 'axios'; import VueMeta from 'vue-meta'; Vue.config.productionTip = false Vue.use(axios); Vue.use(VueMeta, { refreshOnceOnNavigation: true }); const createApp = async () => { //追加 await store.dispatch('auth/searchUser'); new Vue({ router, vuetify, store, render: h => h(App) }).$mount('#app') } createApp(); //追加一気にauth.jsの追加とmain.jsの一部追加を行いました
一つづ説明していきますauth.jsconst state = { user: null }stateでuserの情報を管理します
このアプリケーション内では、全てこのuserの値の有無を見てログイン認証やユーザー情報の所得を行いますauth.jsconst getters = { user: state => state.user }stateのuserの情報を所得するgetterを定義しています
auth.jsconst mutations = { setUser (state, user) { state.user = user; } }受け取ったデータをstateのuserに値をセットするミューテーションを定義しています
auth.jsasync register({ commit }, data) { //追加 const response = await axios.post('/api/register', data) commit('setUser', response.data); }Laravel側の
api.php
で定義したregister
に対してpostしています
第二引数のdataはフォームに入力された値がv-modelでバインドされたdataの中身が渡されています
ここでの返り値として、先ほどオーバーライドしたregistered()
メソッドでの$userの値がresponseにセットされます
その値をsetUserに対してcommitしてstateのuserに値を設定していますauth.jsasync searchtUser({ commit }) { //追加 const response = await axios.get('/api/user'); const user = response.data ? response.data : null; commit('setUser', user); }Laravel側の実装の際に
api.php
にて定義した/user
のルートに対してアクセスをしています
/user
のルートはAuth::user()として認証しているユーザーの情報を返却する様に作りました
Auth::user()は認証していればユーザー情報が、認証されていなければnullが返ってきます
それを利用して、上記アクションでは/api/user
に対してリクエストをしてその戻り値(認証されていればユーザー情報、認証されていなければnull)を
変数responseに入れています
const user = response.data ? response.data : null;
で認証されていてresponseに値が入っていればその値を
認証されておらずnullが入っていればnullを変数userに入れています
そのuserをsetUserでcommitしてstateのuserに値を入れています
なのでstateのuserはログインしていればユーザー情報、ログインしていなければnullが常に入っている様にしています
あとはこれを常時実行するためにどうしているかと言うと、先ほど追加したmain.js
の追加部分になりますmain.jsconst createApp = async () => { await store.dispatch('auth/searchUser'); new Vue({ router, vuetify, store, render: h => h(App) }).$mount('#app') } createApp();ここでVueインスタンスが作られる際に毎回、
createApp()
を実行することにより
auth.js
のsearchUser
アクションを実行しています
これにより、auth.js
のsearchUser
が毎回実行されることで
Laravelで定義した/user
にリクエストを投げ現在の認証情報を所得しauth.js
のsetUser
がcommitされ
stateのuserに値がセットされると言うことになりますRegister.vuecreated () { const user = this.$store.getters['auth/user']; if (user !== null) { this.$router.push('/todo'); } }この部分でそのページにアクセスする度に
created()
が実行され
auth.js
のgettersを利用してstateの現在のuser情報を所得し
ログインしていれば/todo
のページへ遷移する様に設定しています(ログインしていない場合はログインページが表示される)ここまでの実装で
会員登録が行える様になりますので、フォームから入力して登録を実行してみてください
正常であれば、入力内容がDBに保存され登録処理ができます終わりに
今回はヘッダーのコンポーネントの作成と、会員登録機能の実装を一通り行いました
次回は、今回登録した内容を利用してログインができる様に、ログイン機能の実装をやっていきます次のパートはこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part4
- 投稿日:2020-03-17T17:27:52+09:00
Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part2
前回のパート
前回はVue CLIとLaravelの環境構築を含め、VuexやVue RouterのセットアップとVue MetaとVuetifyの
インストールを行いました
前回の記事はこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part1
今回は、本記事で作成するTodoリストに使うテーブル作成から行いますAuthの導入
まずはターミナルから
$ php artisan serve
と$ npm run serve
を実行して
LaravelとVue CLIを動かしておいてくださいまた事前に、.envファイルのDBの設定とDBの作成を行ってください
Laravelの認証を使うためにAuthを導入していきます
コマンドにて下記を実行してください
$ composer require laravel/ui
$ php artisan ui vue --auth
$ php artisan migrate
$ npm install
$ npm run dev
上記を順に実行することで、LaravelでAuthが導入できLaravel側でのデフォルトの認証画面にアクセスできる状態になります(今回はview側はVueを使用するため使いません)マイグレーションの作成
まず今回使うテーブルは2種類になります
ユーザーの情報を扱う、UsersテーブルとTodoの情報を管理するTodosテーブルになります
Usersテーブルは上記のAuthの導入をした際に、作成されているUsersテーブルをそのまま使うので
ここで作るテーブルはTodosテーブルのみになります
早速Todosテーブルのマイグレーションを作成していきます
コマンドにて下記を実行
$ php artisan make:migration create_todos_table --create=todos
作成されたファイル
database/migrations/XXXX_XX_XX_XXXXXXX_create_todos_table.php
を開き下記と同じ様に書き換えてくださいXXXX_XX_XX_XXXXXXXX_create_todos_table.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class TodosCreateTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('todos', function (Blueprint $table) { $table->id(); $table->integer('user_id'); $table->text('text'); $table->softDeletes(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('todos'); } }上記が完了したら、マイグレーションを実行しましょう
$ php artisan migrate
実行したら作成したマイグレーションのテーブルが作成できているか、確認してください以上で今回使用する、テーブルの準備が整いました
終わりに
今回は、Authの導入とマイグレーションファイルの作成を行いました
次回から会員登録やログインなどの認証まわりの実装に入っていきます次のパートはこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part3
- 投稿日:2020-03-17T17:27:02+09:00
Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part1
はじめに
本記事は、Vue CLIとLaravelに加えてVuetifyを使ってTodoリストを作るチュートリアルです
Vuetifyは各自採用するかは決めていただければと思います。
本記事にはVuetifyの記載が多く登場しますが、Vuetifyを使わずにこのチュートリアルを進められる方はVuetifyの部分は無視してもらい
自身でマークアップを行ってください。
また、本チュートリアルはこちらの記事を参考にさせて頂き制作しましたこのチュートリアルで学べること
- Vue CLIとLaravelを利用した開発の流れ
- Vue(SPA)での開発
- LaravelとVueでの認証周りのあれこれ
- Vuexの活用方法
- Vue Routerの活用方法
このチュートリアルの対象者
- Laravelの基本を学んだ方
- Vueの基本を学んだ方
- Vue CLIとLaravelで何か作ってみたい方
バージョン
Vue CLI - 4.0.5
laravel - 7.0.4Vue CLI × Laravelの環境構築
まずはLaravelでアプリケーションを作成していきます
コマンドにて下記を実行
$ laravel new VueTodo
作ったアプリケーションに移動します
$ cd VueTodo
次にVue CLIをLaravelに作っていきます
$ vue create client
Manualyを選択
RouterとVuexを選択
historyモードを使用するのでyを押してEnter
今回はエラー防止のみのESLintを使用するのでそのままEnter
保存時にLintを実行するため、そのままEnter
package.jsonで管理するため、Inpackage.json
を選択してEnter
今回の設定を今回は特に保存しないので、nを押してEnter
これでLaravelにclientと言う名前でVue CLIが構築されます
ここまでで、LaravelとVue CLIの準備は完了proxyの設定を行う
Vue CLIとLaravel間ではドメインが違うため、お互いに通信を行うための設定が必要です
今回はproxyを使います
Vue CLIの機能を使いproxyの設定をすることができます。clientディレクトリに
vue.config.js
ファイルを作成
下記を追加
これによりVue CLIからの通信は http://127.0.0.1:8000 に変換され同一ドメインでの通信が可能になります
(ここのパスは環境によって変わるため、$ php artisan serve
をした際にアクセスできるLaravel側の自身の環境に書き換えてください)vue.config.jsmodule.exports = { devServer: { proxy: { '/api': { target: 'http://127.0.0.1:8000' } } } }RouteServiceProviderの変更
app/Http/Providers/RouteServiceProvider
のmapApiRoutes()
メソッドの変更を行います
デフォルトでは下記のようになっていますRouteServiceProvider.phpprotected function mapApiRoutes() { Route::prefix('api') ->middleware('api') //・・・① ->namespace($this->namespace) ->group(base_path('routes/api.php')); }①の部分がデフォルトではapiとなっています
このmiddlewareの設定を下記のように書き換えますRouteServiceProider.phpprotected function mapApiRoutes() { Route::prefix('api') ->middleware('web') ->namespace($this->namespace) ->group(base_path('routes/api.php')); }何故ここを書き換えるのかと言うと
apiとwebでは適応されるmiddlewareが違います
apiのmiddlewareはCSFRトークンやセッションなどのmiddlewareが含まれていません
ただ今回の場合は、Laravelのセッションの認証をするためにセッションや、クッキーを必要とするため
webに変更しています
従来のAPIとしてLaravelを利用する場合は、apiのデフォルトのままで大丈夫ですaxiosのインストール
コマンドにて下記を実行
$ npm install axios
clietn/src/main.js
にてaxiosをuseするmain.jsimport Vue from 'vue'; import App from './App.vue'; import axios from 'axios'; Vue.config.productionTip = false Vue.use(axios); new Vue({ render: h => h(App) }).$mount('#app')Vue Routeのセットアップ
Vue Routerセットアップを行います
すでにVue CLIの作成時にRouterを導入してるのでインストールは不要です
client/src/router
と言うディレクトリがRouterのファイルになります
client/src/index.js
のファイル名をわかりやすい様にリネームし、router.js
と変更し
router.js
に下記に書き換えてくださいrouter.jsimport Vue from 'vue'; import Router from 'vue-router'; Vue.use(Router); export default new Router({ mode: 'history', routes: [ //今は空にしておく ] })
router.js
の作成が完了したら、main.js
にて下記を追加main.jsimport Vue from 'vue'; import App from './App.vue'; import router from './router/router'; //追加 import axios from 'axios'; Vue.use(axios); new Vue({ router, //追加 render: h => h(App) }).$mount('#app')これでVue Routerのセットアップは完了です
Vuexのセットアップ
こちらも、Vue CLIの作成時にインストールしているのでインストールは不要です
client/src/store
がVuexのファイルになります
こちらも、わかりやすい様にリネームしてstore.js
として、新規ファイルでauth.js
を作成してください
作成したらstore.js
を下記に書き換えてくださいstore.jsimport Vue from 'vue'; import Vuex from 'vuex'; import auth from './auth'; Vue.use(Vuex); export default new Vuex.Store({ modules: { auth } })
auth.js
にも下記を追加auth.jsimport axios from 'axios'; //axiosを今後使うので読み込んでます const state = { } const getters = { } const mutations = { } const actions = { } export default { namespaced: true, state, getters, mutations, actions }
main.js
に下記を追加するmain.jsimport Vue from 'vue'; import App from './App.vue'; import router from './router/router'; import store from './store/store'; //追加 import axios from 'axios'; Vue.use(axios); new Vue({ router, store, //追加 render: h => h(App) }).$mount('#app')以上でVuexのセットアップは終了です
Vue Metaのインストール
Vue Metaを導入することでVueのscript内でheadのlang設定やtitleなどの設定を行えるようになります
今後使っていくので使い方等は追々説明しますので、ここではインストールとセットアップのみ手順にしたがって行ってくださいコマンドにて下記を実行
$ npm install vue-meta
main.js
にて下記を追加するmain.jsimport Vue from 'vue'; import App from './App.vue'; import router from './router/router'; import store from './store/store'; import axios from 'axios'; import VueMeta from 'vue-meta'; //追加 Vue.use(axios); Vue.use(VueMeta, { refreshOnceOnNavigation: true }); //追加 new Vue({ router, store, render: h => h(App) }).$mount('#app')Vuetifyの導入
※Vuetifyを使わない方はここを飛ばしてもらってOKです
$ cd client
に移動して下記コマンドを実行
$ vue add vuetify
コマンドを実行することでclient/plugins
にvuetify.js
が作成されていることを確認してください
また、main.js
に自動的に追加されていることも確認してください(追加されていない場合は追加してください)main.jsimport Vue from 'vue'; import App from './App.vue'; import router from './router/router'; import store from './store/store'; import vuetify from './plugins/vuetify'; //追加されている import axios from 'axios'; import VueMeta from 'vue-meta'; Vue.use(axios); Vue.use(VueMeta, { refreshOnceOnNavigation: true }); //追加 new Vue({ router, vuetify, //追加されている store, render: h => h(App) }).$mount('#app')終わりに
以上でVue CLIとLaravelで今回必要な物のインストールやセットアップなどの環境の構築が終わりました
次回は、今回のTodoリストで使うUserのテーブルとTodoを管理する2つのテーブルのマイグレーションの作成から始めようと思います次のパートはこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part2
- 投稿日:2020-03-17T16:03:16+09:00
laravel-dompdf の使い方
1) プロジェクトの作成
laravel new pdf012) ライブラリーのインストール
cd pdf01 composer require barryvdh/laravel-dompdf
php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider"3) コントローラーの作成
php artisan make:controller HomeControllerapp/Http/Controllers/HomeController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class HomeController extends Controller { // public function index() { $pdf = \PDF::loadView('generate_pdf'); return $pdf->download('test01.pdf'); } }4) View の作成
resources/views/generate_pdf.blade.php<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>My First Page</title> </head> <body> <h1>Hello World!!</h1> <blockquote> Good Afternoon<p /> </blockquote> Mar/17/2020 PM 15:48<p /> </body> </html>5) routes の作成
routes/web.php<?php use Illuminate\Support\Facades\Route; Route::get('/', function () { return view('welcome'); }); Route::get('pdf', 'HomeController@index')->name('generate_pdf.index');6) サーバーの起動
php artisan serve --host 0.0.0.0
7) クライアントからアクセス
- 投稿日:2020-03-17T01:59:16+09:00
Laravel6.x バリデーション 他テーブル特定カラムに存在しなければいけない
他テーブルの特定のカラムに入力値が存在するしなければいけない。。
そんなバリデーションを書くには、、
そう、exist
です。exists:テーブル,カラム
参考・引用元
- 投稿日:2020-03-17T00:48:43+09:00
Laravelでjs読み込む時に「$ is not defined javascript」エラー
めちゃめちゃ基本的なところでつまづいたので備忘録。
laravelを使ってjs読み込みたいのに何故か最初のおまじない部分でずっとコンソールエラー。
$ is not defined javascripthoge.js$(function(){ //←処理入る前のここで既に怒られる //ここに処理 });
なんでえ???と思ってたらjsの呼び出し方間違えてました。
↓こう書いてたのをhoge.blade.php<script src="/js/hoge.js"></script>こうしないといけなかったみたい。
hoge.blade.php<script src="{{ asset('/js/hoge.js') }}"></script>参考にさせていただいた記事
https://qiita.com/sakuraya/items/411dbc2e1e633928340e