Matching Dynamic Rules

I need to model some rules in to a system. They don’t need to be weighted at this point, just simple rules. Basically, when a record is saved to the database, the PHP will check whether the values match with the existing rules and act accordingly. Basically a series of IF…ELSE statements, but they’re in the database, rather than hard coded in PHP.

The rules are stored in the database in two parts. One table holds the actual details of the rules and each has a UID, while the second holds the individual conditions that need to be met.

I came up with two ideas to process these:

  1. Work through all of the rules, looking at the associated conditions and work out which one is the best match
  2. Create some kind of checksum that is generated when the form is submitted which is checked against one stored against the rule itself

In the end I figured that the second would be the more elegant solution, but I can’t get it to work. I wanted to be clever and have it have options like “IF EQUALS”, “IF DOESN’T EQUAL”, “IF BETWEEN” etc. I have that data going in to the database no problem, but processing it afterwards is the problem.

I need this completed and tested by the end of the week and what I originally thought would be a days work at best looks like it’s going to be my undoing. Does anyone have any help for me on this?

Thanks guys

Have you looked at MySQL triggers?

I haven’t, no. I don’t suppose you can give me a bit more of a pointer? It’s the “how to find the best match” part that I’m struggling with. I will look a bit more in to triggers though, see if I can work out how to use them in this example

hehe. “They don’t need to be weighted at this point” but “give me a bit more of a pointer”
And no one bothered to define “best match”, of course. “Give me clear answer for I need something from somewhere”

What? :confused:

Need to post more info if you want help. You have to define “best match” somehow, otherwise any matches will all be TRUE, and hence all equal.

Um, sorry?

Dunno if that helps with “best”, but perhaps I’m misunderstanding. I was thinking of priority, eg a11 is more important than a10, and 8 is more important than 7, so what is best: a11, 7 or a10, 8

Anyway, also intrigued.

Basically, I will be posting a bunch of data such as:

job: 123456
type: a12
status: 8

I need to then check that against rules. Some will ignore certain values, like the job number for example. Others may need to check the type and status, so “IF type = ‘a12’ AND status BETWEEN 7 AND 8” as a loose example.

Does that help?

Antnee, do you have any sample data, expected results etc?

Sounds interesting, but we’re going to need something to work with fella.



Just seen your post above, in effect, you’re going to need a parser for your ‘language’ which in turn would provide a mapping to build the validator. The specification pattern maybe of some use here…

Thanks Anthony, I’ll take a look and see what I can come up with

interface Specification_Interface
     * @return  bool
    public function isSatisfiedBy($record);

class BetweenSpecification implements Specification_Interface
    public function __construct($field, $lower, $upper){
        $this->field = $field;
        $this->lower = $lower;
        $this->upper = $upper;
    public function isSatisfiedBy($record){
        return $record[$this->field] >= $this->lower && $record[$this->field] <= $this->upper;

$record = array(
    'age'   => 18

$specification = new BetweenSpecification('age', 16, 21);

); #bool(true) 

Maybe this will help. :wink:

Hash, sounds like you’re talking about weighting, which I wasn’t particularly bothered about right now.

Anthony, seems like it could be potentially long winded, because I have up to 18 different values that need to be assessed. I assume you’re suggesting that I run through all of the rules in turn, see which produces the highest number of TRUE results, and then use that one?

The highest number of true results is a weighting. You need to work out what you want, or post some data. Anthony’s solution won’t give you the highest number of true, only t or f based on a number of boolean conditions.

Well, kind of… you would split your rule into segments (or specifications) you would then create a composite object of these specifications to validate the record.

class CompositeSpecification implements Specification_Interface
        $sub_specifications = array();
    public function isSatisfiedBy($candidate){
        foreach($this->sub_specifications as $specification){
            if(false === $specification->isSatisfiedBy($candidate)){
                return false;
        return true;
    public function addSpecification(Specification_Interface $specification){
        array_push($this->sub_specifications, $specification);

So, this ‘IF age BETWEEN 16 AND 21’, would become…

$specification = new CompositeSpecification();
$specification->addSpecification(new BetweenSpecification('age', 16, 21));


Following? :slight_smile:

Using this method, it’s fairly simple to add weighting, a trivial example would be the addition of another method…

    public function getScoreFor($candidate){
        $satisfiedby = 0;
        foreach($this->sub_specifications as $specification){
            if(true === $specification->isSatisfiedBy($candidate)){
        return $satisfiedby;

Whether this returns a percentage maybe is up-to you. :wink:

:wink: well I’m thinking the OP’s whole problem is he doesn’t have a weighting algorithm. Despite his claims to not need one, he is clearly asking for one

It’s the “how to find the best match” part that I’m struggling with

highest number of TRUE results

I could be on the wrong track, but what is better: a11, 7 or a10, 8? is the real problem here, not how to represent it with classes.

hash, what I mean by weighting (and apologies if I used the wrong definition) is that if two cases match, I don’t need one to take precedence, because no two rules will (should) ever interfere, I just need to know which rule to work with.

Anthony, I think your solution looks the opposite way around for me as you appear to be passing the range to the object and it checks whether it matches or not within the class, whereas I need to pass the actual value and have that verified. I imagine it’s not hard to switch them around though?

Are you sure?

I thought you wanted to create (string)‘rule’ which would validate a record? I’ll go re-read the OP! :stuck_out_tongue:

Oh dear, I may be confusing this further. Let me see if I can reword it so that we’re all on the same page (sorry)

I will pass a series of values from a form. These values then need to be checked to see whether they are equal to, not equal to, or between (depending on the rule in question) another value (or pair of). So, if I say the customers postcode is “AB34 5EF” as an example, I need the system to look and see whether any rules apply to either that postcode, or whether this postcode falls within a range (for example “AB1 1AA to AB99 9ZZ”).

However, there will not just be one value that needs to be checked to see which rule to use (each rule has numerous conditions), there can be anything up to 18, so as an example:

if (post1 == "val1")
if (post2 != "val2")
if (post3 IS NULL)
if (post4 IS NOT NULL)
if (post5 BETWEEN "val5a" AND "val5b")
do this....

I have one table that lists the actual rules, and another that lists the conditions that apply to the rules (sharing a rule_id FK).

I was trying to not have to work through all of the rules, since it’s a lot of data from the DB, but rather I was hoping that I could generate some kind of checksum that I would save against the rule itself, and when the data is posted, check whether a checksum of this data matched the checksum of the rule, therefore immediately finding the rule I need to use (if any; sometimes no rule applies and nothing happens, rather than best match).

Sorry for the confusion. Is it any clearer now?