We use Payone with our Magento shop. And we want to show our users warnings in their cart when their total amount is too large for a certain payment method.
That is why I want to check the total amount against each payment method max order value.
But somehow I can not reach the correct data.
When I try to get them by Payones config:
$methods = Mage::helper('payone_core/config')->getConfigPayment($store);
I get an object->array with all methods, but they are protected. So I can not use them in my cart module.
What is a clean way to get Payones payment methods (all active methods with their max_order_value)?
Edit:
I tried following code, but it still says:
Fatal error: Cannot access protected property
Payone_Core_Model_Config_Payment::$methods in
/pathToClass/CtaB2c/Helper/Data.php on line 20
class CtaB2c_Helper_Data extends Payone_Core_Helper_Config {
public function getConfigPayment($store) {
return parent::getConfigPayment($store);
}
public function showPaymentRestrictions() {
$quote = Mage::getSingleton('checkout/session')->getQuote();
$store = $quote->getStoreId();
$total = $quote->getBaseGrandTotal();
$methods = $this->getConfigPayment($store);
$methods = $methods->methods; //error occurs here: member has protected access
$avaibleMethods = array();
foreach ($methods AS $mid => $method) {
$minTotal = $method->minOrderTotal;
$maxTotal = $method->maxOrderTotal;
if($minTotal <= $total && $maxTotal >= $total) {
$avaibleMethods[$mid] = $method->code;
}
}
return $avaibleMethods;
}
}
I know, there is no check if this payment method is avaible, but actually I just want know if maxOrderTotal is bigger than payment methods max_order_total. And of course I do not need this extra function. I could call parent::getConfigPayment($store) in my function as well.
Edit 2
This is the object I get from getConfigPayment():
object(Payone_Core_Model_Config_Payment)#<a number> (1) {
["methods":protected]=>
array(6) {
[<a number>]=>
object(Payone_Core_Model_Config_Payment_Method)#<a number> (38) {
["id":protected]=>
string(1) "a number"
["scope":protected]=>
string(6) "stores"
["scope_id":protected]=>
string(1) "<a number>"
["code":protected]=>
string(15) "advance_payment"
["name":protected]=>
string(8) "Vorkasse"
["sort_order":protected]=>
string(1) "<a number>"
["enabled":protected]=>
string(1) "<a number>"
["fee_config":protected]=>
NULL
["mode":protected]=>
string(4) "test"
["use_global":protected]=>
string(1) "1"
["mid":protected]=>
string(5) "<a number>"
["portalid":protected]=>
string(7) "<a number>"
["aid":protected]=>
string(5) "<a number>"
["key":protected]=>
string(16) "<a key>"
["allowspecific":protected]=>
string(1) "0"
["specificcountry":protected]=>
array(0) {
}
["allowedCountries":protected]=>
array(2) {
[0]=>
string(2) "DE"
[1]=>
string(2) "AT"
}
["request_type":protected]=>
string(16) "preauthorization"
["invoice_transmit":protected]=>
string(1) "0"
["types":protected]=>
NULL
["klarna_config":protected]=>
NULL
["klarna_campaign_code":protected]=>
NULL
["paypal_express_image":protected]=>
NULL
["check_cvc":protected]=>
NULL
["check_bankaccount":protected]=>
NULL
["bankaccountcheck_type":protected]=>
NULL
["message_response_blocked":protected]=>
NULL
["sepa_country":protected]=>
NULL
["sepa_de_show_bank_data":protected]=>
NULL
["sepa_mandate_enabled":protected]=>
NULL
["sepa_mandate_download_enabled":protected]=>
NULL
["customer_form_data_save":protected]=>
NULL
["is_deleted":protected]=>
string(1) "0"
["minValidityPeriod":protected]=>
string(0) ""
["minOrderTotal":protected]=>
string(1) "1"
["maxOrderTotal":protected]=>
string(4) "1000"
["parent":protected]=>
string(1) "<a number>"
["currency_convert":protected]=>
string(1) "0"
}
You can always extend the payone_core/config class YourNameSpace_Module_Helper_Payone extends ThePayOneNamespace_Payone_Core_Config and basically get any method to be public
class YourNameSpace_Module_Helper_Payone extends ThePayOneNamespace_Payone_Core_Config
public function someProtectedParentMethod()
{
return parent::someProtectedParentMethod();
}
}
The above will allow you to use any protected method and get the data you are after.
This is hopefully the Magento way to get information about Payones Payment methods. You should call setPaymentRestrictionNoticeMessage() somewhere in your controller.
class YourModule_Helper_Data extends Mage_Core_Helper_Abstract {
/**
* Returns array of methods that will not work with current max order value.
* #return array
*/
public function getPaymentsWithRestrictions() {
$quote = Mage::getSingleton('checkout/session')->getQuote();
$store = $quote->getStoreId();
$total = $quote->getBaseGrandTotal();
/**
* #var Payone_Core_Model_Config_Payment $model
*/
$model = Mage::helper('payone_core/config')->getConfigPayment($store);
$methods = $model->getMethods();
$restrictedMethods = array();
foreach ($methods AS $mid => $method) {
/**
* #var Payone_Core_Model_Config_Payment_Method $method
*/
$minTotal = $method->getMinOrderTotal();
$maxTotal = $method->getMaxOrderTotal();
$isEnabled = $method->getEnabled();
if($isEnabled && ($minTotal > $total || $maxTotal < $total)) {
$restrictedMethods[$mid] = $method;
}
}
return $restrictedMethods;
}
/**
* Sets notification message with information about payment methods
* that will not work.
*/
public function setPaymentRestrictionNoticeMessage() {
$restrictedMethodModels = $this->getPaymentsWithRestrictions();
$restrictedMethods = array();
foreach ($restrictedMethodModels AS $methodModel) {
/**
* #var Payone_Core_Model_Config_Payment_Method $methodModel
*/
$restrictedMethods[] = $methodModel->getName();
}
Mage::getSingleton('core/session')->addNotice(
Mage::helper('checkout')->__(
'Your order value is too high for following payment methods: ' . implode(', ', $restrictedMethods)
)
);
}
}
Get the Payone config in your function:
$payoneConfig = Mage::helper('payone_core/config')->getConfigPayment($storeId);
In Payone_Core_Model_Config_Payment you can find all methods which you can call on $payoneConfig, e.g. getAvailableMethods(). Overwrite Payone_Core_Model_Config_Payment the Magento way if you want to add more functionality.
Related
I am trying to iterate over a php object and changing each string value by reference, but something is just not working. In some arrays the strings will not be changed. Anyone has an idea why? Or has a suggestion on how to solve the task?
Here is my code:
recursive_object_string_changer($object);
function recursive_object_string_changer($object)
{
if($object == null) {
return;
}
foreach ($object as &$attribute) {
if (is_string($attribute)) {
$attribute = $attribute."!";
} else if (is_array($attribute)) {
recursive_object_string_changer($attribute);
} else if (is_object($attribute)) {
recursive_object_string_changer($attribute);
}
}
unset($attribute);
}
Thank you very much!
I think you want to make the function's signature also accept the initial object as a reference so that the recursion works on subsequent calls.
recursive_object_string_changer($object);
function recursive_object_string_changer(&$object)
{
if ($object === null) {
return;
}
foreach ($object as &$attribute) {
if (is_string($attribute)) {
$attribute .= "!";
} elseif (is_array($attribute)) {
recursive_object_string_changer($attribute);
} elseif (is_object($attribute)) {
recursive_object_string_changer($attribute);
}
}
unset($attribute);
}
I used this for a sample:
$object = new stdClass();
$object->string = 'Test';
$object->array = [
'a',
'b',
'c',
];
$subObject = new stdClass();
$subObject->string = 'Another String';
$object->object = $subObject;
Which produces:
object(stdClass)#1 (3) {
["string"]=>
string(5) "Test!"
["array"]=>
array(3) {
[0]=>
string(2) "a!"
[1]=>
string(2) "b!"
[2]=>
string(2) "c!"
}
["object"]=>
object(stdClass)#2 (1) {
["string"]=>
string(15) "Another String!"
}
}
You might always want to add a guard before the for loop to make sure that $object is an array or an object in the first place.
I am developing a web application in laravel 5.3. The problem i am getting is that attributes doesn't add up in stdClass object, however you can see my code where i am explicitly setting/adding a new attributes in a object.
problematic code
1- $sender = Sender::where('id', $this->senderId)->first();
2- if ($sender != null) {
3- var_dump($sender->bundle);
4- $sender->bundle->latitude = $this->lat;
5- $sender->bundle->longitude = $this->long;
6- $sender->bundle->location = $response->formattedAddress();
7- var_dump($sender->bundle);
8- $sender->save();
9- error_log('resolved');
10- } else {
11- error_log('no sender');
12- }
In above code you can clearly see that i am setting some new properties for bundle object.
$sender->bundle->latitude = $this->lat;
$sender->bundle->longitude = $this->long;
$sender->bundle->location = $response->formattedAddress();
but in output you can clearly see that it doesn't get add up. The code basically runs in laravel queue. In above code $sender is laravel eloquent model and the attribute bundle is being json_decode via laravel mutators.
mutator code
public function setBundleAttribute($value) {
$this->attributes['bundle'] = json_encode($value);
}
public function getBundleAttribute($value) {
return json_decode($value);
}
output of above problematic code
object(stdClass)#686 (3) { #output of line 3
["city"]=>
string(0) ""
["province"]=>
string(0) ""
["country"]=>
string(0) ""
}
object(stdClass)#686 (3) { #output of line 7
["city"]=>
string(0) ""
["province"]=>
string(0) ""
["country"]=>
string(0) ""
}
[2017-07-25 16:11:03] Processed: App\Jobs\LocationResolverQueue
resolved
Problem Solved
laravel Accessors & Mutators cause the problem.
Accessor and Mutator get called whenever we get or set property respectively, in my case the mutator was calling whenever i try to access $sender->bundle->property however accessor didn't get called because i was setting a $sender->bundle->property rather than $sender->bundle
i solved problem like
$sender = Sender::where('id', $this->senderId)->first();
if ($sender != null) {
$temp = $sender->bundle;
$temp->latitude = $this->lat;
$temp->longitude = $this->long;
$temp->location = $response->formattedAddress();
$sender->bundle = $temp;
$sender->save();
}
What i have learned about objects in php is that the hash with a number (#n) points to the instantiation times for example :
if we have something like this object(Index)#5 (1) means that we have 5 instances of the Index object.
However in my case i'm working on a custom PHP MVC i have only instantiated the class once (i'm sure only once. a model class directly within the controller ) but i'm getting an object like so
object(Timino\App\Models\Index)#5 (1)
so why is this happening ?
do namespaces affect this ! ?
does this have an affection to the performance ?!
Namespaces should not affect this. For performance issues, the number of objects during script runtime will only have an impact, if the script is getting close or over the max memory limit. FYI, here are some considerations about performance.
A simple example to show/explain the "object counter":
class TestClass {
public $number = 2;
}
class ClassInner {
protected $number = 5;
protected $innerObject;
public function __construct() {
$this->innerObject = new \stdClass();
}
}
$testInstance = new TestClass();
$classInner = new ClassInner();
$classInner2 = new ClassInner();
$testInstance2 = new TestClass();
$classInner3 = $classInner2;
echo '<pre>';
var_dump($testInstance);
var_dump($classInner);
var_dump($classInner2);
var_dump($testInstance2);
var_dump($classInner3);
echo '</pre>';
Should result in this output. Pleas have a look at the order of instances and count:
object(TestClass)#1 (1) {
["number"]=>
int(2)
}
object(ClassInner)#2 (2) {
["number":protected]=>
int(5)
["innerObject":protected]=>
object(stdClass)#3 (0) {
}
}
object(ClassInner)#4 (2) {
["number":protected]=>
int(5)
["innerObject":protected]=>
object(stdClass)#5 (0) {
}
}
object(TestClass)#6 (1) {
["number"]=>
int(2)
}
object(ClassInner)#4 (2) {
["number":protected]=>
int(5)
["innerObject":protected]=>
object(stdClass)#5 (0) {
}
}
I'm trying to implement a DataTable class in php which will be basically a table to contain data just like an sql table and will be made of array()
The class is defined as followed:
class DataTable{
protected static $tabela; // table
//columns and strips, each column point to a strip
public function __construct($colunas, $faixas) {
$this->tabela = array();
$this->constroiDt($colunas, $faixas); //builds the table
}
public function getRows($where){
// todo
}
public static function getTabela(){
return $this->tabela;
}
private function constroiDt($colunas, $faixas){
if(count($colunas)!= count($faixas)){
$this->tabela = null;
return;
}
$i=0;
foreach($colunas as $cl){
$this->tabela = array_merge($this->tabela, array($cl => $faixas[$i]));
$i += $i + 1;
}
// the result will be an array like ('col1' => ('val1','val2'), 'col2' => ('val1','val2'))
// if I want to access a value, just type array['col1'][0] for example
}
}
Outside of the class function, when I create an example DT and try to access it, it seems that will work:
$columns = array("name", "age");
$strips = array(array("someone","another person"),array("20","30"));
$dt1 = new DataTable($columns, $strips);
var_dump($dt1); // will print:
// object(DataTable)#1 (1) { ["tabela"]=> array(2) { ["nome"]=> array(2) { [0]=> string(6) "fulano" [1]=> string(7) "ciclano" } ["idade"]=> array(2) { [0]=> string(2) "20" [1]=> string(2) "30" } } }
But then I add echo "--- " . $dt1::getTabela()['nome'][0];
It doesn't even print the ---. var_dump($dt1::getTabela()) and var_dump($dt1->getTabela()) also is blank. What is being missed here? Tried also this but didn't work.
You shouldn't use $this in a static function / for static properties as there is not necessarily an object context to use.
Instead, you should use self::$tabela everywhere instead.
Or change your variable (and the related methods...) to a "normal" protected property:
protected $tabela;
You are mixing static variables with non static accesors
i just put your code and i got a lot of errors/notices
NOTICE Accessing static property DataTable::$tabela as non static on line number 10
NOTICE Accessing static property DataTable::$tabela as non static on line number 31
NOTICE Accessing static property DataTable::$tabela as non static on line number 31
NOTICE Accessing static property DataTable::$tabela as non static on line number 31
NOTICE Accessing static property DataTable::$tabela as non static on line number 31
object(DataTable)#1 (1) { ["tabela"]=> array(2) { ["name"]=> array(2) { [0]=> string(7) "someone" [1]=> string(14) "another person" } ["age"]=> array(2) { [0]=> string(2) "20" [1]=> string(2) "30" } } }
FATAL ERROR Uncaught Error: Using $this when not in object context in /home/phptest/public_html/code.php70(5) : eval()'d code:20 Stack trace: #0 /home/phptest/public_html/code.php70(5) : eval()'d code(44): DataTable::getTabela() #1 /home/phptest/public_html/code.php70(5): eval() #2 {main} thrown on line number 20
Ok, so my issue is, my ajax call isn't updating correctly. It's the same as many functions as I have, it's just not updating the values. Although, I can run the query on it's own in mysql and it update ok. Function is below:
/*
* "elerts/quicksave" > Update elert from all screen
*/
public function quicksave($id)
{
$data = (object)Input::get();
$ev = Events::find($id);
$ev->limit = $data->limit;
$ev->EventEnabled = $data->EventEnabled;
$ev->SundayStart = $data->SundayStart;
$ev->MondayStart = $data->MondayStart;
$ev->TuesdayStart = $data->TuesdayStart;
$ev->WednesdayStart = $data->WednesdayStart;
$ev->ThursdayStart = $data->ThursdayStart;
$ev->FridayStart = $data->FridayStart;
$ev->SaturdayStart = $data->SaturdayStart;
$ev->save();
$queries = DB::getQueryLog();
$last_query = end($queries); dd($last_query);
return "Your eLert has been saved!";
}
Below is an example ID getting passed and an example of the $data object that's getting passed.
$id = '107';
object(stdClass)#137 (9) { ["limit"]=> string(3) "400" ["EventEnabled"]=> string(1) "1" ["SundayStart"]=> string(1) "0" ["MondayStart"]=> string(1) "0" ["TuesdayStart"]=> string(1) "0" ["WednesdayStart"]=> string(1) "0" ["ThursdayStart"]=> string(1) "1" ["FridayStart"]=> string(1) "1" ["SaturdayStart"]=> string(1) "1"}
I'm confused as to why nothing is getting updated. Any help?
EDIT: Below I've included the code for my model so people won't have to question it...
<?php
/**
* #author jmadrigal
* Date: 7/2/14
* Time: 10:23 AM
*/
class Events extends Eloquent {
protected $primaryKey = 'eventid';
public $timestamps = false;
protected $fillable = array(
'eventname', 'eventdescription', 'EventEnabled', 'visitcost', 'groupid', 'flagid', 'SundayStart', 'MondayStart', 'TuesdayStart', 'WednesdayStart', 'ThursdayStart', 'FridayStart',
'SaturdayStart', 'limit', 'Vtmpl', 'delayV', 'Etmpl', 'delayE', 'Ttmpl', 'delayT', 'Mtemp', 'delayM', 'Login', 'freqv', 'freqt', 'freqe', 'maxe', 'maxt', 'maxv',
'amtide', 'amtidt', 'amtidv', 'apptinterval'
);
public function aInterval() {
return $this->hasMany('AppointmentInterval');
}
}
More than likely you have not defined the mass-assignment attributes your Events Model.
So in your Events Model try:
protected $fillable = array('limit', 'EventEnabled', 'SundayStart', 'MondayStart', 'TuesdayStart', 'WednesdayStart', 'ThursdayStart', 'FridayStart', 'SaturdayStart');
This is a security feature of Laravel and helps to prevent against blindly allowing any attributes to be updated.
The type being sent "string" for any checkbox wasn't going in because the values needed to be an (int) value or a (bool) value of '1' or '0'. That was the issue. Database was set up a year ago by someone else and I didn't catch that until now. It's fixed though.