php How to allow nested default value - php

level1();
function level1($value = null){
level2($value);
}
function level2($value = 100){}
How can I define $value of level1 as optional and still have the default of level2 applied?
Above code would not use the default because $value is already set to null by level1.

If you want the default value to be applied, you have to skip the argument completely. The easiest solution would be just to check, if $value === null
function level1($value = null){
if ($value === null) {
level2();
} else {
level2($value);
}
}
If you want to check, if the default value of level1 is applied, you could use func_num_args().
function level1($value = null){
if (func_num_args() == 0) {
level2();
} else {
level2($value);
}
}

Here's a way of doing it, it supports unlimited arguments:
function level1(){
$args = func_get_args();
call_user_func_array('level2', $args);
}

You could always do
function level2($value){
if($value === null)
$value = 100;
}
It's not the same as what you're looking for, but it has the same effect.

perhaps a bit dirty, but should work:
<?php
function level1($value = null){
($value === null)?level2():level2($value);
}
function level2($value = 100){echo $value;}
level1();
level1(7);
?>
this prints 100 followed by a 7.

Related

How to find where a special Smarty variable is declared in PrestaShop?

I using prestashop 1.6 and I have some variable in my index.tpl like as $aslist that I Don't know where this variable is defined or assigned!
I need to find this variable and do some change over that.
anybody know how can I find a solution that show where smarty variables assigned ?
I need to a address file like as:
$aslist assigned in .\www\controllers\front\CmsController.php - (line 58 )
You can add this function to config/config.inc.php
function log_smarty_assign($var_name)
{
$smarty_var_filter = 'aslist';
if ($var_name == $smarty_var_filter)
{
$log = '';
$trace = debug_backtrace(false);
if (isset($trace[1]))
{
$log .= 'Variable '.$var_name.' assigned in ';
$log .= $trace[1]['file'].' #'.$trace[1]['line'];
echo "<pre>$log</pre>";
}
}
}
Edit: $trace[1] should be used instead of $trace[2]
And then search for the smarty assign method and modify it to something like this:
I found it in /tools/smarty/sysplugins/smarty_internal_data.php
public function assign($tpl_var, $value = null, $nocache = false)
{
if (is_array($tpl_var)) {
foreach ($tpl_var as $_key => $_val) {
if ($_key != '') {
$this->tpl_vars[$_key] = new Smarty_variable($_val, $nocache);
//log the assignment
log_smarty_assign($_key);
}
}
} else {
if ($tpl_var != '') {
$this->tpl_vars[$tpl_var] = new Smarty_variable($value, $nocache);
//log the assignment
log_smarty_assign($tpl_var);
}
}
return $this;
}
Output example:
Variable product assigned in ...\classes\controller\Controller.php #180

in specific condition set and store a variable until another specific condition

Hello I'm pretty new in programming. I need to solve this problem in php but the solution in any different language will be great. I tryied to solve it with if statement but if condition is changed the variable is gone. Easy example for better understanding.
// possible conditions ( 'cond1', 'cond2', 'cond3', 'cond4','cond5' )
// conditions can be called randomly
I would like to have somethng like this:
$variable = 'off';
since ( $condition == 'cond2' )
$variable = 'on';
until ( $condition == 'cond4' )
The goal is to switch variable 'on' in the 'cond2' condition and hold it on when the others conditions are changing independently on their order until condition is changed to 'cond4' and variable is switched back to 'off'.
Thanks for any suggestions.
I don't think your current concept is realizable in PHP as you cannot listen to variables, you need to actively get notified. So one scenario with the same solution but a different concept would be
class Condition {
private $value;
private $variable = false;
public function setCondition($new_value) {
$this->value = $new_value;
}
public function getCondition() {
return $this->value;
}
public function isVariableSet() {
return ($this->variable === true); //TRUE if $this->variable is true
//FALSE otherwise
}
}
Now in the method setCondition(...) you can listen and actively set the variable.
public function setCondition($new_value) {
switch ($new_value) {
case 'cond2':
$this->variable = true;
break;
case 'cond4':
$this->variable = false;
break;
}
$this->value = $new_value;
}
With this you can use it like the following
$foo = new Condition();
$foo->setCondition('cond1');
var_dump( $foo->isVariableSet() ); //FALSE
$foo->setCondition('cond2');
var_dump( $foo->isVariableSet() ); //TRUE
$foo->setCondition('cond3');
var_dump( $foo->isVariableSet() ); //TRUE
$foo->setCondition('cond4');
var_dump( $foo->isVariableSet() ); //FALSE
Or in your case:
$conditions = array( 'cond1', 'cond2', 'cond3', 'cond4','cond5' );
$cond = new Condition();
foreach ($conditions as $i => $condition) {
$cond->setCondition($condition);
if ($cond->isVariableSet() == true) {
$toggle = 'on';
}
else {
$toggle = 'off';
}
$results[$condition] = $toggle.' ; ';
}
If you don't create the instance of Condition outside the loop, you gain nothing as you create a new object everytime and no state stays. However, exactly that is required.
You can also do this via array_map() and save the foreach()
$conditions = array( 'cond1', 'cond2', 'cond3', 'cond4','cond5' );
$cond = new Condition();
$results = array();
$setCondGetVariable = function($condition) use($cond) {
$cond->setCondition($condition);
if ($cond->isVariableSet() == true) {
$toggle = 'on';
}
else {
$toggle = 'off';
}
return $toggle.' ; ';
};
$results = array_map($setCondGetVariable, $conditions);

PHP - putting if statement coding inside of a variable

I am trying to get an if statement to dynamically code itself based on user input. So the if statement code is being inserted into a variable ($if_statement_variable), like this:
$if_statement_variable = "if (";
$price = trim($_GET["Price"]);
if (!empty($price)) {
$if_statement_variable .= " $Product->price < $price ";
}
$product_name = trim($_GET["Product_name"]);
if (!empty($product_name)) {
$if_statement_variable .= " && $Product->$product_name == 'product_name_string' ";
}
// plus many more if GET requests
$if_statement_variable .= ") ";
Then results from an XML file will be displayed based on user values submitted and the $if_statement_variable.
$XMLproducts = simplexml_load_file("products.xml");
foreach($XMLproducts->product as $Product) {
echo $if_statement_variable; // Here is where the problem is
{ // opening bracket for $variable_if_statement
echo $Product->$product_name; // products displayed based on if statement code in $if_statement_variable
} //closing bracket for $variable_if_statement
}
The echo $if_statement_variable above correctly displays $price from this variable string, but does NOT display $Product->price. Assuming $price had a value of 1000, the output is if ( == 1000 ). How can I get $Product->price to correctly insert itself into the $if_statement_variable so that it displays the $Product->price values from the XML file?
If you're trying to generate a boolean value dynamically, based on some complicated logic, just assign the true/false value to a variable, (say, $booleanValue) and then do if($booleanValue){}
Something like:
$price = trim($_GET['price']);
$product_name = trim($_GET['Product_name']);
if(!empty($price)){
$booleanValue = ($Product->price < $price);
}
if(!empty($productName)){
$booleanValue = ($booleanValue && $Product->$product_name == 'product_name_string')
}
if($booleanValue){
echo $Product->$product_name;
}
In other words, create a variable to hold the actual boolean value, not a string to hold an expression that will evaluate to a boolean value.
Do not build PHP source as a string. In this case callables are a better solution. A callable is a function inside a variable. In PHP this might be an function name, and array with an object and a method name, an anonymous function or an object implementing invoke.
Here is an example for anonymous functions:
function getCondition($parameters) {
$conditions = [];
if (isset($parameters['Price']) && trim($parameters['Price']) != '') {
$price = trim($parameters['price']);
$conditions[] = function($product) use ($price) {
return $product->price < $price;
}
}
if (isset($parameters['Product_name']) && trim($parameters['Product_name']) != '') {
$productName = trim($parameters['Product_name']);
$conditions[] = function($product) use ($productName) {
return $product->product_name == $productName;
}
}
return function($product) use ($conditions) {
foreach ($conditions as $condition) {
if (!$condition($product)) {
return FALSE;
}
}
return TRUE;
}
}
$condition = getConditon($_GET);
if ($condition($product)) {
...
}
It is important that each function can be called the same way. So if you call the condition function you not need to know, which condition it is. In the example above you can imagine that the getCondition() function can get really complex really fast if you add additional conditions.
If you encapsulate the conditions into classes, the usage becomes more readable:
$condition = new \YourCompany\Product\Conditions\Group(
new \YourCompany\Product\Conditions\PriceMaximum($_GET, 'Price'),
new \YourCompany\Product\Conditions\Name($_GET, 'Product_name')
);
if ($condition($product)) {
...
}
This way you separate the actual condition logic from the from the use. The source of all classes is some more then the anonymous function variant. But you you can put each class in it's own file and use them in any combination you need.
The classes need to implement __invoke().
class Group {
private $_conditions = array();
public function __construct() {
$this->_conditions = func_get_args();
}
public function __invoke($product) {
foreach ($this->_conditions as $condition) {
if (!$condition($product)) {
return FALSE;
}
}
return TRUE;
}
}
class Name {
private $_productName = NULL;
public function __construct($parameters, $name) {
if (isset($parameters[$name]) && trim($parameters[$name]) > 0) {
$this->_productName = trim($parameters[$name]);
}
}
public function __invoke($product) {
return (
NULL === $this->_productName ||
$product->product_name == $this->_productName
);
}
}
class PriceMaximum {
private $_maximum = NULL;
public function __construct($parameters, $name) {
if (isset($parameters[$name]) && trim($parameters[$name]) > 0) {
$this->_maximum = trim($parameters[$name]);
}
}
public function __invoke($product) {
return (
NULL === $this->_maximum ||
$product->price < $this->_maximum
);
}
}
This concept can even be used together with an anonymous function:
$condition = new \YourCompany\Product\Conditions\Group(
new \YourCompany\Product\Conditions\PriceMaximum($_GET, 'Price'),
new \YourCompany\Product\Conditions\Name($_GET, 'Product_name'),
function ($product) {
return $product->category == 'food';
}
);

How to quickly check what variables exist from a bunch of vars?

If you have 10 variables that are sometimes set, other times unset, is there a quick way to echo the ones that exist without throwing an exception? These vars come from user input.
I would currently write it as
if ($var_1 != NULL) { echo $var_1; }
if ($var_2 != NULL) { echo $var_2; }
if ($var_3 != NULL) { echo $var_3; }
if ($var_other_1 != NULL) { echo $var_other_1 ; }
if ($var_other_2 != NULL) { echo $var_other_2 ; }
etc.. But is there a more quicker way?
compact function will help you
Check this function: http://php.net/manual/en/function.get-defined-vars.php
You can do something like this:
<?php
$vararr = get_defined_vars();
foreach ($vararr as $name => $value) {
echo "{$name}: {$value}<br>\n";
}
Here's another option using variable variables and a list of the variables you want to examine:
foreach( array("var_1", "var_2") as $var )
{
if( isset($$var) )
{
echo $$var;
}
}

I need a more efficient way of checking if multiple $_POST parameters isset

I have these variables, and I need to check if all of them isset(). I feel there has to be a more efficient way of checking them rather than one at a time.
$jdmMethod = $_POST['jdmMethod'];
$cmdMethod = $_POST['cmdMethod'];
$vbsMethod = $_POST['vbsMethod'];
$blankPage = $_POST['blankPage'];
$facebook = $_POST['facebook'];
$tinychat = $_POST['tinychat'];
$runescape = $_POST['runescape'];
$fileUrl = escapeshellcmd($_POST['fileUrl']);
$redirectUrl = escapeshellcmd($_POST['redirectUrl']);
$fileName = escapeshellcmd($_POST['fileName']);
$appData = $_POST['appData'];
$tempData = $_POST['tempData'];
$userProfile = $_POST['userProfile'];
$userName = $_POST['userName'];
Try this
$allOk = true;
$checkVars = array('param', 'param2', …);
foreach($checkVars as $checkVar) {
if(!isset($_POST[$checkVar]) OR !$_POST[$checkVar]) {
$allOk = false;
// break; // if you wish to break the loop
}
}
if(!$allOk) {
// error handling here
}
I like to use a function like this:
// $k is the key
// $d is a default value if it's not set
// $filter is a call back function name for filtering
function check_post($k, $d = false, $filter = false){
$v = array_key_exists($_POST[$k]) ? $_POST[$k] : $d;
return $filter !== false ? call_user_func($filter,$v) : $v;
}
$keys = array("jdmMethod", array("fileUrl", "escapeshellcmd"));
$values = array();
foreach($keys as $k){
if(is_array($k)){
$values[$k[0]] = check_post($k[0],false,$k[1]);
}else{
$values[$k] = check_post($k[0]);
}
}
You could extend the keys array to contain a different default value for each post-value if you wish.
EDIT:
If you want to make sure all of these have a non-default value you could do something like:
if(sizeof(array_filter($values)) == sizeof($keys)){
// Not all of the values are set
}
Something like this:
$jdmMethod = isset($_POST['jdmMethod']) ? $_POST['jdmMethod'] : NULL;
It's Ternary Operator.
I think this should work (not tested, from memory)
function handleEmpty($a, $b) {
if ($b === null) {
return false;
} else {
return true;
}
array_reduce($_POST, "handleEmpty");
Not really. You could make a list of expected fields:
$expected = array(
'jdmMethod',
'cmdMethod',
'fileName'
); // etc...
... then loop those and make sure all the keys are in place.
$valid = true;
foreach ($expected as $ex) {
if (!array_key_exists($ex, $_POST)) {
$valid = false;
break;
}
$_POST[$ex] = sanitize($_POST[$ex]);
}
if (!$valid) {
// handle the problem
}
If you can develop a generic sanitize function, that will help - you can just sanitize each as you loop.
Another thing I like to use is function that gives a default as it sanitizes.
function checkParam($key = false, $default = null, $type = false) {
if ($key === false)
return $default;
$found_option = null;
if (array_key_exists($key,$_REQUEST))
$found_option = $_REQUEST[$key];
if (is_null($found_option))
$found_option = $default;
if ($type !== false) {
if ($type == 'string' && !is_string($found_option))
return $default;
if ($type == 'numeric' && !is_numeric($found_option))
return $default;
if ($type == 'object' && !is_object($found_option))
return $default;
if ($type == 'array' && !is_array($found_option))
return $default;
}
return sanitize($found_option);
}
When a default is possible, you'd not want to do a loop, but rather check for each independently:
$facebook = checkParam('facebook', 'no-facebook', 'string);
It is not the answer you are looking for, but no.
You can create an array an loop through that array to check for a value, but it doesn't get any better than that.
Example:
$postValues = array("appData","tempData",... etc);
foreach($postedValues as $postedValue){
if(isset($_POST[$postedValue])){
...
}
}

Categories