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:
Work through all of the rules, looking at the associated conditions and work out which one is the best match
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?
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”
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
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.
Antnee, do you have any sample data, expected results etc?
Sounds interesting, but we’re going to need something to work with fella.
Edit:
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…
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
{
protected
$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…
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?
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")
AND
if (post2 != "val2")
AND
if (post3 IS NULL)
AND
if (post4 IS NOT NULL)
AND
if (post5 BETWEEN "val5a" AND "val5b")
THEN
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).