views:

109

answers:

2

I am trying to create an object that is capable of handling query-like conditional statements. This is so I can 'join' two conditions together to create a dependency between them based on the type of 'join' being used. I currently have a simple object that contains the following methods:

public function addCondition ( Condition $condition, $join = null )
{
    $this->conditions[] = $condition;
}

public function validate ( )
{
    foreach ( $this->conditions as $condition )
    {
        $result = $condition->validate( );
        [...]
    }
}

The problem is, I need to be able to perform a conditional join between two statements, that will affect the return value of the the validate method. The idea is that you could supply a condition as follows:

$this->addCondition($condition_1);
$this->addCondition($condition_2, 'AND');
$this->addCondition($condition_3, 'NOT');

This would then generate the logic required to specify that the results of the third condition would backwards-chain to affect the results of the first condition.

In the example, lets say:

condition_1 = Apple is Red
condition_2 = Apple is Ripe
condition_3 = Apple is Golden Delicious

Using this I should assume that if I was to pass a ripe, red and golden delicious apple, the result of validate() would be false. The method should fail because the 'join' for condition_3 is NOT.

However, at present there is no way of telling the code that the result of the entire method depends on the result of the previous condition and the way it is joined to it.

Any help is greatly appreciated! Thanks.

A: 

Put the logic in your Condition subclasses.

Create a Condition_And class that takes two (or more) Condition objects and returns true only if they are both true.

Create a Condition_Or class that takes two (or more) Condition objects and returns false if any is true.

Create a Condition_Not class if you feel it is necessary (Apple is NOT Golden Delicious).

Stringing these together should get you any query you're looking for. Since they're all subclasses of the same type, you can build them up putting NOTs inside of ORs inside of ANDs inside of ORs and so on.

Scott Saunders
A: 

Conditionals that involve both AND and OR are inherently nested. Your class does not seem to have a way to express this.

No nesting means that your conditions must either all be joined with AND, or all be joined with OR. In any case - you can't use both at the same time.

For your example, AND seems the natural choice, so all you need is a NOT flag for each condition:

$this->addCondition($condition_1, true);   // e.g.: must be true to succeed
$this->addCondition($condition_2, true);
$this->addCondition($condition_3, false);  // e.g.: must be false to succeed

You would then do:

$valid = true;

foreach ( $this->conditions as $condition )
{
  $valid = $valid && $condition->validate();
  if (!$valid) 
  {
    // react to "validation failed at $condition"
  }
}

return $valid;
Tomalak