PrestaShop脚本添加商品附件后前端不显示问题求助
PrestaShop商品附件前端不显示问题排查与解决思路
问题背景
我编写了PHP脚本为已导入的PrestaShop商品添加附件,ps_attachment、ps_attachment_lang等3张数据表已正确填充,后台商品页面“选项”标签中能看到附件已勾选,但附件在前端商品页面无法显示,仅在点击后台的“预览”或“保存”操作后才会显示。
已执行的操作:
- 清空缓存
- 删除
var/cache下的dev和prod缓存文件夹 - 编写调用
$product->save()方法的PHP脚本
原附件添加脚本
<?php $csvFile = "xxxx.csv"; if (($handle = fopen($csvFile, "r")) !== FALSE) { // Parcours des lignes du fichier CSV while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) { $reference = $data[0]; // Référence du produit $files = explode(",", $data[1]); // Chemins vers les fichiers (séparés par une virgule) // Récupération de l'ID du produit $sql = "SELECT id_product FROM ps_product WHERE reference = '$reference'"; $result = $conn->query($sql); echo "$reference"; if ($result->num_rows > 0) { $row = $result->fetch_assoc(); $productId = $row["id_product"]; echo "$productId"; // Parcours des fichiers joints foreach ($files as $file) { // Obtention de la taille du fichier en octets $fileSize = filesize($file); $fileName = basename($file); // Nom du fichier // Vérification si le fichier existe déjà pour le produit donné $sqlCheck = "SELECT id_attachment FROM ps_product_attachment WHERE id_product = '$productId'"; $resultCheck = $conn->query($sqlCheck); $attachmentId = null; if ($resultCheck->num_rows > 0) { // Parcourir les résultats pour vérifier si le fichier existe déjà while ($rowCheck = $resultCheck->fetch_assoc()) { $existingAttachmentId = $rowCheck["id_attachment"]; // Vérifier si le fichier est déjà associé au produit $sqlFileCheck = "SELECT id_attachment FROM ps_attachment WHERE id_attachment = '$existingAttachmentId' AND file = '$file'"; $resultFileCheck = $conn->query($sqlFileCheck); if ($resultFileCheck->num_rows > 0) { // Le fichier existe déjà pour le produit donné $attachmentId = $existingAttachmentId; break; } } } if ($attachmentId === null) { // Le fichier n'existe pas encore pour le produit, l'insérer dans ps_attachment $sqlInsertAttachment = "INSERT INTO ps_attachment (file, file_name, file_size, mime) VALUES ('$file', '$fileName', '$fileSize', 'application/pdf')"; if ($conn->query($sqlInsertAttachment) === TRUE) { $attachmentId = $conn->insert_id; } else { echo "Erreur lors de l'ajout du fichier joint : " . $conn->error . "\n"; } } if ($attachmentId !== null) { // Associer le fichier joint au produit dans ps_product_attachment $sqlInsertProductAttachment = "INSERT INTO ps_product_attachment (id_product, id_attachment) VALUES ('$productId', '$attachmentId')"; if ($conn->query($sqlInsertProductAttachment) === TRUE) { echo "Fichier joint ajouté avec succès pour le produit $reference.\n"; // Récupération de l'ID de l'attachment après insertion $idAttachment = $attachmentId; // Parcours des langues prises en charge $idLang = 1; $name = $data[$idLang]; // Récupération du nom du fichier joint dans la langue spécifiée $description = $data[$idLang]; // Récupération de la description du fichier joint dans la langue spécifiée // Insertion des informations de langue dans la table ps_attachment_lang $sqlInsertAttachmentLang = "INSERT INTO ps_attachment_lang (id_attachment, id_lang, name, description) VALUES ('$idAttachment', '$idLang', '$name', '$description')"; if ($conn->query($sqlInsertAttachmentLang) === TRUE) { echo "Informations de langue ajoutées avec succès pour l'attachment $idAttachment et la langue $idLang.\n"; } else { echo "Erreur lors de l'ajout des informations de langue : " . $conn->error . "\n"; } } else { echo "Erreur lors de l'association du fichier joint pour le produit $reference : " . $conn->error . "\n"; } } } } else { echo "Produit non trouvé pour la référence : $reference.\n"; } } fclose($handle); } $conn->close(); ?>
尝试的$product->save()脚本
<?php require(dirname(__FILE__).'/config/config.inc.php'); define('_PS_ROOT_DIR_', dirname(dirname(__FILE__)).'/'); // Inclusion de la classe Product require_once _PS_ROOT_DIR_ . '/classes/Product.php'; // Liste des références de produits à cibler $targetReferences = array( '20052' ); foreach ($targetReferences as $reference) { // Recherche du produit par référence $productId = Product::getIdByReference($reference); if ($productId) { $product = new Product($productId); // Enregistrer les options sans modification $product->save(); echo "Produit mis à jour pour la référence : " . $reference . "<br>"; } else { // Gérer le cas où la référence du produit n'est pas trouvée echo "Produit non trouvé pour la référence : " . $reference . "<br>"; } } ?>
解决思路
1. 强制同步产品索引与附件关联
后台点击保存/预览时,PrestaShop会自动刷新产品索引表(如ps_product_index)并更新缓存关联。直接操作数据库添加附件后,这些关联未同步,导致前端无法读取。修改更新脚本,主动触发索引更新:
$product = new Product($productId); // 强制重新加载附件关联 $product->attachments = $product->getAttachments(Context::getContext()->language->id); // 触发产品属性与索引更新 Product::updateProductAttributes($productId); $product->save();
2. 校验附件路径格式
前端显示附件需要符合PrestaShop规范的路径,对比后台手动添加的附件file字段值,确保脚本插入的路径格式一致(比如是否带/前缀、相对路径是否正确)。
3. 全量清理缓存
除删除var/cache下的文件夹,还需:
- 后台“高级参数>性能”中点击“清除缓存”,选择清除所有缓存
- 若使用Redis等外部缓存,同步清除对应产品的缓存数据
4. 使用官方类方法替代直接SQL操作
直接操作数据库容易遗漏内部钩子和关联逻辑,改用Attachment类方法处理:
// 创建附件 $attachment = new Attachment(); $attachment->file = $file; $attachment->file_name = $fileName; $attachment->file_size = $fileSize; $attachment->mime = 'application/pdf'; $attachment->add(); // 设置多语言信息 $attachment->name[$idLang] = $name; $attachment->description[$idLang] = $description; $attachment->update(); // 关联到产品 $attachment->attachToProduct($productId);
该方式会自动触发内部关联更新与缓存刷新,避免遗漏步骤。
内容的提问来源于stack exchange,提问作者Bahwaimongars
相关产品推荐
相关产品推荐

