My project using strapi v4 for design backend and sql. Unfornately, the id in REST API when I request is differ from the id in the Content Manager (The UI strapi). You can see the differences here:
I've read some documents and found it due to the algorithms creating id in UI and backend is not the same. So basically, we cannot fix this bug of id.
This case is not rare, you can find another case here: https://github.com/strapi/strapi/issues/21967
This bug makes me crazy cause I cannot get any information of the data because the id is not matched.
But I'm not going to ask for help. I posted a post that need for help but it seems like no one faced the same problem (or maybe my post is not up-trending). So I write this post to hope someone in same find a way to fix. This is not the best way (just a temporary method to fix) but you still can get through the bug. I CHOSE A NEW WAY TO MATCH THE ID: it's called slug. Yes, you cannot match the id so you need to choose another variable, which is the same in REST API and Content Manager and also UNIQUE.
A new problem arises When you need to get informations of a data, you still get by slug, no problem. But when you need to push the data into backend. The strapi doesn't allow us to push by slug. For example, in my shopping-project, when user need to store the product into cart, my project not only cannot push the id product to backend due to id not match but also cannot push slug due to Strapi doesn't allow.
What's next? We need to make the Strapi allow.
- First, you have to create a variable called slug or anything you want, provided that it is an UNIQUE ID
- Second, whenever you create a product or data, you have to push that slug along, to provide any product always have slug.
- Third, when you've done all the step above, you need to make Strapi allows pushing slug. For example when you need to get product's information by slug.
const getProductBySlug = async (slug) => {
const res = await axiosClient.get(
'/products?filters[slug][$eq]=${encodeURIComponent(slug)}&populate=*'
);
// console.log("DEBUG API Response", res.data);
const product = res?.data?.data?.[0];
return product ?? null;
};
1.When you need to push the cart has information of products, you have to do more:
In globalApi, still the same:
const addToCart = (data, jwt) => axiosClient.post('/user-carts', data, {
headers: {
Authorization: 'Bearer ' + jwt
}
})
You have to adjust the code in the folder run Strapi (backend)
2.Adjust the modules of type builder, for example in my project this is:
'towerl-api/src/api/user-cart/routes/user-cart.js'
At first, the file just using the default module exports of Strapi, that means it just allows us to delete by id, there you have to create a new module that allow us to delete by slug. Due to that you have to rewrite all the method include the default method:
const { createCoreRouter } = require('@strapi/strapi').factories;
module.exports = {
routes: [
// DEFAULT ROUTES OF CORE
{
method: 'GET',
path: '/user-carts',
handler: 'user-cart.find',
config: { policies: [] },
},
{
method: 'GET',
path: '/user-carts/:id',
handler: 'user-cart.findOne',
config: { policies: [] },
},
{
method: 'POST',
path: '/user-carts',
handler: 'user-cart.create',
config: { policies: [] },
},
{
method: 'PUT',
path: '/user-carts/:id',
handler: 'user-cart.update',
config: { policies: [] },
},
{
method: 'DELETE',
path: '/user-carts/:id',
handler: 'user-cart.delete',
config: { policies: [] },
},
// Adjust route: DELETE BY SLUG
{
method: 'DELETE',
path: '/user-carts/slug/:slug',
handler: 'user-cart.deleteBySlug',
config: { policies: [] },
},
],
};
3.Last but not least, you also need to adjust the file user-cart.js from towerl-api/src/api/user-cart/controllers/user-cart.js
This is used for create function to replace slug with product ID
'use strict';
const { createCoreController } = require('@strapi/strapi').factories;
module.exports = createCoreController('api::user-cart.user-cart', ({ strapi }) => ({
async create(ctx) {
const { data } = ctx.request.body;
// Get slug
const slug = data.products.connect[0];
// Find product by slug
const productEntry = await strapi.entityService.findMany('api::product.product', {
filters: { slug },
limit: 1,
});
if (!productEntry || productEntry.length === 0) {
return ctx.badRequest('Product does not exist with the provided slug.');
}
const productId = productEntry[0].id;
// Replace slug with product ID
data.products.connect = [{ id: productId }];
// Call Strapi's default create function
const response = await super.create(ctx);
return response;
},
async deleteBySlug(ctx) {
const { slug } = ctx.params;
const entity = await strapi.db.query('api::user-cart.user-cart').findOne({
where: { cartSlug: slug },
});
if (!entity) {
return ctx.notFound('Cart not found');
}
await strapi.db.query('api::user-cart.user-cart').delete({
where: { id: entity.id },
});
ctx.send({ message: 'Deleted successfully' });
}
}));
That's all, you've changed the method post/get product by id (it's a bug from Strapi) into method post/get product by slug, I don't know when will the bug get fixed but I think it's good when you need to fix quickly.
If you have something differ to me, please don't hesitate to comment to this post. I hope this post helps you and also me in the way of becoming a nice programming!!
You can visit my project fixed by the way above, your suggestion will be very helpful to me:
https://github.com/TruoYang/my-shopping-project
Top comments (0)