On the backend of a PrestaShop site I'm using this function:
public function hookAjax($action, $id_product, $id_lang, $title, $descript, $order, $id = NULL)
{
/* various code*/
$this->context->smarty->assign(
array(
'block_define' => $this->getFormDesc($id_product)
)
);
return $this->context->smarty->fetch($this->local_path.'views/templates/hook/admin_extra_desc.tpl');
}
public function getFormDesc($id_product) {
$array = array();
foreach (Language::getLanguages() as $lang) {
/*various code*/
foreach($result as $k=> $r) {
$files = array();
$helper = new HelperImageUploader();
$helper->setMultiple(false)->setUseAjax(true)->setName('thumbnail_'.$r['id'].'_'.$r['id_lang'])->setFiles($files)->setMaxFiles(3)->setUrl('../modules/module-name/imgAjaxCall.php?');
$result[$k]['img-form'] = $helper->render();
$result[$k]['img'] = $result[$k]['img'] ? _PS_BASE_URL_.__PS_BASE_URI__.'modules/module-name/upload/'.$result[$k]['img'] : '';
}
$array[$lang["id_lang"]] = array(
'lang_data' => $lang,
'count' => count($result),
'data' => $result
);
}
return $array;
}
HookAjax is called by:
<?php
include(dirname(__FILE__).'/../../config/config.inc.php');
$context = Context::getContext();
$addDesc = Module::getInstanceByName('module-name');
echo $addDesc->hookAjax($_POST['action'],$_POST['id_prodotto'],$_POST['lang'],$_POST['title'], $_POST['text_desc'], NULL, $_POST['row']);
?>
But I struggle with this error:
Fatal error: Call to a member function addJs() on a non-object in {my_site}/classes/helper/HelperUploader.php on line 257
You need to include init.php in HookAjax after including config.inc.php so that controller is initialized in context.
include(dirname(__FILE__).'/../../init.php');
Note that this is just bad practice, respect the MVC and use proper controllers for your AJAX calls and data validation/processing in them, not inside main module class.
Related
Hi tried refreshing the modification cache cache in opencart and since then i am getting a blank page in front end with this error message.
public function trigger($event, array $args = array()) {
foreach ($this->data as $value) {
if (preg_match('/^' . str_replace(array('\*', '\?'), array('.*', '.'), preg_quote($value['trigger'], '/')) . '/', $event)) {
$result = $value['action']->execute($this->registry, $args);
if (!is_null($result) && !($result instanceof Exception)) {
return $result;
}
}
}
}
Thanks,
It seems your have an OC version 3.0.2.x or above.
In your $this->data of the Event Class, you have an event registered that is missing an action parameter.
$this->data[] = array(
'trigger' => $trigger,
'action' => $action, // <-- this must be an Action Object with a method execute()
'priority' => $priority
);
All events are registered via the register() method which explicitly requests that an Action object is being passed as a parameter.
Since the error is pointing to "Call to undefined method Action::execute()", I can assume, you have an issue with the action class.
Most likely you need to check the Modifications of the system/engine/action.php file in your system/storage/modifications.
It could be that the method execute() is either missing or somehow corrupt.
Debug
try to var_dump the $value to see what is there:
public function trigger($event, array $args = array()) {
foreach ($this->data as $value) {
//log out the $value before the error to see if the Action object is actually there and see what trigger causes this.
var_dump($value);
if (preg_match('/^' . str_replace(array('\*', '\?'), array('.*', '.'), preg_quote($value['trigger'], '/')) . '/', $event)) {
$result = $value['action']->execute($this->registry, $args);
if (!is_null($result) && !($result instanceof Exception)) {
return $result;
}
}
}
}
Hope this helps
Hi tried refreshing the modification cache cache in opencart and since then i am getting a blank page in front end with this error message.
public function trigger($event, array $args = array()) {
foreach ($this->data as $value) {
if (preg_match('/^' . str_replace(array('\*', '\?'), array('.*', '.'), preg_quote($value['trigger'], '/')) . '/', $event)) {
$result = $value['action']->execute($this->registry, $args);
if (!is_null($result) && !($result instanceof Exception)) {
return $result;
}
}
}
}
Thanks,
It seems your have an OC version 3.0.2.x or above.
In your $this->data of the Event Class, you have an event registered that is missing an action parameter.
$this->data[] = array(
'trigger' => $trigger,
'action' => $action, // <-- this must be an Action Object with a method execute()
'priority' => $priority
);
All events are registered via the register() method which explicitly requests that an Action object is being passed as a parameter.
Since the error is pointing to "Call to undefined method Action::execute()", I can assume, you have an issue with the action class.
Most likely you need to check the Modifications of the system/engine/action.php file in your system/storage/modifications.
It could be that the method execute() is either missing or somehow corrupt.
Debug
try to var_dump the $value to see what is there:
public function trigger($event, array $args = array()) {
foreach ($this->data as $value) {
//log out the $value before the error to see if the Action object is actually there and see what trigger causes this.
var_dump($value);
if (preg_match('/^' . str_replace(array('\*', '\?'), array('.*', '.'), preg_quote($value['trigger'], '/')) . '/', $event)) {
$result = $value['action']->execute($this->registry, $args);
if (!is_null($result) && !($result instanceof Exception)) {
return $result;
}
}
}
}
Hope this helps
I have these two methods in my Contact.php model:
public function getSubscribers($listId)
{
return $this->withTrashed()
->where(DB::raw("concat('',email * 1)"), '!=', DB::raw('email'))
->where('opt_out', '0')
->select('email')
->chunk(1000, function($results) use ($listId) { $this->subscribeEmails($listId, $results); });
}
public function subscribeEmails($listId, $subscribers)
{
$emails = array();
foreach ($subscribers as $key => $subscriber)
{
$memberActivity = $subscriber->memberActivity($listId);
if ( ! $memberActivity['data'])
{
$emails[] = array('email' => $subscriber->email);
}
else
{
foreach ($memberActivity['data'] as $data)
{
foreach ($data['activity'] as $activity)
{
if ($activity['action'] !== 'unsub')
{
$emails[] = array('email' => $subscriber->email);
}
}
}
}
}
MailchimpWrapper::lists()->batchSubscribe($listId, $emails, false, true);
}
And the getSubscribers() method is called in my AdminContactsController.php controller via a method called updateMailchimp():
public function updateMailchimp()
{
$this->contact->getSubscribers($this->listId);
$message = (object) array(
'title' => 'Excellent!',
'content' => 'The Mailchimp newsletter list has been updated with the latest contacts from within the system.',
'alert_type' => 'success'
);
return Redirect::back()->with('message', $message);
}
Locally, this works great, no problems at all but on the staging server, I get the following error referencing the line cotaining ->chunk(1000, function($results) use ($listId) { $this->subscribeEmails($listId, $results); });:
Using $this when not in object context
Is this a PHP version issue or am I missing something here?
The reason why your code works on localhost but not on the remote server is probably the difference in PHP versions. Before PHP 5.4.0 it is not possible to use $this from anonymous function. You must pass the reference to $this within the use keyword:
public function getSubscribers($listId)
{
$that = $this; // <---- create reference to $this
return $this->withTrashed()
->where(DB::raw("concat('',email * 1)"), '!=', DB::raw('email'))
->where('opt_out', '0')
->select('email')
->chunk(1000, function($results) use (&$that, $listId) { $this->subscribeEmails($listId, $results); });
}
I am not sure why but I am getting this error
Fatal error: Call to a member function update() on a non-object in /home/XXXXXXXXXXXXXXXXX/classes/core.php on line 22
On that page I have this
public function updatemongo($from,$data)
{
$this->db = $m->exchange_rates;
$collection = $this->db->exchangeDB;
$collection->update(array("from" => $from), $data);
}
this is how I am calling this function
foreach ($currencies as $to)
{
if($from != $to)
{
$url = 'http://finance.yahoo.com/d/quotes.csv?f=l1d1t1&s='.$from.$to.'=X';
$handle = fopen($url, 'r');
if ($handle) {
$result = fgetcsv($handle);
fclose($handle);
}
$newdata = array('$set' => array("exchangehistory.{$result[1]}.{$result[2]}" => array("to" => $to, "rate" => $result[0], "updated" => $result[2])));
$fetch->updatemongo($from,$newdata);
$newdata = array('$set' => array("currentexchange" => array("to" => $to, "rate" => $result[0], "updated" => $result[2])));
$fetch->updatemongo($from,$newdata);
}
}
and yes the file needing to access this is also has require_once("core.php");
Please let me know why this is not working.
The updatemongo() function doesn't have access to the $m variable. Please pass it to the function like this:
$fetch->updatemongo($m, $from, $newdata);
And change your function definition to:
public function updatemongo($m, $from, $data)
{
Alternatively, you can set the m property of the object to the connection after you've created it. For example with:
public function __construct)
{
$this->m = new Mongo();
}
...
public function updatemongo($from, $data)
{
$this->db = $this->m->exchange_rates;
$collection = $this->db->exchangeDB;
$collection->update(array("from" => $from), $data);
}
Or perhaps you can just use $this->exchange_rates already above... in any case, you're not making $m available to the function.
Looks like a typo : the object "$m" is not instantiated in function updatemongo()
Either create it here or gain access with global $m; if it exists.
$this->db->exchangeDB contains null or similar when it gets placed into $collection? It's hard to tell for us since we don't know where that variable gets instantiated.
$collection->update(array("from" => $from), $data);
is the cause of your error and the error is clear: $update is not an object. otherwise it would complain "PHP Fatal error: Call to undefined method YourClass::yourMethod() in /my/php/file.php on line xx"
I would like to create the following using class syntax:
$resp = new stdclass;
$resp->CategoryListResp->category[0]->categoryId = 1;
$resp->CategoryListResp->category[0]->categoryName = "Spel";
$resp->CategoryListResp->category[0]->iconUri = "PictoSpel.png";
$resp->CategoryListResp->category[1]->categoryId = 2;
$resp->CategoryListResp->category[1]->categoryName = "Transport";
$resp->CategoryListResp->category[1]->iconUri = "PictoTransport.png";
Should be easy but I cannot find the syntax for this.
I will later output $resp in json format. I am aware I can also use arrays for this...
The json output shall be:
{"CategoryListResp":{"category":[{"categoryId":1,"categoryName":"Spel","iconUri":"PictoSpel.png"},{"categoryId":2,"categoryName":"Transport","iconUri":"PictoTransport.png"}]}}
You can also make your classes more explicit:
class Category {
public $categoryId = 0, $categoryName = '', $iconUri = '';
}
class Resp {
public $categoryListResp = null;
public function __construct() {
$this->categoryListResp = new CategoryListResp();
}
}
class CategoryListResp {
public $category = array();
}
$resp = new Resp();
$resp->categoryListResp->category[0]->categoryId = 1;
$resp->categoryListResp->category[0]->categoryName = "Spel";
$resp->categoryListResp->category[0]->iconUri = "PictoSpel.png";
// etc.
ADDED (based on henq's comment). To fully utilize the class concept you would need to add some methods to the classes. Then you would not use -> for arrays, but call the respective methods. E.g.
class Category {
public $categoryId = 0, $categoryName = '', $iconUri = '';
public function __construct($id, $name, $icon) {
$this->categoryId = $id;
$this->categoryName = $name;
$this->iconUri = $icon;
}
}
class Resp {
public $categoryListResp = null;
public function __construct() {
$this->categoryListResp = new CategoryListResp();
}
public function addCategory($index, $id, $name, $icon) {
$this->categoryListResp->addCategory($index, $id, $name, $icon);
}
}
class CategoryListResp {
public $category = array();
public function addCategory($index, $id, $name, $icon) {
$this->category[$index] = new Category($id, $name, $icon);
}
}
$resp = new Resp();
$resp->addCategory(0, 1, "Spel", "PictoSpel.png");
$resp->addCategory(1, 2, "Transport", "PictoTransport.png");
// etc
You can modify this concept according to your needs.
You're almost there already:
$resp = new stdClass();
$resp->CategoryListResp = new stdClass();
$resp->CategoryListResp->category[0]->categoryId = 1;
$resp->CategoryListResp->category[0]->categoryName = "Spel";
$resp->CategoryListResp->category[0]->iconUri = "PictoSpel.png";
$resp->CategoryListResp->category[1]->categoryId = 2;
$resp->CategoryListResp->category[1]->categoryName = "Transport";
$resp->CategoryListResp->category[1]->iconUri = "PictoTransport.png";
print_r(json_encode($resp));
/*
output:
{"CategoryListResp":{"category":[{"categoryId":1,"categoryName":"Spel","iconUri":"PictoSpel.png"},{"categoryId":2,"categoryName":"Transport","iconUri":"PictoTransport.png"}]}}
*/
Just send $resp to json_encode. Your code should work as is, however. It's better design to create class definitions for CategoryListResp and Category, rather than just using stdClass.
Arrays are the simpler way to go (as suggested by #felix-kling)
This is how the code ended up:
$resp = array(
'CategoryListResp' => array(
'category' => array(
array(
'categoryId' => 1,
'categoryName' => 'Spel',
'iconUri' => 'PictoSpel.png'
),
array(
'categoryId' => 2,
'categoryName' => 'Transport',
'iconUri' => 'PictoTransport.png'
),
),
),
);
print json_encode($resp);
Clean and simple.