In PrestaShop (specifically v1.7.5) one can get an instance of the module class by calling
$module = Module::getInstanceByName('theModuleName');
in the controller of a custom module.
Is 'theModuleName' available via some other setting or variable or does it need to be hardcoded?
It should also be used as first parameter to getModuleLink().
You can access the module name (along with the rest from the module class) by:
$theModuleName = $this->module->name;
Using Prestashop core module "Cronjobs" as an example, you can also run module methods inside a front controller like this:
class CronjobsCallbackModuleFrontController extends ModuleFrontController
{
public function postProcess()
{
$this->module->sendCallback();
die;
}
}
If you are working in a child from ProductListingFrontController, this->module is not defined.
If you call the module with getInstanceByName, you get an instance in order to work with it later. The string way doesn´t work in Listing controllers.
class mymoduleMyControllerModuleFrontController extends ProductListingFrontControllerCore
{
public function init()
{
parent::init();
$this -> module = Module::getInstanceByName('mymodule');
}
}
Related
I have followed many tutorials, but they are either cryptic or they did not work, or they wanted you to use the terrible CMS block module which gives you limited control over the custom elements of a page.
So far:
I created a controller called ProgramsController.php and put it into ps_root/controllers/front
class ProgramsControllerCore extends FrontController
{
public $php_self = 'programs';
public function init()
{
parent::init();
}
public function initContent()
{
parent::initContent();
$this->setTemplate(_PS_THEME_DIR_.'programs.tpl');
}
}
I created a template called programs.tpl and put it into ps_root/themes/mytheme/ folder
I then use: localhost/index.php?controller=programs or I use the SEO and links builder to create a localhost/programs link, and I get an error: Fatal error: Class 'ProgramsController' not found in ...\classes\controller\Controller.php on line 135
But that's not right since the path ought to be a ../controllers/front path, why is it looking in ../classes/controller? I assume from all the tutorials that the dispatcher should know to hook my front controller to the correct template. Why is this not working?
Basic Question:
In PrestaShop 1.6 I just want to know how to create custom pages like: http://myshop.com/mycustompage
But that it also utilizes the existing header and footer.
For creating a new custom page you have to follow some steps:
you have to create a new folder in your modules folder of prestashop like
C:\wamp\www\prestashop\modules\your_module_name
Then you put your controller file in your module folder like:
C:\wamp\www\prestashop\modules\your_module_name\controller\front\your_file.php
And in that you code like:
class ProgramsControllerCore extends FrontController
{
public $php_self = 'programs';
public function init()
{
parent::init();
}
public function initContent()
{
parent::initContent();
$this->setTemplate(_PS_THEME_DIR_.'programs.tpl');
}
}
Then you make a new folder views in your module like:
C:\wamp\www\prestashop\modules\your_module_name\views
Then in that you make another folder named template and in that another a folder named front like:
C:\wamp\www\prestashop\modules\your_module_name\views\templates
C:\wamp\www\prestashop\modules\your_module_name\views\templates\front
Then in that file you have to put your theme file Like
C:\wamp\www\prestashop\modules\your_module_name\views\templates\front\programs.tpl
and now render your file. I hope it would work.
Can someone explain this code in Silverstripe:
public function init() {
RSSFeed::linkToFeed($this->Link() . "rss");
parent::init();
}
What exactly is init function?
what parent::init();
exactly do in code
in php classes when you overwrite a method of parent class you still can call the parent class with this code, it will help you to put some code at the beginning of the real method without removing it.
you can find out more about it at php documentation
The upmost init() method is defined in the Controller class.
Then ContentController extends Controller, which overrides the Controller class's init() method, but it's also calling parent::init() on the first line. Then usually you define all your page controller classes like this (for any new page type), in the example below for the default Page_Controller class:
class Page_Controller extends ContentController {
public function init() {
parent::init();
// do your own stuff here
}
}
So this is the traditional PHP based class extension mechanism, but Silverstripe also allows you to use Extensions and Data Extensions, which is basically extending the functionality of already existing controllers, data objects. I won't go into details with this... You can find out more about this here: https://docs.silverstripe.org/en/4/developer_guides/extending/extensions/
I usually have something like this in my controller classes:
class Page_Controller extends ContentController {
public function init() {
parent::init();
// do your own stuff here
$this->extend('updateInit');
}
}
Notice the $this->extend('updateInit'); line above.
I can have another extension defined for the Page_Controller class inside a YAML config file somewhere, and than have the updateInit() method defined in that class. Example:
class Page_Controller_Extension extends Extension {
public function updateInit() {
// do some more stuff here
}
}
...and in this case you would have something like this in a YAML config file:
---
Name: siteextensions
After:
- 'framework/*'
- 'cms/*'
---
Page_Controller:
extensions:
- Page_Controller_Extension
Note that this is not really the traditional way of extending classes, like in PHP, it's more like defining some decorators for a controller class. Also, to refer to the parent, or object being decorated, you can't use just $this, you'll need to use $this->owner. Example below:
class Page_Controller_Extension extends Extension {
public function updateInit() {
// do some more stuff here
if ($this->owner->IsFeatured) {
// do something here
}
}
}
You usually decorate controllers extending the Extension class, and you extend the DataExtension class if you want to decorate DataObjects - works the same way as explained above.
I am bootstrapping my application with Zend_Application_Module_Bootstrap inside the various module directories. How can I require that a resource inside another module's bootstrap be executed first?
// app/modules/user/Bootstrap.php
class User_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initUser()
{
}
}
// app/modules/author/Bootstrap.php
class Author_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initAuthor()
{
$this->bootstrap('user'); // Fatal: Resource matching 'user' not found
}
}
I've decided to use plugins to achieve this fine-grained functionality, as execution order cannot be managed properly, therefore making module bootstraps a poor choice to place code with dependencies.
Used referenced answer below to base my decision:
load /execute module based bootstraps from each module in certain order
According to this thread from the ZF1 mailing list, you can access the module-bootstraps via the modules resource of the application bootstrap.
Man, what a mouthful. Here's what I mean:
// app/modules/user/Bootstrap.php
class User_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initUser()
{
}
}
// app/modules/author/Bootstrap.php
class Author_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initAuthor()
{
$app = $this->getApplication(); // it's actually the application *bootstrap*
$app->bootstrap('modules');
$modulesResource = $app->getResource('modules');
$userBootstrap = $modulesResource->user;
$userBootstrap->bootstrap('user'); // should be cool
}
}
In my own experience, as soon as one of my module-level resources needs to be referenced in more than one module - especially during bootstrapping - I just push the bootstrapping of that resource up into the application-level bootstrap.
Should I not be using Index as the name for a controller class in CodeIgniter? I have an Index controller, and I'm seeing its methods being called multiple times. More specifically, I always see its index method called first, whether or not I'm visiting a path that should be routed there.
In application/controllers/index.php
class Index extends CI_Controller
{
public function index()
{
echo "index";
}
public function blah()
{
echo "blah";
}
}
When I visit index/blah, I see indexblah printed. When I visit index/index, I see indexindex. If I rename the controller to something else (e.g. Foo), it doesn't have a problem. That's the obvious workaround, but can anyone tell me why this is happening? Should I report this as a bug to CodeIgniter?
(Notes: I have no routes set up in configs/routes.php; my index.php is outside the CodeIgniter tree)
To further clarify what the issue is, in PHP4 Constructors were a function that had the same name as the Class...
example
class MyClass
{
public function MyClass()
{
// as a constructor, this function is called every
// time a new "MyClass" object is created
}
}
Now for the PHP5 version (Which codeigniter now, as of 2.0.x, holds as a system requirement)
class MyClass
{
public function __construct()
{
// as a constructor, this function is called every
// time a new "MyClass" object is created
}
}
So To answer the question that addresses the problem...
Should I not be using Index as the name for a controller class in CodeIgniter?
I believe it would be best to not choose Index as a controller name as the index() function has a reserved use in codeigniter. This could cause issues depending on your PHP configuration.
can anyone tell me why this is happening?
When your controller get's instantiated, index as the constructor is getting called.
Compare Constructors and DestructorsDocs:
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class . [highlighting by me]
In your case your Controller does not have any __construct() function but a function that has the same name as the class: index. It is getting called in the moment Codeigniter resolves and loads and then instantiates your Index Controller.
You can solve this by just adding the constructor to your Controller:
class Index extends CI_Controller
{
public function __construct() {}
public function index()
{
echo "index";
}
public function blah()
{
echo "blah";
}
}
After this change, it does not happen again.
Should I report this as a bug to CodeIgniter?
No, there is not really a need to report this as a bug, it's how the language work and as Codeigniter supports PHP 4 it must remain backwards compatible and needs to offer PHP 4 constructors. (Note: The Codeigniter project documents, they need server support for PHP version 5.1.6 or newer, but the actual code has PHP 4 compatiblity build in, I'm referring to the codebase here, not the documentation.)
Here is another solution using Codeigniter3
require_once 'Base.php';
class Index extends Base
{
public function __construct()
{
parent::index();
$classname=$this->router->fetch_class();
$actioname=$this->router->fetch_method();
if($actioname=='index' || $actioname == '')
{
$this->viewall();
}
}
}
And the viewall() had the following
$this->siteinfo['site_title'].=' | Welcome';
$this->load->view('templates/header', $this->siteinfo);
$this->load->view('templates/menu', $this->siteinfo);
$this->load->view('index/viewall', $data);
$this->load->view('templates/footer', $this->siteinfo);
The Base controller does all the library and helper loading for the entire application which is why it is being required in the default class
Basically from my short understanding of CodeIgniter, having a default action as index is a wrong. I found this out by using the printing the result of $this->router->fetch_method(); in the construct() of my index class. The default action by CodeIgniter is index, you may only set the default controller within application/config/routes.php and not the default action.
So my advice, never use index() as the default action especially if you are using index as the default controller
I have a question for you. I'm not sure how to structure a PHP Module for CMS maybe when I create a new Page I want to select the Module which are created, for example
News Module, Gallery Module etc..
How can I structure this and implement those modules in PHP CMS ?
In your database you should hold a modules table that consists of the following:
id
module_name
module_desc
module_folder
module_active
so that you can keep modules organized, in the table where you have module_folder this should be the location of the module such as
cms_root() . "/modules/%module_folder%/main.module.php"
This is where interfaces would come in handy :)
interface IModule
{
public function __run($param);
public function __version();
public function __shutdown();
//...
}
you should also have a class called Module where the module would extend and gather rights to templates/database ect.
class Module
{
public $DB,$TPL; /*...*/
/*
Functions ehre to help the module gain access to the instance of the page.
*/
}
Also the Module class should be able to execute modules and keep track of executed modules, so in your core code you can say $Module->RunAll() and it would run them.
A module file would probably look like:
class Gallery_Module extends Module implements IModule
{
public function __version()
{
return '1.0';
}
public function __run()
{
//Assign module data to the template :)
}
public function __shutdown()
{
//Clean old records etc from DB
}
}
And within your core as said above, you can get the Module class to read active modules from the database load the files from the folder and create an instance of the class, followed by there execution.
Hope this helps.