-1

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?

2
  • 1
    Do NOT store if's like that -> it makes the code impossible to read Commented Apr 4, 2014 at 12:17
  • Where do you do declare $Product->price ? Commented Apr 4, 2014 at 12:21

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

For some reason the if conditions (placed in the $booleanValue) are not being applied. Nothing is being displayed in the foreach loop.
1

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';
  }
);

1 Comment

Thanks! A lot to grasp here. I'll try to make this work!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.