Overriding controllers in Prestashop 1.7 - php

Hi I want to override a controller (in /controllers/front/MyAccountController.php) I tried different things :
In a custom module : /modules/my_module/override/controllers/front/MyAccountController.php
class MyAccountController extends MyAccountControllerCore
{
/**
* Assign template vars related to page content
* #see FrontController::initContent()
*/
public function initContent()
{
exit("test");
}
In /override/controllers/front/MyAccountController.php
// SAME CODE //
I also tried with this code :
class MyAccountControllerCore extends FrontController
{
/**
* Assign template vars related to page content
* #see FrontController::initContent()
*/
public function initContent()
{
exit("test");
}
What is the correct wayto do it, please ?

All this methods should work,
Did you check the option Disable all overrides in Advanced Parameters > Performance
It should be to No.
You can also delete the file app/cache/prod/class_index.php to force PrestaShop to scan the override folder.

To override MyAccountController controller you need to extend MyAccountControllerCore class and in initContent function add parent::initContent() and clear cache it may work.

Related

How do you register custom methods like those within Application.php in Laravel

I am wondering how to register custom method within:
Illuminate/Foundation/Application.php
Like:
/**
* Get the current application name.
*
* #return string
*/
public function getName()
{
return $this['config']->get('app.name');
}
Taken from:
/**
* Get the current application locale.
*
* #return string
*/
public function getLocale()
{
return $this['config']->get('app.locale');
}
Where should I put this, instead of vendor file ofc?
Thanks
You maybe able to extend the Illuminate/Foundation/Application.php
example:
<?php
namespace app\Custom;
class Application extends \Illuminate\Foundation\Application
{
}
for more details, please refer this click here .
Note: Adding your code under vendor files, may lost during the composer update command. So its not advisable to actually add your custom codes there.

Pass data in an included view with Laravel 5.6

Using Laravel 5.6, I'm trying to get the number of received links a logged-in user may have in my application.
public function getReceivedLinksCount() {
return $count = App\Link::where([
['recipient_id', Auth::id()],
['sender_id', '!=', Auth::id()]
])->count();
}
So far, so good. Question is not about that piece of code, but where I can use it. I'd like to display this counter on the navigation bar of the website (Facebook's style) which is in my header.blade.php which is included in every page.
I'd like to do it with a clean code, of course. It seems like I need to use View Composers but I'm not sure it's the right way to do it, and not sure on how the code is supposed to look.
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
view()->composer('layouts.header', function ($view) {
$view->with('variable_name', \App\Path-To-Your-Model::something());
});
}
You can share a value across all views by using View::share(), see docs
For example
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
$linksCount = Link::getReceivedLinksCount();
View::share('linksCount', $linksCount);
}
...
}
This works well if you want to set the value everywhere. Personally, I would set the value in the constructor of a 'BaseController' that gets extended by other controllers. This makes the code more discoverable because most people would expect view values to be set in a controller. And it's also a bit more flexible if you plan on having a section of your app that doesn't require that value to be computed.

How to set different layouts for different modules in Zend Framework 3

How can I set different layouts for different modules in Zend Framework 3 instead of using single one same layout template all around the site?


Zend Framework - Issue

> You may want to alter the layout based on the current
module. This requires (a) detecting if the controller matched in
routing belongs to this module, and then (b) changing the template of
the View Model.


The place to do these actions is in a listener. It should listen
either to the “route” event at low (negative) priority, or on the
“dispatch” event, at any priority. Typically, you will register this
during the bootstrap event.
namespace Content;
class Module
{
/**
* #param \Zend\Mvc\MvcEvent $e The MvcEvent instance
* #return void
*/
public function onBootstrap($e)
{
// Register a dispatch event
$app = $e->getParam('application');
$app->getEventManager()->attach('dispatch', array($this, 'setLayout'));
}
/**
* #param \Zend\Mvc\MvcEvent $e The MvcEvent instance
* #return void
*/
public function setLayout($e)
{
$matches = $e->getRouteMatch();
$controller = $matches->getParam('controller');
if (false === strpos($controller, __NAMESPACE__)) {
// not a controller from this module
return;
}
// Set the layout template
$viewModel = $e->getViewModel();
$viewModel->setTemplate('content/layout');
}
}
The manual says above, but if you want to use these code, you'll need:

// module/Content/config/module.config.php
return [
/* whatever else */
'view_manager' => [
'template_map' => [
'content/layout' => __DIR__ . '/../view/layout/layout.phtml'
]
]
];


Shortly, when all modules initialized(bootstrap) successfully, Zend will call onBootstrap() automatically, which bind 'dispatch' event to setLayout() method, where the controller name is matched with current module's namespace, and if success, use setTemplate() to set layout template.




e.g.

Module/Namespace: Content,


Controller: Content\Controller\MatchMeController,(success!)
Controller: Other\Controller\DontMatchMeController,(fail!)


But there is a tiny drawback: setLayout() use

strpos(controller, __NAMESPACE__) === false

to identify current module, but what if I had a ContentController in some other module? So use

strpos(controller, __NAMESPACE__) !== 0


instead.



----------


Zend Framework - Issue


The manual is quite detailed, it also mentions lots of other things like set different layouts for different controllers (or actions).


You can switch between layouts for a particular controller's action by using the following code:
// A controller's action method that uses an alternative
// layout template.
public function indexAction()
{
//...
// Use the Layout plugin to access the ViewModel
// object associated with layout template.
$this->layout()->setTemplate('layout/layout2');
//...
}
In addition to the Layout controller plugin, there is the Layout view
helper which provides the same capabilities. With the Layout view
helper, you can, for example, switch layout from the "static" page
which has no specific controller action.
Setting Layout for All Actions of a Controller
If all action methods of a controller class need to use the same alternative layout, you can override the onDispatch() method of the AbstractActionController class and call the setTemplate() method there, as shown in the example below:
// Add this alias in the beginning of the controller file
use Zend\Mvc\MvcEvent;
// ...
class IndexController extends AbstractActionController
{
/**
* We override the parent class' onDispatch() method to
* set an alternative layout for all actions in this controller.
*/
public function onDispatch(MvcEvent $e)
{
// Call the base class' onDispatch() first and grab the response
$response = parent::onDispatch($e);
// Set alternative layout
$this->layout()->setTemplate('layout/layout2');
// Return the response
return $response;
}
}
Reference

Codeigniter: how can i tell if a model is already loaded?

Are there native codeigniter functions I can use to tell if a certain model has already been loaded? Can php's class_exists() be used to tell if a model has already been loaded?
I would be tempted to extend the CI_Loader core class. (See extending Core Class)
class MY_Loader extends CI_Loader {
function __construct()
{
parent::__construct();
}
/**
* Returns true if the model with the given name is loaded; false otherwise.
*
* #param string name for the model
* #return bool
*/
public function is_model_loaded($name)
{
return in_array($name, $this->_ci_models, TRUE);
}
}
You would be checking for a given model with the following:
$this->load->is_model_loaded('foobar');
That strategy is already being used by the CI_Loader class.
This solution supports the model naming feature of CI, where models can have a different name than the model class itself. The class_exists solution wouldn't support that feature, but should work fine if you aren't renaming models.
Note: If you changed your subclass_prefix configuration, it might not be MY_ anymore.
The simplest solution is to use PHP function class_exists
http://php.net/manual/en/function.class-exists.php
For example. if you want to check if Post_model has been defined or not.
$this->load->model('post_model');
/*
a lot of code
*/
if ( class_exists("Post_model") ) {
// yes
}
else {
// no
}
The simplest is the best..
Edited:
You can use the log_message() function.
Put this in your model’s constructor (parent::Model())
log_message ("debug", "model is loaded");
don’t forget to set the log config to debug mode in the config.php file
$config['log_threshold'] = 2;
And set the system/logs directory permission to writable (by default CI will create the log files here)
or set the logs directory in another dir
$config['log_path'] = 'another/directory/logs/';
CI will then create the log file in the directory. monitor the log files as you like. You can get the debug message to see if your model is already loaded or not in the log files.
Riffing off what Maxime Morin & Tomexsans have written, this is my solution:
<?php
class MY_Loader extends CI_Loader {
/**
* Model Loader
*
* Overwrites the default behaviour
*
* #param string the name of the class
* #param string name for the model
* #param bool database connection
* #return void
*/
function model ($model, $name = '', $db_conn = FALSE) {
if (is_array($model) || !class_exists($model)) {
parent::model($model, $name, $db_conn);
}
}
}
?>
This way, you don't ever need to (consciously) check whether a model's loaded or not :)

Extending or Overriding CakePHP plugins without modifying original

I am using a plugin (in this case Authake) and I would like to override/extend some of the functionality, but I'm not sure how I would go about doing this. I've managed to figure out how to customize the view (I created a folder '/app/views/plugins/authake' but I'm wondering how to modify/override/extend the Models and Compoenents of the plugin.
I'm guessing you want to extend the functionality of a model or perhaps a behavior in the plugin?
For example, we could extended the functionality of a Sequence behavior that is part of a Sequence plugin like so:
Create a new file in app/models/behaviors and call it extended_sequence.php
In this file, we'll create an ExtendedSequenceBehavior class that extends SequenceBehavior and overrides the beforeFind method. It will end up looking something like:
<?php
/**
* Import the SequenceBehavior from the Sequence Plugin
*/
App::import('Behavior', 'Sequence.Sequence');
/**
* Extended Sequence Behavior
*/
class ExtendedSequenceBehavior extends SequenceBehavior
{
/**
* Overrides the beforeFind function
*/
public function beforeFind(&$model, $queryData)
{
/**
* Do something different here such as modify the query data
*/
/**
* You could still call the original function as well
*/
parent::beforeFind(&$model, $queryData);
}
}
?>
Note, that we have to import the Sequence behavior using Cake's App::import before we define the ExtendedBehavior class.
Update your model to use the extended class:
var $actsAs = array('ExtendedSequence');

Categories