[英]Override Prestashop Module Controller: Where to place php file?
I am attempting to override a module in Prestashop. 我试图覆盖Prestashop中的模块。 I have successfully overridden the modules' templates but I cannot successfully overwrite the modules' controller.
我已经成功覆盖了模块的模板,但是无法成功覆盖模块的控制器。
Where should the new controller class file be placed? 新的控制器类文件应放在何处?
I have tried the following locations but they dont add new behaviour (change anything): 我尝试了以下位置,但它们未添加新行为(更改任何内容):
~/overrides/modules/blockwishlist/controllers/front/mywishlist.php
〜/ overrides / modules / blockwishlist / controllers / front / mywishlist.php
~/themes/MY_THEME/modules/blockwishlist/controllers/front/mywishlist.php〜/ themes / MY_THEME / modules / blockwishlist / controllers / front / mywishlist.php
According to my previous question I could do it by editing core classes (suggested kindly by u/Sergii P) but I am sure there is a standard way to do this that doesn't involve editing core classes? 根据我之前的问题,我可以通过编辑核心类(由u / Sergii P推荐)来做到这一点,但是我确定有一种标准方法可以实现,而无需编辑核心类?
For reference; 以供参考; here is the contents of
mywishlist.php
: 这是
mywishlist.php
的内容:
<?php
if (!defined('_CAN_LOAD_FILES_'))
exit;
//class BlockWishListMyWishListModuleFrontController extends BlockWishListMyWishListModuleFrontControllerCore // extends ModuleFrontController
class BlockWishListMyWishListModuleFrontControllerOverride extends BlockWishListMyWishListModuleFrontController
{
public function __construct()
{
parent::__construct();
}
/**
* Assign wishlist template
*/
public function assign()
{
$errors = array();
....
$this->setTemplate('mywishlist.tpl');
}
}
EDIT: I have a possible workaround for not being able to override the ModuleFrontController
class. 编辑:我有一个可能的解决方法,无法覆盖
ModuleFrontController
类。 The objective is to add an 'Export to CSV' button to the My Wishlists page, when the button is clicked the server will generate a CSV file containing all products in that wishlist. 目的是在“我的愿望清单”页面上添加一个“导出到CSV”按钮,单击该按钮时,服务器将生成一个包含该愿望清单中所有产品的CSV文件。 Before I do all the work, can you provide advice on whether this is possible...
在我完成所有工作之前,您能否提供关于是否可行的建议?
{hook h='displayExportToCsvColumn' mod='myCustomModule'}
{hook h='displayExportToCsvColumn' mod='myCustomModule'}
BlockWishlist
( ~/themes/MY_THEME/modules/blockwishlist/controllers/front/mywishlist.php ) and then my hook will call my custom module. BlockWishlist
( 〜/ themes / MY_THEME / modules / blockwishlist / controllers / front / mywishlist.php ),然后我的钩子将调用我的自定义模块。 Is this possible? As far as I could work out, you can't override ModuleFrontController
at the moment (sorry to say). 据我
ModuleFrontController
,您目前无法覆盖ModuleFrontController
(对不起)。 The clues lie within Dispatcher::dispatch()
: 线索位于
Dispatcher::dispatch()
:
case self::FC_MODULE :
$module_name = Validate::isModuleName(Tools::getValue('module')) ? Tools::getValue('module') : '';
$module = Module::getInstanceByName($module_name);
$controller_class = 'PageNotFoundController';
if (Validate::isLoadedObject($module) && $module->active) {
$controllers = Dispatcher::getControllers(_PS_MODULE_DIR_.$module_name.'/controllers/front/');
if (isset($controllers[strtolower($this->controller)])) {
include_once(_PS_MODULE_DIR_.$module_name.'/controllers/front/'.$this->controller.'.php');
$controller_class = $module_name.$this->controller.'ModuleFrontController';
}
}
$params_hook_action_dispatcher = array('controller_type' => self::FC_FRONT, 'controller_class' => $controller_class, 'is_module' => 1);
break;
It only checks the /modules/?/controllers/
directory. 它仅检查
/modules/?/controllers/
目录。 You can't override the ModuleFrontController
classes, but if you're smart enough, you can override Dispatcher
class and make it scan for overrides of ModuleFrontController
. 您不能覆盖
ModuleFrontController
类,但是如果您足够聪明,则可以覆盖Dispatcher
类并使它扫描ModuleFrontController
覆盖。
Usually there is a way to alter things you want with hooks, worst case scenario - inject javascript via hook and alter content. 通常,在最坏的情况下,有一种方法可以用钩子来更改所需的东西-通过钩子注入javascript并更改内容。
Hey I've struggled with this issue aswell. 嘿,我也在这个问题上苦苦挣扎。 I ended up spotting a solution on the prestashop forums : https://www.prestashop.com/forums/topic/480523-override-front-controller-of-modules/
我最终在prestashop论坛上发现了一个解决方案: https : //www.prestashop.com/forums/topic/480523-override-front-controller-of-modules/
The user Alex has created a override for the Dispatcher that will check for any module controller overrides. 用户Alex已为Dispatcher创建一个替代,它将检查是否有任何模块控制器替代。
The file does not seem to be available on the forum anymore you can however still find it here along with some explanations on how it works : http://nemops.com/overriding-modules-controllers-in-prestashop-1-6/#.XDR7HHX0muU 该文件似乎不再在论坛上可用,但是您仍然可以在这里找到它,以及有关其工作原理的一些解释: http : //nemops.com/overriding-modules-controllers-in-prestashop-1-6/ #.XDR7HHX0muU
In case none of those work anymore here is the code : 如果这些都不起作用,则代码如下:
<?php
if (!defined('_PS_VERSION_')) {
exit;
}
class Dispatcher extends DispatcherCore
{
public function dispatch()
{
$controller_class = '';
// Get current controller
$this->getController();
if (!$this->controller) {
$this->controller = $this->useDefaultController();
}
// Dispatch with right front controller
switch ($this->front_controller) {
// Dispatch front office controller
case self::FC_FRONT :
$controllers = Dispatcher::getControllers(
array(_PS_FRONT_CONTROLLER_DIR_, _PS_OVERRIDE_DIR_.'controllers/front/')
);
$controllers['index'] = 'IndexController';
if (isset($controllers['auth'])) {
$controllers['authentication'] = $controllers['auth'];
}
if (isset($controllers['compare'])) {
$controllers['productscomparison'] = $controllers['compare'];
}
if (isset($controllers['contact'])) {
$controllers['contactform'] = $controllers['contact'];
}
if (!isset($controllers[strtolower($this->controller)])) {
$this->controller = $this->controller_not_found;
}
$controller_class = $controllers[strtolower($this->controller)];
$params_hook_action_dispatcher = array(
'controller_type' => self::FC_FRONT,
'controller_class' => $controller_class,
'is_module' => 0,
);
break;
// Dispatch module controller for front office
case self::FC_MODULE :
$module_name = Validate::isModuleName(Tools::getValue('module')) ? Tools::getValue('module') : '';
$module = Module::getInstanceByName($module_name);
$controller_class = 'PageNotFoundController';
if (Validate::isLoadedObject($module) && $module->active) {
$controllers = Dispatcher::getControllers(_PS_MODULE_DIR_.$module_name.'/controllers/front/');
if (isset($controllers[strtolower($this->controller)])) {
include_once(_PS_MODULE_DIR_.$module_name.'/controllers/front/'.$this->controller.'.php');
if (file_exists(
_PS_OVERRIDE_DIR_.'modules/'.$module_name.'/controllers/front/'.$this->controller.'.php'
)) {
include_once(_PS_OVERRIDE_DIR_.'modules/'.$module_name.'/controllers/front/'.$this->controller.'.php');
$controller_class = $module_name.$this->controller.'ModuleFrontControllerOverride';
} else {
$controller_class = $module_name.$this->controller.'ModuleFrontController';
}
}
}
$params_hook_action_dispatcher = array(
'controller_type' => self::FC_FRONT,
'controller_class' => $controller_class,
'is_module' => 1,
);
break;
// Dispatch back office controller + module back office controller
case self::FC_ADMIN :
if ($this->use_default_controller && !Tools::getValue('token') && Validate::isLoadedObject(
Context::getContext()->employee
) && Context::getContext()->employee->isLoggedBack()) {
Tools::redirectAdmin(
'index.php?controller='.$this->controller.'&token='.Tools::getAdminTokenLite($this->controller)
);
}
$tab = Tab::getInstanceFromClassName($this->controller, Configuration::get('PS_LANG_DEFAULT'));
$retrocompatibility_admin_tab = null;
if ($tab->module) {
if (file_exists(_PS_MODULE_DIR_.$tab->module.'/'.$tab->class_name.'.php')) {
$retrocompatibility_admin_tab = _PS_MODULE_DIR_.$tab->module.'/'.$tab->class_name.'.php';
} else {
$controllers = Dispatcher::getControllers(_PS_MODULE_DIR_.$tab->module.'/controllers/admin/');
if (!isset($controllers[strtolower($this->controller)])) {
$this->controller = $this->controller_not_found;
$controller_class = 'AdminNotFoundController';
} else {
// Controllers in modules can be named AdminXXX.php or AdminXXXController.php
include_once(_PS_MODULE_DIR_.$tab->module.'/controllers/admin/'.$controllers[strtolower(
$this->controller
)].'.php');
$controller_class = $controllers[strtolower($this->controller)].(strpos(
$controllers[strtolower($this->controller)],
'Controller'
) ? '' : 'Controller');
}
}
$params_hook_action_dispatcher = array(
'controller_type' => self::FC_ADMIN,
'controller_class' => $controller_class,
'is_module' => 1,
);
} else {
$controllers = Dispatcher::getControllers(
array(
_PS_ADMIN_DIR_.'/tabs/',
_PS_ADMIN_CONTROLLER_DIR_,
_PS_OVERRIDE_DIR_.'controllers/admin/',
)
);
if (!isset($controllers[strtolower($this->controller)])) {
// If this is a parent tab, load the first child
if (Validate::isLoadedObject($tab) && $tab->id_parent == 0 && ($tabs = Tab::getTabs(
Context::getContext()->language->id,
$tab->id
)) && isset($tabs[0])) {
Tools::redirectAdmin(Context::getContext()->link->getAdminLink($tabs[0]['class_name']));
}
$this->controller = $this->controller_not_found;
}
$controller_class = $controllers[strtolower($this->controller)];
$params_hook_action_dispatcher = array(
'controller_type' => self::FC_ADMIN,
'controller_class' => $controller_class,
'is_module' => 0,
);
if (file_exists(_PS_ADMIN_DIR_.'/tabs/'.$controller_class.'.php')) {
$retrocompatibility_admin_tab = _PS_ADMIN_DIR_.'/tabs/'.$controller_class.'.php';
}
}
// @retrocompatibility with admin/tabs/ old system
if ($retrocompatibility_admin_tab) {
include_once($retrocompatibility_admin_tab);
include_once(_PS_ADMIN_DIR_.'/functions.php');
runAdminTab($this->controller, !empty($_REQUEST['ajaxMode']));
return;
}
break;
default :
throw new PrestaShopException('Bad front controller chosen');
}
// Instantiate controller
try {
// Loading controller
$controller = Controller::getController($controller_class);
// Execute hook dispatcher
if (isset($params_hook_action_dispatcher)) {
Hook::exec('actionDispatcher', $params_hook_action_dispatcher);
}
// Running controller
$controller->run();
} catch (PrestaShopException $e) {
$e->displayMessage();
}
}
}
After this it is possible to override module controllers by putting the override file in : 此后,可以通过将替代文件放入以下位置来替代模块控制器:
override/modules/{moduleName}/controllers/{front/admin}/{filename}.php
In this file you have to define a class with the exact same name as the class you want to override and append "Override" at the end of the classname. 在此文件中,您必须定义一个名称与要覆盖的类完全相同的类,并在类名的末尾附加“ Override”。
I hope this helps 我希望这有帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.