StripeとPostgreSQLに登録されているデータの紐づけ
Next.jsとLaravelとStripeを使って商品管理システムを作っている最中に、同じ商品をそれぞれ①Stripeと②PostgreSQLに登録しています。
しかも、①と②それぞれの商品IDが違うので、紐づけを行う必要があります。
このさき、商品の編集や削除といった機能を作るときにはStripe側の商品IDとPostgreSQL側の商品IDの対関係が必要だからです。
したがって、どのようにして異なる商品ID値を持った同じ商品をつもづけたのかを備忘録として残しておきます。
【手順】
■Stripe側から商品を全件数分取得する
frontend/app/products/getListProducts/page.tsx
useEffect(() => {
axios.get('http://localhost:8000/api/stripe/products')
.then((response) => {
setStripeProducts(response.data);
});
}, []);
■Laravel経由でPostgreSQLから商品を全件数分取得する
frontend/app/products/getListProducts/page.tsx
useEffect(() => {
axios.get('http://localhost:8000/api/readAllProducts')
.then((response) => {
setProducts(response.data);
});
}, []);
■map
関数とfind
関数を使ってStripe側とPostgreSQL側の①商品名(ProductName)と②商品説明(Product Description)が同じかを判定して新規で定義した配列に詰める
frontend/app/products/getListProducts/page.tsx
const mergeProductData = (stripeProducts: any[], products: any[]) => {
return stripeProducts.map((stripeProduct) => {
// PostgreSQLの商品からnameとdescriptionの両方で一致する商品を探す
const matchedProduct = products.find(product =>
product.name === stripeProduct.name &&
product.description === stripeProduct.description
);
// `productId`をstripeProductに追加
return {
...stripeProduct,
productId: matchedProduct ? matchedProduct.productId : null, // 一致する場合は`productId`を追加
};
});
}
上記の方法で、Stripe側とPostgreSQL側とのデータの紐づけができました。
page.tsx
'use client'
import { useEffect, useState } from "react"
import axios from "axios"
import Header from "../productsComponents/header/page";
import { useRouter } from "next/navigation";
export default function AllListProducts() {
const router = useRouter();
const [stripeProducts, setStripeProducts] = useState<any[]>([]); // Stripeからの製品
const [products, setProducts] = useState<any[]>([]); // PostgreSQLからの製品
const [newProduct, setNewProduct] = useState({
name: '',
description: '',
price: 0
});
// Stripeからの商品データを取得
useEffect(() => {
axios.get('http://localhost:8000/api/stripe/products')
.then((response) => {
setStripeProducts(response.data);
});
}, []);
// PostgreSQLからの商品データを取得
useEffect(() => {
axios.get('http://localhost:8000/api/readAllProducts')
.then((response) => {
setProducts(response.data);
});
}, []);
// 商品IDをStripe商品に追加する処理(name と description 両方を使って関連付け)
const mergeProductData = (stripeProducts: any[], products: any[]) => {
return stripeProducts.map((stripeProduct) => {
// PostgreSQLの商品からnameとdescriptionの両方で一致する商品を探す
const matchedProduct = products.find(product =>
product.name === stripeProduct.name &&
product.description === stripeProduct.description
);
// `productId`をstripeProductに追加
return {
...stripeProduct,
productId: matchedProduct ? matchedProduct.productId : null, // 一致する場合は`productId`を追加
};
});
}
// 両方のデータを結びつけて、productIdを追加した結果を取得
const mergedProducts = mergeProductData(stripeProducts, products);
// 商品編集ボタンのクリックハンドラー
const clickProductEdit = () => {
router.push(`/products/editProduct`);
}
// 商品削除ボタンのクリックハンドラー
const clickProductDelete = () => {
router.push('');
}
return (
<div className="">
<Header />
<h1 className="font-bold">Product List</h1>
<table className="w-full table-auto border border-gray-500 rounded-md">
<thead className="bg bg-gray-100">
<tr>
<th className="p-4">ID</th>
<th className="p-4">Name</th>
<th className="p-4">Description</th>
<th className="p-4">
Price
<small>(USD)</small>
</th>
<th>Image</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{mergedProducts.length > 0 ? (
mergedProducts.map((product) => (
<tr key={product.id}>
<td className="p-4">{product.id}</td>
<td className="p-4">{product.name}</td>
<td className="p-4">{product.description}</td>
<td className="p-4">{product.price}</td>
<td className="p-4">
{product.images ? (
<img src={product.images[0]} style={{ width: 100 }} />
) : null}
</td>
<td className="p-4">
<button
type="button"
className="bg bg-blue-500 text-white rounded-md px-4 py-4"
onClick={clickProductEdit}
>
Edit
</button>
</td>
<td className="p-4">
<button
type="button"
className="bg bg-rose-500 text-white rounded-md px-4 py-4"
onClick={clickProductDelete}
>
Delete
</button>
</td>
</tr>
))
) : (
<tr>
<td colSpan={7} className="text-center p-4">
<p>Products are not register</p>
</td>
</tr>
)}
</tbody>
</table>
</div>
)
}