はじめに
初心者向けのチュートリアルとして Laravel 11 と Vue 3 を組み合わせたアプリケーションを作成する方法を説明しています。
また、本記事では Vue 3 の記法として Options API を用いて記述しております。
Options API は Vue 2 の記法と同じであり、少し手順を変更すれば Vue 2 を用いたチュートリアルとしても活用できると考えたためです。
完成イメージ
ポケモンのデータを取得できる無料のAPI「PokeAPI」を用いて、ポケモンの一覧を表示します。また、お気に入りのポケモンを登録/解除できる機能を作成し、気になるポケモンに目印を付けることを可能とします。
前提条件
- Docker が使用できる状態であること
用いる技術
- PHP 8.3
- Laravel 11.x
- Vue.js 3
- Vue Router 4
- TailwindCSS
- MySQL 8.4
手順
1. Docker コンテナの作成
AlmaLinux、Nginx、MySQL、phpMyAdmin のコンテナを作成するため、docker-compose.yml
を新規作成して以下の内容を記述してください。
ローカルホスト側からコンテナにアクセスできるように、以下のポートにおいてローカルホスト - コンテナ間で接続する設定を行っております。
- ローカルホスト 80番 ← Nginxコンテナ 80番
- ローカルホスト 5173番 ← AlmaLinuxコンテナ 5173番(Vite サーバ接続のため)
- ローカルホスト 8080番 ← phpMyAdminコンテナ 80番
name: "laravel_vue_tutorial"
services:
nginx:
container_name: laravel_vue_tutorial_nginx
image: nginx:1.26
ports:
- 80:80
volumes:
- ./laravel:/var/www/html/laravel
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
php:
container_name: laravel_vue_tutorial_php
ports:
- 5173:5173
build:
context: .
dockerfile: ./docker/php/dockerfile
volumes:
- ./laravel:/var/www/html/laravel
- ./docker/php/www.conf:/etc/php-fpm.d/www.conf
depends_on:
- mysql
mysql:
container_name: laravel_vue_tutorial_mysql
image: mysql:8.4
environment:
- MYSQL_DATABASE=tutorial
- MYSQL_USER=tutorial
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=password
pma:
container_name: laravel_vue_tutorial_pma
image: phpmyadmin:5.2
environment:
- PMA_HOST=laravel_vue_tutorial_mysql
ports:
- 8080:80
depends_on:
- mysql
AlmaLinux のコンテナを用いて PHP を動作させるため、docker/php
ディレクトリに dockerfile
を作成して以下の内容を記述してください。PHP、Composer、Node.js をインストールした後、PHP-FPM を起動するように設定しております。
FROM almalinux:8.10
RUN dnf -y update
RUN dnf -y install unzip
# PHP
RUN mkdir /run/php-fpm
RUN dnf -y install epel-release
RUN dnf -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
RUN dnf module enable -y php:remi-8.3
RUN dnf -y install php php-fpm php-mysqlnd
# Composer
COPY --from=composer:2.7.8 /usr/bin/composer /usr/bin/composer
# Node
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
RUN source ~/.bashrc && nvm install 20.17.0
COPY ./laravel /var/www/html/laravel
WORKDIR /var/www/html/laravel
EXPOSE 9000
CMD ["php-fpm", "-F"]
Laravel を動作させるため、docker/nginx
ディレクトリに Nginx の設定ファイル default.conf
を作成して以下の内容を記述してください。設定内容は Laravel 公式のマニュアルを参考にしております。
server {
listen 80;
listen [::]:80;
server_name localhost;
root /var/www/html/laravel/public;
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass laravel_vue_tutorial_php:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
}
Nginx からの要求に PHP-FPM が応答できるように、docker/php
ディレクトリに www.conf
を作成して以下の内容を記述してください。
[www]
user = nginx
group = nginx
listen = 9000
listen.acl_users = apache,nginx
pm = dynamic
pm.max_children = 50
pm.min_spare_servers = 5
pm.max_spare_servers = 35
動作確認のため、laravel/public
ディレクトリに index.php
を作成して以下の内容を記述してください。内容はシンプルに phpinfo を表示するだけです。
<?php
echo phpinfo();
上記のファイルが全て作成できたら、以下のコマンドを実行してコンテナを作成および起動を実施してください。起動後にブラウザから http://localhost にアクセスして、phpinfo が表示されれば OK です。
docker compose up -d
表示が確認できたら、laravel
ディレクトリ配下にある public
ディレクトリを削除して、laravel
ディレクトリを空にしておいてください。空になっていないと、Laravel のインストール時にエラーとなります。
2. Laravel のインストール
Laravel の公式マニュアルに従ってインストールを行っていきます。
以下のコマンドを実行して、laravel_vue_tutorial_php のコンテナに接続してください。
docker exec -it laravel_vue_tutorial_php bash
接続できたら、以下のコマンドを実行して Laravel をインストールしてください。
composer create-project laravel/laravel ./
インストールが正常に実行できたら、laravel
ディレクトリにある .env
の設定を以下のように変更してください。デフォルトではデータベースとして SQLite を使用する設定となっておりますが、今回は MySQL を使用する設定に変更します。
- DB_CONNECTION=sqlite
+ DB_CONNECTION=mysql
+ DB_HOST=laravel_vue_tutorial_mysql
+ DB_PORT=3306
+ DB_DATABASE=tutorial
+ DB_USERNAME=tutorial
+ DB_PASSWORD=password
.env
を変更したら、データベースにテーブルを作成するため以下のコマンドを実行してください。
php artisan migrate
また、Nginx が Laravel を実行してログファイル等を作成できるように、以下のコマンドを実行して権限設定を行ってください。
chown -R nginx. /var/www/html/laravel/storage
コマンドを実行し終えたら、Laravel の動作確認のためブラウザから http://localhost にアクセスしてください。エラーが表示されず、Laravel の画面が表示されれば OK です。
3. Vue のインストール
以下のコマンドを実行して Vue 3 および VueRouter 4 をインストールしてください。また併せて、Laravel 11 で用いられるビルドツール Vite と Vue を連携させるプラグインもインストールしてください。
npm install vue@3 vue-router@4
npm install @vitejs/plugin-vue --save-dev
インストールできたら、Vite の設定ファイル vite.config.js
に以下の内容を追記してください。Vue を利用する設定とローカルホスト側からホットリロード機能を利用するための設定を記述しています。
import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
+ import vue from "@vitejs/plugin-vue";
export default defineConfig({
+ server: {
+ host: "0.0.0.0",
+ hmr: {
+ host: "localhost",
+ },
+ },
plugins: [
laravel({
input: ["resources/css/app.css", "resources/js/app.js"],
refresh: true,
}),
+ vue(),
],
});
各コンポーネントの親要素となるルートコンポーネントを作成します。laravel/resources/js
ディレクトリに App.vue
を作成して以下の内容を記述してください。
<template>
<router-view></router-view>
</template>
<script>
export default {
name: "App",
};
</script>
ルートコンポーネントの子要素となる Vue ファイルを作成します。laravel/resources/js/pages
ディレクトリに Index.vue
を作成して以下の内容を記述してください。
<template>
<h1>Laravel Vue App</h1>
</template>
作成したコンポーネントをインポートして、Vue のインスタンスを作成します。laravel/resources/js
ディレクトリの app.js
に以下の内容を記述してください。
- import './bootstrap';
+ import { createApp } from "vue";
+ import { createRouter, createWebHistory } from "vue-router";
+ import App from "./App.vue";
+ import Index from "./pages/Index.vue";
+ const routes = [{ path: "/", component: Index }];
+ const router = createRouter({
+ history: createWebHistory(),
+ routes,
+ });
+ const app = createApp(App);
+ app.use(router);
+ app.mount("#app");
作成した Vue インスタンスを HTML 要素にマウントするため、Laravel の blade.php ファイルを作成します。laravel/resources/views
ディレクトリにある既存の welcome.blade.php
を削除した後、新たに index.blade.php
を作成して以下の内容を記述してください。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Laravel Vue App</title>
@vite('resources/js/app.js')
</head>
<body>
<div id="app"></div>
</body>
<body></body>
</html>
また、作成した index.blade.php
を画面に表示するため、laravel/routes
ディレクトリにある web.php
を以下の記述に変更してください。
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
- return view('welcome');
+ return view('index');
});
ファイル作成および変更がすべて完了したら、以下のコマンドを実行して laravel_vue_tutorial_php のコンテナに接続してください。
docker exec -it laravel_vue_tutorial_php bash
以下のコマンドを実行してコンパイルを行った後、ブラウザから http://localhost にアクセスしてください。「Laravel Vue App」と画面に表示されれば OK です。
npm run dev
4. TailwindCSS のインストール
本記事ではなるべくスタイルの調整に費やす時間を減らすため、オープンソースの CSS フレームワークの 1つである TailwindCSS を利用したいと思います。インストール手順は TailwindCSS のサイトに記載されている手順に従って実施します。
以下のコマンドを実行して TailwindCSS のインストールを行ってください。
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
コマンドを実行すると tailwind.config.js
が生成されますので、以下の内容に変更してください。
/** @type {import('tailwindcss').Config} */
export default {
- content: [],
+ content: [
+ "./resources/**/*.blade.php",
+ "./resources/**/*.js",
+ "./resources/**/*.vue",
+ ],
theme: {
extend: {},
},
plugins: [],
};
変更できたら、laravel/resources/css
ディレクトリの app.css
に以下の内容を追記してください。
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
app.css
を読み込むため、index.blade.php
を以下の内容に変更してください。
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Laravel Vue App</title>
- @vite('resources/js/app.js')
+ @vite(['resources/js/app.js','resources/css/app.css'])
</head>
上記で TailwindCSS の利用準備が整いました。動作確認のため、Index.vue を以下のように変更した後、ブラウザから http://localhost にアクセスしてください。「Laravel Vue App」の文字が赤文字になっていれば OK です。
<template>
- <h1>Laravel Vue App</h1>
+ <h1 class="text-red-600">Laravel Vue App</h1>
</template>
5. ポケモン一覧の作成
準備が整ったので、ここからはアプリケーションの中身を作成していきます。
本手順では以下の画面のようにポケモンの一覧を表示できるように作成を進めていきます。
まずは、実際の画面に表示される HTML 要素を Vue ファイルに記述します。
先ほど作成した laravel/resources/js/pages
ディレクトリの Index.vue
を削除した後、新たに PokemonList.vue
を作成して以下の内容を記述してください。
<template>
<div class="p-6">
<h1 class="text-3xl font-black">ポケモン一覧</h1>
<div class="grid py-6 lg:px-8">
<ul role="list" class="grid gap-x-8 gap-y-4 sm:grid-cols-3 xl:col-span-2">
<li v-for="pokemon in pokemons" :key="pokemon.name">
<div class="flex items-center">
<img class="h-24 w-24 rounded-full" :src="pokemon.imageUrl" />
<span class="text-base font-semibold text-gray-900 ml-4">
{{ pokemon.name }}
</span>
</div>
</li>
</ul>
</div>
</div>
</template>
上記のままではポケモンの情報を取得できていないため、画面にポケモンは表示されません。
ポケモンの情報を取得するため、PokeAPI を呼び出す処理を記述します。先ほど作成した PokemonList.vue
に以下の内容を追記してください。
<script>
import axios from "axios";
const DEFAULT_OFFSET = 0;
const DEFAULT_LIMIT = 20;
export default {
data() {
return {
pokemons: [],
};
},
async created() {
await this.fetchPokemonList();
},
computed: {
offset() {
return Number(this.$route.query.offset || DEFAULT_OFFSET);
},
limit() {
return Number(this.$route.query.limit || DEFAULT_LIMIT);
},
},
methods: {
/**
* 一覧表示するポケモンのリストを取得
*/
async fetchPokemonList() {
const { data } = await axios.get("https://pokeapi.co/api/v2/pokemon", {
params: { offset: this.offset, limit: this.limit },
});
this.pokemons = [];
for (const result of data.results) {
const imageUrl = await this.fetchPokemonImage(result.name);
const name = await this.fetchPokemonName(result.name);
this.pokemons.push({ name, imageUrl });
}
},
/**
* ポケモンの画像を取得
*/
async fetchPokemonImage(name) {
const url = `https://pokeapi.co/api/v2/pokemon/${name}`;
const { data } = await axios.get(url);
return data?.sprites?.other?.["official-artwork"]?.front_default;
},
/**
* ポケモンの名前を取得
*/
async fetchPokemonName(name) {
const url = `https://pokeapi.co/api/v2/pokemon-species/${name}`;
const { data } = await axios.get(url);
return data.names.find((name) => name.language.name === "ja").name;
},
},
};
</script>
ポケモンの情報を取得する処理の内容について詳しく説明します。まず最初に created プロパティで methods プロパティに定義している fetchPokemonList()
が実行されます。
async created() {
await this.fetchPokemonList();
},
fetchPokemonList()
では画面に表示するポケモン一覧を取得するため、axios を用いて PokeAPI にリクエストを送信しています。リクエストのパラメータとしては offset
と limit
を設定しており、これらのパラメータを指定することで一覧取得したいポケモンを制御することが可能です。
computed: {
offset() {
return Number(this.$route.query.offset || DEFAULT_OFFSET);
},
limit() {
return Number(this.$route.query.limit || DEFAULT_LIMIT);
},
},
methods: {
async fetchPokemonList() {
const { data } = await axios.get("https://pokeapi.co/api/v2/pokemon", {
params: { offset: this.offset, limit: this.limit },
});
表示したいポケモン一覧が取得できたのですが、先ほどの API ではポケモンの名前(日本語)や画像に関する情報が含まれておりません。そこで、一覧に含まれる各ポケモンごとに異なる API を実行して、ポケモンの名前(日本語)と画像の URL を取得しています。
本記事では PokeAPI についての詳細な説明は省略させていただきます。ご了承ください。
async fetchPokemonList() {
~ 省略 ~
this.pokemons = [];
for (const result of data.results) {
const imageUrl = await this.fetchPokemonImage(result.name);
const name = await this.fetchPokemonName(result.name);
this.pokemons.push({ name, imageUrl });
}
},
async fetchPokemonImage(name) {
const url = `https://pokeapi.co/api/v2/pokemon/${name}`;
const { data } = await axios.get(url);
return data?.sprites?.other?.["official-artwork"]?.front_default;
},
async fetchPokemonName(name) {
const url = `https://pokeapi.co/api/v2/pokemon-species/${name}`;
const { data } = await axios.get(url);
return data.names.find((name) => name.language.name === "ja").name;
},
これで一覧に取得するポケモンの情報を取得することができました。
次に、作成した PokemonList.vue
を Vue Router に認識させるため、laravel/resources/js
ディレクトリの app.js
の内容を以下のように変更してください。
- import Index from "./pages/Index.vue";
+ import PokemonList from "./pages/PokemonList.vue";
- const routes = [{ path: "/", component: Index }];
+ const routes = [{ path: "/pokemons", component: PokemonList }];
また併せて、Laravel 側のルーティング定義を記述する laravel/routes
ディレクトリの web.php
も以下のように変更してください。
- Route::get('/', function () {
+ Route::get('/pokemons', function () {
return view('index');
});
上記のファイルの作成および変更がすべて完了したら、ブラウザから http://localhost/pokemons にアクセスしてください。以下の画面が表示されていれば OK です。
6. お気に入り登録機能の作成(Laravel)
お気に入り登録したポケモンのデータを保存しておくためにはデータベース(MySQL)を用いる必要がありますので、Laravel を用いてデータの操作を行いたいと思います。
まずはデータベースにテーブルを作成するマイグレーションファイルを作成します。以下のコマンドを実行してください。
php artisan make:migration create_favorites_table
実行できたら、laravel/database/migrations
ディレクトリにYYYY_MM_DD_hhmmss_create_favorites_table.php
が作成されているので、以下の内容を追記してください。
本記事ではポケモンの英語名が一意である前提で進めていきます。
<?php
public function up(): void
{
Schema::create('favorites', function (Blueprint $table) {
$table->id();
+ $table->string('pokemon_english_name')->unique();
$table->timestamps();
});
}
上記で記述した favorites テーブルを作成するため、以下のコマンドを実行してください。
php artisan migrate
これでテーブル作成が完了しました。テーブルが作成されたことを確認したい場合は http://localhost:8080 にアクセスし、phpMyAdmin を用いて確認を行ってください。
次に作成したテーブルに対応する Model を作成します。以下のコマンドを実行してください。
php artisan make:model Favorite
実行できたら、laravel/app/Models
ディレクトリにFavorite.php
が作成されているので、以下の内容を追記してください。
class Favorite extends Model
{
use HasFactory;
+ protected $fillable = ['pokemon_english_name'];
}
Model が作成できたらお気に入り登録処理を記述する Controller を作成するため、以下のコマンドを実行してください。
php artisan make:controller PokemonController
実行できたら、laravel/app/Http/Controllers
ディレクトリに PokemonController.php
が作成されているので、以下の内容を記述してください。
Controller には以下の3つの処理を記述しています。
- お気に入り登録したポケモンの英語名を一括出力する
fetchFavorites()
- 指定されたポケモンをお気に入りに登録する
addFavorite()
- 指定されたポケモンをお気に入りから解除する
deleteFavorite()
<?php
namespace App\Http\Controllers;
use App\Models\Favorite;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class PokemonController extends Controller
{
/**
* お気に入り取得
*/
public function fetchFavorites(Request $request): JsonResponse
{
$favorites = Favorite::get()->pluck('pokemon_english_name');
return response()->json($favorites);
}
/**
* お気に入り登録
*/
public function addFavorite(Request $request): JsonResponse
{
Favorite::updateOrCreate(
['pokemon_english_name' => $request->pokemon_english_name],
['pokemon_english_name' => $request->pokemon_english_name]
);
return response()->json();
}
/**
* お気に入り解除
*/
public function deleteFavorite(Request $request): JsonResponse
{
Favorite::where('pokemon_english_name', $request->pokemon_english_name)->delete();
return response()->json();
}
}
作成した Controller を呼び出す API のルーティングを定義します。以下のコマンドを実行して、API のルーティングを定義するためのファイル api.php
を作成してください。
php artisan install:api
One new database migration has been published. Would you like to run all pending database migrations? (yes/no) [yes]:
> yes
laravel/routes
ディレクトリに api.php
が作成できたら、以下の記述に変更してください。
- Route::get('/user', function (Request $request) {
- return $request->user();
- })->middleware('auth:sanctum');
-
+ Route::get('/pokemons/favorites', [App\Http\Controllers\PokemonController::class, 'fetchFavorites']);
+ Route::post('/pokemons/add-favorite', [App\Http\Controllers\PokemonController::class, 'addFavorite']);
+ Route::post('/pokemons/delete-favorite', [App\Http\Controllers\PokemonController::class, 'deleteFavorite']);
これで Laravel でお気に入り登録/解除を行う API が作成できました。
7. お気に入り登録機能の作成(Vue)
先ほど Laravel で作成した お気に入り登録/解除を行う API を用いて、画面からお気に入り登録/解除の操作を行えるようにします。
PokemonList.vue
に以下の内容を追記してください。
<template>
<div class="p-6">
<h1 class="text-3xl font-black">ポケモン一覧</h1>
<div class="grid py-6 lg:px-8">
<ul role="list" class="grid gap-x-8 gap-y-4 sm:grid-cols-3 xl:col-span-2">
<li v-for="pokemon in pokemons" :key="pokemon.name">
<div class="flex items-center">
<img class="h-24 w-24 rounded-full" :src="pokemon.imageUrl" />
<span class="text-base font-semibold text-gray-900 ml-4">
{{ pokemon.name }}
</span>
+ <template v-if="isIncludeFavorites(pokemon.englishName)">
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ class="h-8 w-8 text-yellow-500 ml-3"
+ viewBox="0 0 24 24"
+ fill="currentColor"
+ stroke="none"
+ @click="deleteFavorite(pokemon)"
+ >
+ <path
+ d="M12 17.27L18.18 21l-1.45-6.36L22 9.27l-6.36-.55L12 2 8.36 8.73 2 9.27l4.27 5.37L4.82 21z"
+ />
+ </svg>
+ </template>
+ <template v-else>
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ class="h-8 w-8 text-gray-300 ml-3"
+ viewBox="0 0 24 24"
+ fill="none"
+ stroke="currentColor"
+ @click="addFavorite(pokemon)"
+ >
+ <path
+ d="M12 17.27L18.18 21l-1.45-6.36L22 9.27l-6.36-.55L12 2 8.36 8.73 2 9.27l4.27 5.37L4.82 21z"
+ />
+ </svg>
+ </template>
</div>
</li>
</ul>
</div>
</div>
+ <div
+ class="fixed top-8 right-8 border border-black bg-white rounded shadow-lg py-4 px-6"
+ :class="{ hidden: isModalHidden }"
+ >
+ <p>{{ modalMessage }}</p>
+ </div>
</template>
<script>
~ 省略 ~
export default {
data() {
return {
pokemons: [],
+ favoriteNames: [],
+ isModalHidden: true,
+ modalMessage: "",
+ modalTimeout: null,
};
},
async created() {
await this.fetchPokemonList();
+ await this.fetchFavorites();
},
~ 省略 ~
methods: {
/**
* 一覧表示するポケモンのリストを取得
*/
async fetchPokemonList() {
const { data } = await axios.get("https://pokeapi.co/api/v2/pokemon", {
params: { offset: this.offset, limit: this.limit },
});
this.pokemons = [];
for (const result of data.results) {
const imageUrl = await this.fetchPokemonImage(result.name);
const name = await this.fetchPokemonName(result.name);
- this.pokemons.push({ name, imageUrl });
+ this.pokemons.push({ name, imageUrl, englishName: result.name });
}
},
~ 省略 ~
+ /**
+ * お気に入り取得
+ */
+ async fetchFavorites() {
+ const { data } = await axios.get("/api/pokemons/favorites");
+ this.favoriteNames = data;
+ },
+
+ /**
+ * お気に入り登録/解除メッセージ表示
+ */
+ showModal(message) {
+ this.modalMessage = message;
+ this.isModalHidden = false;
+ if (this.modalTimeout !== null) {
+ clearTimeout(this.modalTimeout);
+ }
+ this.modalTimeout = setTimeout(() => {
+ this.isModalHidden = true;
+ }, 3000);
+ },
+
+ /**
+ * お気に入り登録されているか
+ */
+ isIncludeFavorites(englishName) {
+ return this.favoriteNames.some(
+ (favoriteName) => favoriteName === englishName
+ );
+ },
+
+ /**
+ * お気に入り登録
+ */
+ async addFavorite(addPokemon) {
+ const { status } = await axios.post("/api/pokemons/add-favorite", {
+ pokemon_english_name: addPokemon.englishName,
+ });
+ if (status === 200) {
+ this.favoriteNames.push(addPokemon.englishName);
+ this.showModal(`${addPokemon.name}をお気に入り登録しました。`);
+ }
+ },
+
+ /**
+ * お気に入り解除
+ */
+ async deleteFavorite(deletePokemon) {
+ const { status } = await axios.post("/api/pokemons/delete-favorite", {
+ pokemon_english_name: deletePokemon.englishName,
+ });
+ if (status === 200) {
+ this.favoriteNames = this.favoriteNames.filter(
+ (favoriteName) => favoriteName !== deletePokemon.englishName
+ );
+ this.showModal(`${deletePokemon.name}をお気に入り解除しました。`);
+ }
+ },
},
};
</script>
画面からお気に入り登録/解除の操作を行うための処理内容について詳しく説明します。
ポケモンの名前の右側に表示される星の画像をクリックしたタイミングで処理を実行するため、SVG 要素にクリックイベントを設定しております。無色の星をクリックした場合はお気に入り登録、黄色の星をクリックした場合はお気に入り解除を行います。
お気に入り登録の処理は以下の通りです。
- Laravel のお気に入りポケモン登録 API を呼び出す
- 成功レスポンスが返却されたら、data プロパティで保持している
favoriteNames
の配列にポケモンの英語名を追加する - 成功メッセージを一定時間(3秒)表示する
async addFavorite(addPokemon) {
const { status } = await axios.post("/api/pokemons/add-favorite", {
pokemon_english_name: addPokemon.englishName,
});
if (status === 200) {
this.favoriteNames.push(addPokemon.englishName);
this.showModal(`${addPokemon.name}をお気に入り登録しました。`);
}
},
showModal(message) {
this.modalMessage = message;
this.isModalHidden = false;
if (this.modalTimeout !== null) {
clearTimeout(this.modalTimeout);
}
this.modalTimeout = setTimeout(() => {
this.isModalHidden = true;
}, 3000);
},
お気に入り解除の処理は以下の通りです。
- Laravel のお気に入りポケモン解除 API を呼び出す
- 成功レスポンスが返却されたら、data プロパティで保持している
favoriteNames
の配列から削除したポケモン以外の英語名を抽出してfavoriteNames
に上書きする - 成功メッセージを一定時間(3秒)表示する
async deleteFavorite(deletePokemon) {
const { status } = await axios.post("/api/pokemons/delete-favorite", {
pokemon_english_name: deletePokemon.englishName,
});
if (status === 200) {
this.favoriteNames = this.favoriteNames.filter(
(favoriteName) => favoriteName !== deletePokemon.englishName
);
this.showModal(`${deletePokemon.name}をお気に入り解除しました。`);
}
},
また、お気に入り登録されているポケモンは初期表示の時点で星を黄色にする必要があるため、created プロパティで fetchFavorites()
を呼び出して、Laravel のお気に入りポケモン取得 API を実行しています。
また、星の配色(無色と黄色)を切り替えるために isIncludeFavorites()
を用いて favoriteNames
に該当のポケモンの英語名が含まれているかどうかを判定しています。
async fetchFavorites() {
const { data } = await axios.get("/api/pokemons/favorites");
this.favoriteNames = data;
},
isIncludeFavorites(englishName) {
return this.favoriteNames.some(
(favoriteName) => favoriteName === englishName
);
},
これでお気に入り登録機能を作成することができました。
動作確認のため、ブラウザから http://localhost/pokemons にアクセスして お気に入り登録/解除を行ってください。星の配色が切り替わり、メッセージが表示されれば OK です。
追加課題
本記事で作成したアプリケーションには不足している機能が多くあります。
チュートリアルの応用として、以下のような機能を追加で作成してみてください。
追加機能例
ページング機能
現状では最初の20匹しか表示されないため、21匹目以降も表示可能とする。
お気に入りポケモン一覧表示
お気に入り登録したポケモンのみを一覧表示する機能を作成する。
表示件数変更
現状では20匹ずつ表示しているが、ユーザーが任意に表示件数を変更可能とする。
GitHub
完成版のプロジェクトはこちら