はじめに
LaravelとVue.jsでちょっとしたアプリを作っていた時に、LaravelのControllerで生成・加工したデータをVue.jsのテンプレートファイルに渡して使用するには下記の手順でデータを渡す必要がありましたので今後必要になった時に直ぐに思い出せる様にまとめたいと思います。
Controller→View(Bladeファイル)→Vue(Vue.jsテンプレート)
前提とするデータ構成
とある店舗情報を格納するデータをDB等から取得して下記の多次元配列としてControllerで整形したと想定します。
*Controllerでの細かいデータの取得・加工処理については本記事では割愛します。
array(5){
0 => array(5)
1 => array(5)
2 => array(5)
3 => array(5)
4 => array(5)
}
valueである各配列の中身は下記の様な形式のデータとします。
array(5){
'shopId' => "testId1",
'shopName' => "testShop1",
'price' => "1000",
'shopTel' => "1234-5678-90",
'shopMessage' => array('short' => "test shot message",
'long' => "test long message"
),
'shopImage' => array('url1' => "https://example.com/sample1.jpg",
'url2' => "https://example.com/sample2.jpg"
)
}
Controller
順を追って、まずはControllerから流れを見て行きます。
上記の店舗情報データを$sampleDataとします。
この$sampleDataをVueファイルで配列の様に扱うにはjsonエンコーディングを行いオブジェクト化する必要があります。
$shopData = json_encode($sampleData);
viewを指定する箇所を含めると下記の様な具合になります。
app/Http/Controllers/SampleController.php
public function index()
{
/*** データの加工処理は省略 ***/
// 配列のjsonエンコード化
$shopData = json_encode($sampleData);
// viewファイルに$shopDataを渡す
return view('index')->with('shopData', $shopData);
}
View
次はViewファイルを見て行きます。
bodyタグ内を下記の通り記述して行きます。
resources/views/index.blade.php
<main id="app">
<shop-page v-bind:shop-data="{{ $shopData }}"></shop-page>
</main>
shop-pageタグがVueテンプレートの内容を反映する箇所です。
このshop-pageタグにControllerから受け取ったデータをバインド(結びつける)します。
「v-bind」属性(ディレクティブ)でバインドを行います。
v-bindで指定した「shop-data」がVueテンプレート内にてControllerから来た$shopDataのデータを受け持つことになります。
Vueテンプレート内ではキャルメルケースのshopDataと言う名前でデータが利用されることになります。
Vueテンプレート
Vueテンプレートの中身は下記の通りです。
resources/components/ShopPage.vue
<template>
<div class="card text-white bg-dark mb-3" v-for="shop in shopData">
<div class="row no-gutters">
<img class="card-img" :src="shop.shopImage.url1" alt="no image">
<div class="card-body">
<h3 class="card-title">{{ shop.shopName }}</h3>
<p class="card-text">{{ shop.shopMessage.short }}</p>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
shopData: {
type: Object
},
},
name:'shop-page'
}
</script>
scriptタグ内のprops(プロパティ)に記載されているshopDataがbladeファイル内での$shopDataになります。
型にObject型を指定する必要があります。
データの利用例として、templateタグ内で店舗情報をBootstrapのcardで表示するコードを記載しています。
for文の要領で店舗情報ごとにcardを作成するには一番外側のcardクラスが指定されたdivタグ内でv-forディレクティブを設定する方法があります。
下記の通りに指定することでforeach文の様に各店舗情報のオブジェクトを抽出することが出来ます。
v-for="shop in shopData"
今回のデータ構成ではkeyの値を参照する必要の無い作りになっている為「v-for」ディレクティブでkeyの値を取得していませんが、もし必要な場合は下記の通りに記載する必要があります。
v-for="(shop, key) in shopData"
「shop」はControllerで生成したの店舗ごとの情報をまとめたデータです。
このshopの値は「v-for」ディレクティブが指定されたタグ内で記載されている全てのタグ内で各データに沿ったkeyを指定することで利用出来ます。
shop{
'shopId' : "testId1",
'shopName' : "testShop1",
'price' : "1000",
'shopTel' : "1234-5678-90",
'shopMessage' : {
'short' : "test shot message",
'long' : "test long message"
},
'shopImage' : {
'url1' : "https://example.com/sample1.jpg",
'url2' : "https://example.com/sample2.jpg"
}
}
h1タグやpタグにて文字列を出力する場合は下記の通り二重括弧を使って値を指定します。
<h1 class="card-title">{{ shop.shopName }}</h1>
<p class="card-text">{{ shop.shopMessage.short }}</p>
画像を表示させる場合は少し書き方が異なります。
src属性に画像データのパスやURLを指定しますが、「src」の直前に「:」(コロン)を指定する必要がある。
<img class="card-img" :src="shop.shopImage.url1" alt="no image">
店舗情報をボタンクリックイベント後の関数で利用したい場合は下記の様に「v-on:click」ディレクティブに関数名を指定してパラメータとして店舗情報を指定すると良いです。
関数定義内の各詳細のデータの指定の仕方は同様です。
<a v-on:click="testFunc(shop)" href="javascript::void(0)" class="btn btn-primary">detail</a>
ちなみに
bladeファイル上で配列のkey指定をして数値や文字列など単体のデータを渡す場合はControllerでjsonエンコードを行う必要はありません。
配列のままbladeファイルでkey指定することによって単体のデータを渡すことが出来ます。
app/Http/Controllers/SampleController.php
$singleValue = array('key1' => 1, 'key2' => 2, 'key3' => 3);
resources/views/index.blade.php
<shop-page v-bind:shop-data="{{ $shopData }}" v-bind:single-value="{{ $singleValue['key1'] }}" ></shop-page>
この場合はVueファイル内ではpropsでNumber型やString型を指定する必要があります。
以上です。
LaravelをやるとVue.jsに触れる機会が出てくる為この辺りの理解も深める必要があるなと感じました!