我在实现向购物车中添加或删除产品的逻辑时遇到了一些困难。
首先在我的数据库层面:
这意味着用户实际上有“几个篮子”(一个产品=一个篮子)
这是我如何使用 sequelize 创建模型/关系:
// Inside db.config.js
db.paniers = sequelize.define('panier', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
field: 'PAN_ID'
},
userId: {
type: Sequelize.INTEGER,
references: {
model: db.users,
key: 'USE_ID'
},
primaryKey: true,
allowNull: false,
field: 'USE_ID'
},
produitId : {
type: Sequelize.INTEGER,
references: {
model: db.produits,
key: 'PRO_ID'
},
primaryKey: true,
allowNull: false,
field: 'PRO_ID'
},
quantite: {
type: Sequelize.INTEGER,
allowNull: false,
field: 'PAN_QUANTITE'
}
}, {
tableName: 'PANIER'
});
然后对于查询,做了两个查询:
一个显示购物车的信息(购物车 ID、产品 ID、产品名称、产品价格、产品图片、购物车数量)
另一个更新数量。
这是我如何在 POSTMAN 下进行 axios 查询和结果
const APIURL = 'http://localhost:8090/api';
// Get the details of the cart
export const getDetails = (userId) => axios.get(`${APIURL}/panier/details/${userId}`,
{
userId: userId,
});
// Update the quantity of the cart
export const updateQuantite = (produitId) => axios.put(`${APIURL}/panier/${produitId}`,
{
produitId: produitId,
});
// Result for the userId 1 (getDetails)
{
"PRO_ID": 1,
"PRO_NOM": "Un immeuble",
"PRO_PRIX": "1515",
"PRO_URL": "58afa4f2-41b1-42f7-a371-6d267784c44e.jpg",
"PAN_QUANTITE": 1,
"PAN_ID": 1
},
{
"PRO_ID": 2,
"PRO_NOM": "Model",
"PRO_PRIX": "102",
"PRO_URL": "a76fbe76-a183-49fa-84ee-40d5da08b91f.png",
"PAN_QUANTITE": 1,
"PAN_ID": 2
}
这是我的两个控制器管理他的路线:
// Display the informations of the basket
exports.getDetails = (req, res) => {
const queryResult = db.sequelize.query(
'SELECT P.PRO_ID, PRO_NOM, PRO_PRIX, PRO_URL, PA.PAN_QUANTITE, PA.PAN_ID\n' +
'FROM panier AS PA INNER JOIN produit AS P ON PA.PRO_ID = P.PRO_ID\n' +
'WHERE USE_ID = :id',
{
replacements: { id: req.params.userId },
type: QueryTypes.SELECT
}
).then(panier => {
res.json(panier);
}).catch(err => res.status(400).send(err));
}
// Modify the quantity of a basket
exports.update = (req, res) => {
Paniers.update({
quantite: req.body.quantite
}, {
where: {
produitId: req.params.produitId
}
}).then(panier => {
res.json(panier);
}).catch(err => res.status(400).send(err));
}
这就是我的信息的显示方式(仍在开发中,这就是为什么它看起来真的不像任何东西^^')
这是我迷路的地方... 这是我的购物车 pagePage.js :
import React, { useState, useEffect } from 'react';
import { Card, CardHeader, CardMedia, Grid, ButtonGroup, Button} from '@material-ui/core';
import PayPal from '../services/PayPal/paypal'
import {getDetails, updateQuantite, getAllPanier, get} from '../services/API/panier'
export default function PanierPage() {
// Récupération des détails des paniers
const [paniers, setPaniers] = useState([])
const getPaniersDetails = () => [
getDetails(JSON.parse(localStorage.getItem('User')).id).then(response => {
setPaniers(response.data)
console.log(response)
}).catch(err => console.log(err))
]
const handleIncrement = (id) => {
updateQuantite(id).then(response => {
// ???
}).catch(err => console.log(err))
}
const handleDecrement = () => {
}
// Affichage des détails des paniers
const paniersAffichage = paniers.map((panier) => (
<Grid container>
<Card key={panier.PAN_ID}>
<CardHeader title={panier.PRO_NOM}/>
<CardMedia image={`http://localhost:8090/${panier.PRO_URL}`}/>
<Button onClick={() => handleIncrement(panier.PRO_ID)}> + </Button>
{panier.PAN_QUANTITE}
<Button onClick={handleDecrement}> - </Button>
</Card>
</Grid>
));
// Chargement des produits
useEffect(() => {
getPaniersDetails();
}, [])
return (
<>
<Grid>
{paniersAffichage}
</Grid>
<PayPal/>
</>
);
}
解释:
我在“getPaniersDetails”中获取我的购物篮信息,在其中指明用户 ID,然后将其加载到我的 useEffect 中。
basketsDisplay 允许我显示相关用户的购物篮。
我在每张卡片中给出了用于映射的购物车的 ID,然后我显示了信息...... 当点击“+”时,我想增加我的数量,所以我给了它产品 ID。
handleIncrement 因此将使用“updateQuantite”处理此操作。
这是我屏蔽的地方,我有一种将自己混在不同 ID 之间的印象。特别是在表的购物车 ID 和我查询的购物车 ID 之间(SELECT)
我确信设置起来非常简单,但在我看来,这对我来说似乎很复杂......
如果我错过了任何重要的点告诉我,我会尽力改变我的帖子
答案 0 :(得分:0)
你的对象模型没有多大意义。
我会改变它以使其更具活力。
如果你有用户,而且他们有一个购物篮属性,这种方法更有意义。
注意:下面的代码是一个粗略的大纲,但应该能让你知道如何去做。
interface Database {
users: User[]; // Array of users.
}
interface User {
id: number;
username: string;
passwordHash: string;
baskets: Basket[];
}
interface Basket {
id: number;
items: Item[]; // array of items;
date: string;
}
interface Item {
id: number; // ID of the item.
name: string;
imgURL: string;
description: string[];
quantity: number;
}
现在如果我们想接收数据并将数据发送到数据库,我们会这样做。
interface Basket {
items: string[]; // list of item id's.
}
// You want to use a session token instead of the user id so noone but the user can access their basket.
// Normaly baskets will be local to the browser or app and not sored on a servers database.
// Only past orders should be stored. But in this example, we are storing the current basket too.
async function getBasket(sessionToken: string){
return await axios.get(`${api.host}/basket`, {
headers: {
Session-Token: sessionToken, // used to identify the user
Content-Type: "application/json",
}
}).data;
}
// we send the basket object, which is just a list of IDs, and the session token.
async function setBasket(basket: Basket, sessionToken: string){
return await axios.put(`${api.host}/basket`, {
headers: {
Session-Token: sessionToken, // used to identify the user
Content-Type: "application/json",
}
}).data;
}
现在在服务器端,使用 express 我们可以处理请求。
要使用 express 实现会话,有 npm 模块 express-session
,它是 express 的中间件。当用户登录时,他们将获得一个标头,将其保存为 cookie 以用于未来的请求。当他们退出时,会话将从您的服务器中删除,并在客户端上删除 cookie。
为了增加安全性,您可以设置会话的过期时间。用户必须重新登录并获得新会话。
// check the documentation to tune it to what you need.
app.use(session({
secret: 'mySuperSecret',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}))
app.get("/basket", async(req, res) => {
// here we first check if the session exists.
if(req.session.views){
// if it does, then we return the list of baskets.
const { baskets } = await getUser(req.session.userID);
res.sendStatus(200).send([success: true, data: baskets]);
}
// if not, then we will return a 403 error.
// we also send a response that matches the layout of the normal response.
res.sendStatus(403).send([success: false, data: []]);
})
app.put("/basket", (req, res) => {
// here we first check if the session exists.
if(req.session.views){
// if it does, then we add the basket to the user.
addBasket(req.session.userID, basket)
.then(res.sendStatus(204).send([success: true, data: []]))
}
// if not, then we will return a 403 error.
// we also send a response that matches the layout of the normal response.
res.sendStatus(403).send([success: false, data: []]);
})
如果您有任何问题,请在评论部分提问。有空我会回复的。