PrestaShop 1.7.8.7:停用商品自动重定向至父分类的实现方案
PrestaShop 1.7.8.7 停用商品自动重定向至父分类解决方案
方案一:覆盖ProductController核心控制器
这是最直接的处理方式,商品详情页请求由ProductController处理,我们在控制器初始化阶段判断商品状态,实现自动重定向。
- 创建覆盖文件:在
/override/controllers/front/目录下新建ProductController.php,写入以下代码:
<?php class ProductController extends ProductControllerCore { public function initContent() { parent::initContent(); // 检查商品是否存在且已停用 if (isset($this->product) && !$this->product->active) { // 获取商品默认父分类ID $id_category = $this->product->id_category_default; if ($id_category) { $category = new Category($id_category, $this->context->language->id); // 301永久重定向到分类页面 Tools::redirect($category->getLink(), null, null, 301); } } } }
生成覆盖缓存:后台进入高级参数 > 性能,点击「生成覆盖缓存」按钮,确保覆盖逻辑生效。
测试:访问任意停用商品的URL,验证是否自动跳转到对应父分类页面。
方案二:自定义模块实现(无需修改核心文件)
如果不想使用核心覆盖,可通过模块钩子拦截请求:
- 创建模块目录
/modules/disabledproductredirect/,新建disabledproductredirect.php:
<?php if (!defined('_PS_VERSION_')) { exit; } class DisabledProductRedirect extends Module { public function __construct() { $this->name = 'disabledproductredirect'; $this->tab = 'front_office_features'; $this->version = '1.0.0'; $this->author = 'Custom'; $this->need_instance = 0; $this->bootstrap = true; parent::__construct(); $this->displayName = $this->l('停用商品自动重定向'); $this->description = $this->l('将已停用商品页面自动重定向至所属父分类'); } public function install() { return parent::install() && $this->registerHook('actionDispatcherBeforeRenderController'); } public function hookActionDispatcherBeforeRenderController($params) { $controller = $params['controller']; // 仅拦截商品详情页请求 if ($controller instanceof ProductController) { $product = $controller->product; if ($product && !$product->active) { $id_category = $product->id_category_default; if ($id_category) { $category = new Category($id_category, $this->context->language->id); Tools::redirect($category->getLink(), null, null, 301); } } } } }
- 后台安装模块:进入模块管理器 > 上传模块,上传模块压缩包完成安装,确保钩子注册成功。
方案三:修正.htaccess重定向生成脚本
若之前的脚本失效,大概率是未正确获取商品与分类的SEO URL,以下是修正后的脚本:
创建generate_redirects.php放在网站根目录,执行后会将重定向规则追加到.htaccess:
<?php require_once(dirname(__FILE__).'/config/config.inc.php'); require_once(dirname(__FILE__).'/init.php'); // 获取所有已停用且有父分类的商品 $disabled_products = Db::getInstance()->executeS(' SELECT p.id_product, pl.link_rewrite, cl.link_rewrite as cat_link FROM '._DB_PREFIX_.'product p LEFT JOIN '._DB_PREFIX_.'product_lang pl ON p.id_product = pl.id_product AND pl.id_lang = '.(int)Context::getContext()->language->id.' LEFT JOIN '._DB_PREFIX_.'category c ON p.id_category_default = c.id_category LEFT JOIN '._DB_PREFIX_.'category_lang cl ON c.id_category = cl.id_category AND cl.id_lang = '.(int)Context::getContext()->language->id.' WHERE p.active = 0 AND c.id_category IS NOT NULL '); $redirect_rules = []; foreach ($disabled_products as $product) { $product_url = __PS_BASE_URI__.$product['link_rewrite'].'.html'; $category_url = __PS_BASE_URI__.$product['cat_link'].'.html'; $redirect_rules[] = "Redirect 301 $product_url $category_url"; } // 写入.htaccess并避免重复规则 $htaccess_path = dirname(__FILE__).'/.htaccess'; if (file_exists($htaccess_path)) { $current_content = file_get_contents($htaccess_path); $current_content = preg_replace('/# START Disabled Product Redirects(.*?)# END Disabled Product Redirects/s', '', $current_content); $new_content = $current_content."\n# START Disabled Product Redirects\n".implode("\n", $redirect_rules)."\n# END Disabled Product Redirects\n"; file_put_contents($htaccess_path, $new_content); echo '重定向规则生成成功!'; } else { echo '未找到.htaccess文件!'; }
执行完成后立即删除该脚本,避免安全风险。此方案适合静态URL场景,若商品/分类SEO链接变更,需重新执行脚本更新规则。
常见问题排查
- 覆盖文件失效:检查
/cache/class_index.php是否更新,未更新则手动删除后刷新页面。 - 模块钩子不生效:确认模块已安装,且
actionDispatcherBeforeRenderController钩子已注册,可在后台模块 > 钩子中查看。 - .htaccess规则无效:检查服务器是否启用
mod_rewrite模块,确保.htaccess文件权限正确。
内容的提问来源于stack exchange,提问作者Ambre Ramos
相关产品推荐
相关产品推荐

