CakePHPとVue-cli2でSPA②コントローラーからVueに変数を渡す
323 回閲覧されました
みなさんこんにちは、jonioです。
前回はCakePHPとVue-cliの連携をしました。
今回はCakePHPのコントローラーからVueに変数を渡してブラウザに表示します。
CakePHPの4系をベースに解説しますが3系は一部書き方が違うのでその部分にも触れます。
目次
コントローラーからVueに渡す変数
テーブルの中身の情報を渡します、使うテーブル名はdemoです。
カラムは以下になりますが自分で用意したテーブルを使っても問題ないです。
default.phpの編集
下記のコードに変更してください。
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.10.0
* @license https://opensource.org/licenses/mit-license.php MIT License
* @var \App\View\AppView $this
*/
$cakeDescription = 'CakePHP: the rapid development php framework';
?>
<!DOCTYPE html>
<html>
<head>
<?= $this->Html->charset() ?>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
<?= $cakeDescription ?>:
<?= $this->fetch('title') ?>
</title>
<?= $this->Html->css(['normalize.min', 'milligram.min', 'cake']) ?>
<?= $this->fetch('meta') ?>
<?= $this->fetch('css') ?>
<?= $this->fetch('script') ?>
<?= $this->AssetMix->script('main') ?>
</head>
<body>
<nav class="top-nav">
<div class="top-nav-title">
<a href="<?= $this->Url->build('/') ?>"><span>Cake</span>PHP</a>
</div>
<div class="top-nav-links">
<a target="_blank" rel="noopener" href="https://book.cakephp.org/4/">Documentation</a>
<a target="_blank" rel="noopener" href="https://api.cakephp.org/4/">API</a>
</div>
</nav>
<main class="main">
<div class="container">
<?= $this->fetch('content') ?>
</div>
</main>
<footer>
</footer>
</body>
</html>
50行目がないとVue.jsが表示できないです。
CakePHPの設定
今回はDemoコントローラーのindexアクションでブラウザ(http://localhost/demo/index)を表示します。
コントローラーのindexアクションのコードを下記にします。
public function index()
{
$demos = $this->Demo->find('all')->toArray();
$this->set(compact('demos'));
$this->viewBuilder()->setOption('serialize', ['demos']);
}
7行目はCakePHPのバージョンが4の場合の書き方で3の場合の書き方は下記になります。
$this->set('_serialize', 'demos');
話を戻して、7行目の「demos」は5行目の「demos」と同じにします。
次はindex.phpです、コードを下記にします。
<div id="app"></div>
今回は「http://localhost/demo/index」でVue.jsを表示したいので上記のコードをこのファイルに持ってきました。
routes.php
「CakePHPのプロジェクト > config > routes.php」の編集をします。
<?php
/**
* Routes configuration.
*
* In this file, you set up routes to your controllers and their actions.
* Routes are very important mechanism that allows you to freely connect
* different URLs to chosen controllers and their actions (functions).
*
* It's loaded within the context of `Application::routes()` method which
* receives a `RouteBuilder` instance `$routes` as method argument.
*
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
//ここから追加
use Cake\Routing\Route\DashedRoute;
use Cake\Routing\RouteBuilder;
//ここまで追加
/*
* The default class to use for all routes
*
* The following route classes are supplied with CakePHP and are appropriate
* to set as the default:
*
* - Route
* - InflectedRoute
* - DashedRoute
*
* If no call is made to `Router::defaultRouteClass()`, the class used is
* `Route` (`Cake\Routing\Route\Route`)
*
* Note that `Route` does not do any inflections on URLs which will result in
* inconsistently cased URLs when used with `:plugin`, `:controller` and
* `:action` markers.
*/
/** @var \Cake\Routing\RouteBuilder $routes */
// $routes->setRouteClass(DashedRoute::class);
//ここから追加
$routes->setExtensions(['json']);
$routes->resources('Demo');
//ここまで追加
$routes->scope('/', function (RouteBuilder $builder) {
/*
Here, we are connecting '/' (base path) to a controller called 'Pages',
* its action called 'display', and we pass a param to select the view file
* to use (in this case, templates/Pages/home.php)...
*/
$builder->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
/*
* ...and connect the rest of 'Pages' controller's URLs.
*/
$builder->connect('/pages/*', ['controller' => 'Pages', 'action' => 'display']);
$builder->connect('/demo/index', ['controller' => 'Demo', 'action' => 'index'])->setExtensions(['json']); //この行を追加
/*
* Connect catchall routes for all controllers.
*
* The `fallbacks` method is a shortcut for
*
* ```
* $builder->connect('/:controller', ['action' => 'index']);
* $builder->connect('/:controller/:action/*', []);
* ```
*
* You can remove these routes once you've connected the
* routes you want in your application.
*/
$builder->fallbacks();
});
/*
* If you need a different set of middleware or none at all,
* open new scope and define routes there.
*
* ```
* $routes->scope('/api', function (RouteBuilder $builder) {
* // No $builder->applyMiddleware() here.
* // Connect API actions here.
* });
* ```
*/
54行目の「Demo」はコントローラー名です、今回はDemoコントローラーを使うのでDemoを指定しています。
53行目は71行目に使う為にあります、「->setExtensions([‘json’])」でDemoコントローラーの「$demos」をjsonに変換します。
public function index()
{
$demos = $this->Demo->find('all')->toArray(); //←これ
$this->set(compact('demos'));
$this->viewBuilder()->setOption('serialize', ['demos']);
}
これで「http://localhost/demo/index.json」にアクセスすると下記の表示になりdemoテーブルの内容をjsonで表示されているのが確認できます。
{
demos: [
{
id: 1,
title: "title1",
content: "content1",
like_flag: true,
created: null,
modified: null
},
{
id: 2,
title: "title2",
content: "content2",
like_flag: false,
created: null,
modified: null
},
{
id: 3,
title: "title3",
content: "content3",
like_flag: true,
created: null,
modified: null
}
]
}
このデータをVueで使えるようにします。
Vue.jsの設定
まずはmain.jsの設定をします。
main.js
エントリーポイントの設定をします。
「CakePHPのプロジェクト > resources > vue_demo > src > App.vue」を最初に呼び出すVueファイルにする為に「CakePHPのプロジェクト > resources > vue_demo > src > main.js」のコードを下記にします。
import Vue from 'vue';
import App from './App';
Vue.config.productionTip = false;
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue
「CakePHPのプロジェクト > resources > vue_demo > src > App.vue」のコードを下記にします。
<template>
<entry></entry>
</template>
<script>
import Entry from './components/Entry.vue'
export default {
name: 'App',
components: {
Entry
}
}
</script>
Entry.vueはまだ作成していないので作成します。
Entry.vue
「CakePHPのプロジェクト > resources > vue_demo > src > components」の下の階層にEntry.vueを作成して下記のコードを記述します。
<script>
import axios from 'axios';
export default {
data: function () {
return {
demos : [],
}
},
mounted: function(){
axios.get('http://localhost/demo.json')
.then(response => {
this.demos = response.data;
console.log(this.demos);
})
.catch(err => {
this.status = err.message;
});
},
};
</script>
11行目の「http://localhost/demo.json」の「http://localhost/demo」はdemoコントローラーのindexアクションという意味です。
「.json」は付けないといけないんだと思っていいです。
これで「http://localhost/demo/index」にアクセスしてデベロッパーツールを開くとDemoコントローラーのindexアクションにあった「$demos」を取得できているのが確認できます。
それでは$demosの内容をブラウザに表示します、Entry.vueに追記します。
//ここから追加
<template>
<div>
<ul>
<li
v-for="demoList in demos"
:key="demoList.id"
>
<ul>
<li
v-for="demo in demoList"
:key="demo.id"
>
{{ demo.title }}</li>
</ul>
</li>
</ul>
</div>
</template>
//ここまで追加
<script>
import axios from 'axios';
export default {
data: function () {
return {
demos : [],
}
},
mounted: function(){
axios.get('http://localhost/demo.json')
.then(response => {
this.demos = response.data;
console.log(this.demos);
})
.catch(err => {
this.status = err.message;
});
},
};
</script>
これで「http://localhost/demo/index」にアクセスすると下記の表示になります。