PrestaShop自定义产品文本模块表单未在Hook中显示求助
PrestaShop模块后台表单不显示问题排查与解决建议
我开发了一款PrestaShop模块,可为每个产品添加额外文本,支持在后台编辑并将文本保存至数据库,更新后数据可留存。但目前模块的编辑表单未在任何已安装的Hook中显示,恳请提供解决建议。
模块PHP代码
<?php if (!defined('_PS_VERSION_')) { exit; } class MyModuleText extends Module { protected $config_form = false; public function __construct() { $this->name = 'mymoduletext'; $this->tab = 'administration'; $this->version = '1.0.0'; $this->author = 'Jordi Comes'; $this->need_instance = 0; $this->bootstrap = true; parent::__construct(); $this->displayName = $this->l('My_Module_Text'); $this->description = $this->l('Crea un texto editable desde el backoffice para cualquier producto de forma independiente'); $this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_); } public function install() { include(dirname(__FILE__).'/sql/install.php'); $this->registerHook('displayProductTabContent'); $this->registerHook('actionProductUpdate'); $this->registerHook('displayProductAdditionalInfo'); $this->registerHook('header'); return parent::install() && Configuration::updateValue('MYMODULETEXT_MODULE_NAME', 'producttextmodule'); } public function uninstall() { include(dirname(__FILE__).'/sql/uninstall.php'); $this->unregisterHook('actionProductUpdate'); $this->unregisterHook('displayProductAdditionalInfo'); $this->unregisterHook('header'); return parent::uninstall() && Configuration::deleteByName('MYMODULETEXT_MODULE_NAME'); } public function hookDisplayProductTabContent($params) { $productText = $this->getProductText((int)$params['product']['id_product']); $this->smarty->assign(array( 'productText' => $productText, )); return $this->context->smarty->fetch($this->local_path.'../producttabcontent.tpl'); } public function hookActionProductUpdate($params) { if (Tools::isSubmit('submitProductTextModule')) { $id_product = (int)$params['id_product']; $text = pSQL(Tools::getValue('mymoduletext')); if (isset($text)) { $sql = 'REPLACE INTO `'._DB_PREFIX_.'mymoduletext` (`id_product`, `text`) VALUES ('.$id_product.', "'.$text.'")'; Db::getInstance()->execute($sql); } } } public function hookDisplayProductAdditionalInfo($params) { $id_product = (int)$params['product']['id_product']; $sql = 'SELECT `text` FROM `'._DB_PREFIX_.'mymoduletext` WHERE `id_product` = '.(int)$id_product; $text = Db::getInstance()->getValue($sql); if ($text === false) { return ''; } $this->context->smarty->assign(array( 'mymoduletext' => $text, )); return $this->context->smarty->fetch($this->local_path.'../producttextmodule.tpl'); } public function hookHeader() { $this->context->controller->addCSS($this->_path.'views/css/producttextmodule.css'); $this->context->controller->addJS($this->_path.'views/js/producttextmodule.js'); } public function getContent() { $output = ''; if (Tools::isSubmit('submitProductTextModule')) { $my_module_name = strval(Tools::getValue('MYMODULETEXT_MODULE_NAME')); if (!$my_module_name || empty($my_module_name) || !Validate::isGenericName($my_module_name) ) { $output .= $this->displayError($this->l('Invalid Configuration value')); } else { Configuration::updateValue('MYMODULETEXT_MODULE_NAME', $my_module_name); $output .= $this->displayConfirmation($this->l('Settings updated')); } } return $output.$this->displayForm(); } public function displayForm() { $default_lang = (int)Configuration::get('PS_LANG_DEFAULT'); $fields_form[0]['form'] = array( 'legend' => array( 'title' => $this->l('Settings'), ), 'input' => array( array( 'type' => 'text', 'label' => $this->l('Configuration value'), 'name' => 'MYMODULETEXT_MODULE_NAME_MODULE_NAME', 'size' => 20, 'required' => true ) ), 'submit' => array( 'title' => $this->l('Save'), 'class' => 'btn btn-default pull-right' ) ); $helper = new HelperForm(); $helper->module = $this; $helper->name_controller = $this->name; $helper->token = Tools::getAdminTokenLite('AdminModules'); $helper->currentIndex = AdminController::$currentIndex.'&configure='.$this->name; $languages = Language::getLanguages(false); $helper->default_form_language = $default_lang; $helper->allow_employee_form_lang = $default_lang; $helper->languages = $languages; $helper->title = $this->displayName; $helper->show_toolbar = true; $helper->toolbar_scroll = true; $helper->submit_action = 'submitProductTextModule'; $helper->toolbar_btn = array( 'save' => array( 'desc' => $this->l('Save'), 'href' => AdminController::$currentIndex.'&configure='.$this->name.'&save'.$this->name. '&token='.Tools::getAdminTokenLite('AdminModules'), ), 'back' => array( 'href' => AdminController::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminModules'), 'desc' => $this->l('Back to list') ) ); $helper->fields_value['MYMODULETEXT_MODULE_NAME'] = Configuration::get('MYMODULETEXT_MODULE_NAME'); return $helper->generateForm($fields_form); } } ?>
模板文件1:producttabcontent.tpl
<div class="product-text-module"> <form action="{$link->getAdminLink('AdminProducts')}&id_product={$product.id_product}&updateproduct" method="post"> <textarea name="mymoduletext" id="mymoduletext">{$productText}</textarea> <button type="submit" name="submitProductTextModule" class="btn btn-default">{l s='Save'}</button> </form> </div> {literal} <style> .product-text-module { padding: 20px; background-color: #f5f5f5; border-radius: 5px; margin-bottom: 20px; } </style> {/literal}
模板文件2:producttextmodule.tpl
<div class="product-text-module"> <p>{$mymoduletext}</p> </div> {literal} <style> .product-text-module { padding: 20px; background-color: #f5f5f5; border-radius: 5px; margin-bottom: 20px; } </style> {/literal}
解决建议
1. 注册后台产品编辑页专属Hook
当前注册的Hook均为前台产品页Hook,后台编辑产品的表单需要绑定displayAdminProductsExtra——这个Hook会在后台产品编辑页面底部渲染内容。
修改install()方法,添加后台Hook注册:
public function install() { include(dirname(__FILE__).'/sql/install.php'); $this->registerHook('displayProductTabContent'); $this->registerHook('actionProductUpdate'); $this->registerHook('displayProductAdditionalInfo'); $this->registerHook('header'); // 新增后台Hook $this->registerHook('displayAdminProductsExtra'); return parent::install() && Configuration::updateValue('MYMODULETEXT_MODULE_NAME', 'producttextmodule'); }
同时在uninstall()方法中添加取消注册:
$this->unregisterHook('displayAdminProductsExtra');
然后实现后台Hook的渲染方法:
public function hookDisplayAdminProductsExtra($params) { $id_product = (int)$params['id_product']; $productText = $this->getProductText($id_product); $this->context->smarty->assign(array( 'productText' => $productText, 'product' => $params['product'], 'token' => Tools::getAdminTokenLite('AdminProducts') )); // 按规范指向后台模板路径 return $this->context->smarty->fetch($this->_path.'views/templates/admin/producttabcontent.tpl'); }
2. 修复模板路径错误
当前代码中$this->local_path.'../producttabcontent.tpl'路径逻辑错误,local_path已指向模块根目录,无需../。建议按PrestaShop规范组织文件:
- 后台模板:
/views/templates/admin/producttabcontent.tpl - 前台模板:
/views/templates/front/producttextmodule.tpl
修改Hook中的模板路径为:
// 前台Hook示例 return $this->context->smarty->fetch($this->_path.'views/templates/front/producttextmodule.tpl'); // 后台Hook示例 return $this->context->smarty->fetch($this->_path.'views/templates/admin/producttabcontent.tpl');
3. 实现缺失的getProductText方法
代码中调用了$this->getProductText但未实现,会触发PHP错误导致Hook无法渲染,添加该方法:
private function getProductText($id_product) { $sql = 'SELECT `text` FROM `'._DB_PREFIX_.'mymoduletext` WHERE `id_product` = '.(int)$id_product; return Db::getInstance()->getValue($sql) ?: ''; }
4. 添加后台表单安全Token
后台表单必须包含PrestaShop安全Token,否则提交会被拦截。修改producttabcontent.tpl的form:
<form action="{$link->getAdminLink('AdminProducts')}&id_product={$product.id_product}&updateproduct" method="post"> <input type="hidden" name="token" value="{$token}"> <textarea name="mymoduletext" id="mymoduletext">{$productText}</textarea> <button type="submit" name="submitProductTextModule" class="btn btn-default">{l s='Save'}</button> </form>
5. 检查Hook注册状态
安装模块后,进入后台模块管理->位置页面,确认displayAdminProductsExtra已关联到你的模块。如果未显示,可尝试卸载重装模块,或手动在ps_hook_module数据库表中添加关联记录。
内容的提问来源于stack exchange,提问作者Jordi Comes
相关产品推荐
相关产品推荐

