I want to write a function for catalog->controller->checkout->cart.php in Opencart 2.3.0.2
I have already written a logic to check priduct_id and action to be taken if particular product id is found.
Now I want to take this logic in separate function in separate php file so that it will become more manageable.
I created function in php file under system->helper and loaded it from startup.php.
Then I can call this function from cart.php but reference to variable $this is lost even if I am passing $this to this function.
My stripped down code looks like this
cart.php
//some code before this
if (!$json) {
// Check if Product is Addon
test($this);
//more code after this
customfunction.php
function test($this) {
// print_r("Test Called");
$temp = $this->request->post['product_id'];
if ($this->request->post['product_id'] == 142) {
$json['success'] = sprintf($this->language->get('text_success'), $this->url->link('product/product', 'product_id=' . $this->request->post['product_id']), $product_info['name'], $this->url->link('checkout/cart'));
$product_options = $this->model_catalog_product->getProductOptions($this->request->post['product_id']);
$product_option_id = $product_option['product_option_id'];
//more code
I am getting error for
$this->request->post['product_id'];
Can someone tell me how to call custom function from separate php file preserving reference to $this variable.
$this is reserved word in php:
The pseudo-variable $this is available when a method is called from
within an object context.
Try that instead:
function test($ctrl) {
$temp = $ctrl->request->post['product_id'];
if ($ctrl->request->post['product_id'] == 142) {
...
Related
I apologise if this question is a bit long winded, but it's quite a large chunk of code and I cannot get it to work for the life of me...
I am building a form inside a Wordpress plugin that should gather some data (either through form inputs, API, or a combination of both - such as calling different API endpoints depending on form values). I want to then use these variables (or properties, as they seem to be referred to within classes) in different methods.
Firstly, I have my class and then a method to register my plugin on the Wordpress menu bar:
class EnigmaDMU {
private $enigma_dmu_screen_name;
private static $instance;
static function GetInstance()
{
if (!isset(self::$instance))
{
self::$instance = new self();
}
return self::$instance;
}
// This loads the WP menu page and plugin page
public function PluginMenu() {
$this->enigma_dmu_screen_name = add_menu_page(
'Enigma DMU Post',
'Enigma DMU Post',
'manage_options',
__FILE__,
array($this, 'RenderPage'),
plugins_url('enigma-daily-update/assets/enigma-cube-white.svg',__DIR__)
);
}
I then have another method called 'RenderPage' which contains my form and the HTML elements for my plugin page inside the WP admin:
public function RenderPage(){
?>
<div class='wrap'>
<div class="header-bar">
<h1>Daily Market Update</h1>
....... continued here
At the very bottom of my code, I have a method to initiate the plugin which adds the AJAX handlers (my methods) for certain AJAX actions which are called in my AJAX requests:
public function InitPlugin() {
add_action('admin_menu', array($this, 'PluginMenu'));
add_action('admin_enqueue_scripts', array($this, 'dmu_load_scripts'));
add_action('admin_enqueue_styles', array($this, 'dmu_load_scripts'));
add_action('wp_ajax_btc_data', array($this, 'getBTCData'));
add_action('wp_ajax_test_func', array($this, 'testFunc'));
}
} //this is the closing tag for the Class.
Underneath this, I have some class-related definitions, which admittedly I am unsure what they do - this was part of a larger tutorial I followed to set up this plugin:
$EnigmaDMUpost = EnigmaDMU::GetInstance();
$EnigmaDMUpost->InitPlugin();
?>
Almost there... I also have my handlers (I have included a test handler to simplify this explanation):
public function getBTCData() {
require __DIR__."/vendor/autoload.php";
$client = new GuzzleHttp\Client();
$btc_curl = $client->get('https://api.alternative.me/v1/ticker/bitcoin/',);
$btc_curl_body = $btc_curl->getBody();
$btc_curl_body_json = json_decode($btc_curl_body);
foreach($btc_curl_body_json as $result){
$btc_price_ur = $result->price_usd;
$btc_change_ur = $result->percent_change_24h;
}
$btc_price = round($btc_price_ur, 2);
$btc_change = round($btc_change_ur, 2);
$this->row3b = $btc_change . '%';
echo 'inside: ' . $this->row3b;
die();
}
I am able to echo this value here (row3b) inside my plugin successfully - this works as expected.
However, when I try and call the property from my testFunc, I get nothing:
public function testFunc() {
$test_item = $this->row3b;
echo 'btc dominance = ' . $test_item . '%.';
}
Finally, the relevant areas of my AJAX script are as follows:
jQuery(document).ready(function($) {
$('#dmu_submit').click(function() {
$('#dmu-loader').show();
$('#dmu_submit').attr('disabled', true);
btc_data = {
action: 'btc_data',
dmu_nonce: dmu_vars.dmu_nonce
};
$.post(ajaxurl, btc_data, function(response) {
$('#dmu-results').html(response);
$('#dmu-loader').hide();
$('#dmu_submit').attr('disabled', false);
});
$('#dmu_test_func').click(function() {
$('#dmu-loader').show();
$('#dmu_submit').attr('disabled', true);
test_data = {
action: 'test_func',
dmu_nonce: dmu_vars.dmu_nonce
};
$.post(ajaxurl, test_data, function(response) {
$('#dmu-results-test').html(response);
$('#dmu-loader').hide();
$('#dmu_submit').attr('disabled', false);
});
return false;
});
Any help would be massively appreciated - I know it's a long post, but I feel as if the answer is actually really simple, I just cannot figure it out. It feels as if I'm doing everything right. Thank you!!
It's not completely clear from your code examples which class your testfunc() is in. But $this in php refers to the instance of the class that it resides within, and the ->row3b refers to a property called row3b (a property is a variable that belongs to the class which is usually defined at the top of the class code). If you're calling $this->row3b within the class itself it will work, but if you need to refer to it from outside the class you will need to instantiate a new instance of the class, and then refer to it with the variable name you assign. E.g.
$myInstance = new theclassname(); $myInstance->row3b;
If the row3b is a static property its slightly different again, you can refer to this outside of the class as theclassname::$row3b
Edit: also ensure that the testfunc resides in the same class that the add_actions are in. The $this in the add_action tells wordpress that it should look for your handler in 'this' class.
Edit2: I think you may also need the die() at the end of your testfunc. Wordpress ajax is funny about this.
I have a custom content type called "program" that I am trying to load via a drupal module.
The .module file includes a class called Program that has a method called
getAllPrograms() using include_once(drupal_get_path('module', 'progs') . '/progs.php');
When i try and load nodes using either node_load() or node_load_multiple() i get one of two different errors randomly.
either:
Fatal error: Fatal error: Call to undefined function user_access() in /mypath/modules/filter/filter.module on line 1035
or
Error: Call to undefined function token_get_entity_mapping() in /mypath//sites/all/modules/contrib/token/token.tokens.inc, line 767
Note: 99% of times it is the first error, and occasionally i would recieve the token_get_entity error.
The strange thing is, while i have been trying different things to resolve the error I have been able to get both of these functions to work for a period but as soon as i clear the Drupal Cache i get the error again.
What I have tried
Disabling and enabling the user module via the database.
Checking the paths and status are correct for the main modules (system, user, block etc)
using db_select to get a list of node ids and then use node_load() (with a loop) and node_load_multiple() to load the nodes. This is one of the things that started working for a short time until i cleared the cache.
Tested to see if i can call user_access() from my .module file. This does not work and returns the same call to undefined function error.
Here is the code that I have (not progs an anonymized name)
progs.module
include_once(drupal_get_path('module', 'progs') . '/progs.php');
progs.php
if( !class_exists('progs') ):
class progs
{
//a bunch of properties
function __construct()
{
// load partial includes and objects
$this->load_partial_inclues();
//retrieve all programs that are open
$this->open_programs = Program::getAllOpenPrograms();
}
function load_partial_inclues()
{
//includes
include_once(drupal_get_path('module', 'progs') . '/core/objects/program.php');
}
}
function progs()
{
global $progs;
if( !isset($progs) )
{
$progs = new progs();
}
return $progs;
}
// initialize
progs();
endif;
Note: I load the $progs into the global space so i can call it elsewhere in my module.
program.php
if( !class_exists('Program') ):
class Program
{
//a bunch of properties
public static function getAllOpenPrograms()
{
// This is the line that causes all of the issues.
$result = node_load_multiple('',array('type' => 'program'));
dpm($result);
}
Thanks in advance!
Like Mike Vranckx mentioned, if you call progs() directly when you include it in progs.module, Drupal basically hasn't bootstrapped, i.e. hasn't started running fully yet. Suggest you put your progs() in progs_init() or similar so that Drupal will invoke it at the right time.
Here's a proposed way that follows your initial structure quite closely, and below you will see an alternative that better follows Drupal's conventions.
New progs.module
/**
* Implements hook_init().
*/
function progs_init(){
progs();
}
And modify your progs.php
// Why are you doing this check? Are you defining this class elsewhere in your project? If not you can safely ignore this
//if( !class_exists('progs') ):
// Convention is to name classes with Pascal case btw.
class progs
{
//a bunch of properties
function __construct()
{
// load partial includes and objects
$this->load_partial_inclues();
//retrieve all programs that are open
$this->open_programs = Program::getAllOpenPrograms();
}
function load_partial_inclues()
{
//includes
include_once(drupal_get_path('module', 'progs') . '/core/objects/program.php');
}
}
function progs()
{
global $progs;
if( !isset($progs) )
{
$progs = new progs();
}
return $progs;
}
A more Drupal way:
progs.module
/**
* Implements hook_init().
*/
function progs_init(){
global $progs;
// Consider using drupal_static to cache this
if( !isset($progs) )
{
module_load_include('inc', 'progs', 'progs');
$progs = new Progs();
}
}
progs.inc (convention is to use .inc)
class Progs
{
//a bunch of properties
function __construct()
{
// load partial includes and objects
$this->load_partial_inclues();
//retrieve all programs that are open
$this->open_programs = Program::getAllOpenPrograms();
}
function load_partial_inclues()
{
//includes
module_load_include('php', 'progs', 'core/objects/program');
}
}
Ok, so I just finished off a function for validating the firstname field on a form.
This function works correctly on its own.
But since I want to make this function re-usable for more than one website, I added an if statement for whether or not to use it. The following code explain this:
Related PHP code:
//Specify what form elements need validating:
$validateFirstname = true;
//array to store error messages
$mistakes = array();
if ($validateFirstname=true) {
//Call first name validation function
$firstname = '';
if (!empty($_POST['firstname'])) {
$firstname = mysql_real_escape_string(stripslashes(trim($_POST['firstname'])));
}
$firstname = validFirstname($firstname);
if ($firstname === '') {
$mistakes[] = 'Your first name is either empty or Enter only ALPHABET characters.';
}
function validFirstname($firstname) {
if (!ctype_alpha(str_replace(' ', '', $firstname))) {
return '';
} else {
return $firstname;
}
}
}
So without this if ($validateFirstname=true) the code runs fine, but the moment I add it; I get the following error message:
Fatal error: Call to undefined function validFirstname()
Are you not able to use functions in if statements at all in PHP? I'm fairly new to using them in this way.
Conditional functions (functions defined inside the conditions) must be defined before they are referred. Here's what manual says:
Functions need not be defined before they are referenced, except when
a function is conditionally defined as shown in the two examples
below.
When a function is defined in a conditional manner such as the two
examples shown. Its definition must be processed prior to being
called.
So if you want to use it that way, you should put it either at the beginning of the if condition or outside the condition.
// Either:
if ($validateFirstname==true) {
function validFirstname($firstname) {}
}
// Or, and I'd rather do it this way, because function is
// created during "compilation" phase
function validFirstname($firstname) {}
if ($validateFirstname==true) {
// ...
}
Also not that function (even if created inside the condition) is pushed to global scope:
All functions and classes in PHP have the global scope - they can be called outside a function even if they were defined inside and vice versa.
So once code is evaluated it doesn't matter if it's declared inside condition or intentionally in global scope.
Functions that are declared in a conditional context (like if body), you can only use after their declaration.
if ($validateFirstname == true) {
//Call first name validation function
function validFirstname($firstname) {
// function body
}
// $firstname initialisation
$firstname = validFirstname($firstname);
// ...
}
(P.s.: changed $validateFirstname = true to $validateFirstname == true which should be what you want)
if($validateFirstname=true)
you are assigning the value "true" to $validateFirstname here
you should use a "==" for comparison e.g
if($validateFirstname==true)
that might help your "if" problem
I've created a plugins system, and I've created everything in that system except, how can I inclusion plugins files to execute it.
I'm tried to create a method, Which is doing include plugins files to execute it.
-- Firstly -- :
The method that get all plugins files, and that begin with index word which indicates the main file of plugin (i.g. index-pluginName.php), and add the path and file name to an array.
public function getPluginFiles($plugin_folder) {
$dir = opendir($plugin_folder);
while ($files = readdir($dir)) {
if ($files == '.' || $files == '..')
continue;
if (is_dir($plugin_folder.'/'.$files))
$this->getPluginFiles($plugin_folder.'/'.$files);
if (preg_match('/^[index]+/i', $files)) {
$this->plugins_path[$plugin_folder.'/'.$files] = $files;
}
}
closedir($dir);
}
-- secondly -- :
The method that include all the main file of plugins to execute, and this method get the path and name of plugin file from the array that created earlier .
public function includePlugFiles() {
$this->getPluginFiles($this->plugin_folder);
foreach ($this->plugins_path as $dir=>$file) {
include_once (dirname($dir)."/".$file);
}
}
Also see an example of code that exists in plugin file:
function test() {
echo " This is first plugin <br/>";
}
$plugin->addHook('top', test); // parameters(top=position, test=callback)
Now, when I create an instance of the object to be this form .
$plugin = new plugin;
$plugin->includePlugFiles();
But after all this, shows error message
Fatal error: Call to a member function addHook() on a non-object in .... projects\plugins\index-test.php on line 7
This is the code of line 7:
$plugin->addHook('top', test); // parameters(top=position, test=callback)
I know the problem occur because, the object will not be created.
and the problem is can't create the object in every main plugin file.
It's probably not the cleanest solution, but instead of trying to reference the $plugin symbol (which is outside the scope of the plugin file), you could also do this:
$this->addHook('top', test);
Alternatively, you could explicitly create the reference inside the includePlugFiles() method:
public function includePlugFiles()
{
$plugin = $this;
$this->getPluginFiles($this->plugin_folder);
foreach ($this->plugins_path as $dir=>$file) {
include_once (dirname($dir)."/".$file);
}
}
So I have two files, 'header.php' and 'pluginfile.php'
The function that I want to call resides in 'pluginfile.php' and is:
public function getNonSubscriptionAmount() {
$total = 0;
foreach($this->_items as $item) {
if(!$item->isSubscription()) {
$total += $item->getProductPrice() * $item->getQuantity();
}
else {
// item is subscription
$basePrice = $item->getBaseProductPrice();
Cart66Common::log('[' . basename(__FILE__) . ' - line ' . __LINE__ . "] Item is a subscription with base price $basePrice");
$total += $basePrice;
}
}
return $total;
}
So in 'header.php' I have:
<?php
include_once($_SERVER['DOCUMENT_ROOT']."/wp-content/plugins/plugin-name/folder/PluginFile.php");
print getNonSubscriptionAmount();
?>
This gives the following error when any page is loaded:
Fatal error: Call to undefined function getnonsubscriptionamount() in
/home/username/domain.com/wp-content/themes/theme/header.php on
line 72
I've spent a couple of hours now trying to figure this out alone and am getting nowhere! Any help much appreciated!
#Wiseguy looks like he had the right idea put in the comments.
You are declaring a method and not a function. Is the function the entirety of your plugin.php file or is there more? If it is everything, remove the public modifier and just declare
function getNonSubscriptionAmount() {
// code here
}
But from the looks of the code it is part of a larger class. If thats the case then #Wiseguy comment is right on, you need to instantiate a new object of the class in plugin.php and then the desired method.
$obj = new PluginClass();
$obj->getNonSubscriptionAmount();
You said:
The function that I want to call resides in 'plugin.php' and is:
And in your file you are including:
So in 'header.php' I have:
include_once($_SERVER['DOCUMENT_ROOT']."/wp-content/plugins/plugin-name/folder/PluginFile.php");
print getNonSubscriptionAmount();
You are not including 'plugin.php' which is were the function lives.
Header.php should include 'plugin.php', not 'PluginFile.php'.