Reputation: 1559
I have the following example array:
$comparisons = array(
0 => array(
'method' => 'productTotalQuantity',
'operator' => '>=',
'value' => '2'
),
1 => array(
'method' => 'productTotalWeight',
'operator' => '<=',
'value' => '10'
)
);
I have invented this array structure, so it can be altered if required. I am trying to somehow evaluate the operator key, so that I can achieve something along the lines of:
foreach ($comparisons as $comparison) {
$value = $this->$comparison['method']($product);
// E.g. $value = $this->productTotalQuantity($product)
// $value could = 4
if ($value $comparison['operator'] $comparison['value']) {
// Comparison successful
$matches[] = TRUE;
}
}
if (count($matches) == count($comparisons)) {
// All comparisons were successful. Apply the discount.
}
If you have time, a full code example of how to parse this array would be extremely helpful. I've been working on it for about 20 hours straight and think I'm about to literally bash my head against a brick wall. If you are familiar with Magento, I am trying to somewhat mimic the functionality of the "Shopping Cart Price Rule" Conditions in Promotions.
Upvotes: 0
Views: 172
Reputation: 3905
<?php
$ge = function($a, $b) {return($a >= $b);};
$le = function($a, $b) {return($a <= $b);};
$comparisons = array(
array(
'method' => 'productTotalQuantity',
'operator' => $ge,
'value' => 2
),
array(
'method' => 'productTotalWeight',
'operator' => $le,
'value' => 10
)
);
// finds out if discount should be applied in this price range
function discount_finder($myval, $comparisons) {
$discount = TRUE;
foreach($comparisons as $comp) {
if (!$comp['operator']($myval, $comp['value'])) {
$discount = FALSE;
$break;
}
}
return $discount;
}
$discount = discount_finder(1, $comparisons);
if ($discount == TRUE) { // apply discount
echo "Discount applied!!!\n";
} else {
echo "no discount!\n";
}
$discount = discount_finder(6, $comparisons);
if ($discount == TRUE) { // apply discount
echo "Discount applied!!!\n";
} else {
echo "no discount!\n";
}
$discount = discount_finder(13, $comparisons);
if ($discount == TRUE) { // apply discount
echo "Discount applied!!!\n";
} else {
echo "no discount!\n";
}
?>
Upvotes: 0
Reputation: 4199
"translating" operations from strings to real operations is mostly dirty and or evil :-) you need a lot of conditional code (if-else) or eval (but everybody knows: eval is evil ^^)
I would use an object-oriented approach, since PHP does support object orientation (I don't know the exact php syntax, it has been a while ;-)) and I give you pseudo code to enforce the ideas:
class AbstractComparator {
boolean static compare($operand1, $operand2);
}
class EqualsComparator extends AbstractComparator {
@Override
boolean static compare($operand1, $operand2) {
return ($operand1 == $operand2);
}
}
// Now use one of the subclasses in your datastructure
$comparisons = array(
0 => array(
'method' => 'productTotalQuantity',
'operator' => EqualsComparator,
'value' => '2'
),
1 => array(
'method' => 'productTotalWeight',
'operator' => SmallerThanComparator,
'value' => '10'
)
);
$allComparisonsSuccessful = true;
foreach ($comparisons as $comparison) {
$value = $comparison['operator'].equals($product);
// Use the AND operator... full predicate is only true if all elements are true
$allComparisonsSuccessful = $allComparisonsSuccessful && $value;
}
Upvotes: 4
Reputation: 19476
This would be an easy job for eval()
. Unfortunately, there's an important rule about when to use eval()
which is: Never do it.
So instead you could introduce a method like this
function parseComparison($comparison)
{
list($methodValue,$operator,$value);
switch ($operator)
{
case '>=': return $methodValue >= $value;
case '<=': return $methodValue <= $value;
case '>': return $methodValue > $value;
case '<': return $methodValue < $value;
default: return false;
}
}
Upvotes: 1