Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I store a PHP conditional staement in the database for later use?

In our current application I have a report that contains something like:

if($foo == 3 || $bar > 3) {
    $e = someFunction();
};

but for a different client that same expression might be:

if($foo == 3 || $bar == 5 && $foobar != 9) {
    $e = someFunction();
};

Is there an straight-forward way to store the two different expressions, just the

$foo == 3 || $bar > 3 OR $foo == 3 || $bar == 5

bits in the database (MySQL) so I do not have to hard code all of these rules by client or maintain client versions of the same report. I'm trying to figure out if I can set a variable o replace the conditions. Something like:

$conditions = $row_rsConditions['condition_row']    //Get $foo == 3 || $bar > 3 from the DB and store it as $conditions
if($conditions) {
    $e = someFunction();
};

There could be > 100 different clients and each client could/would have a different set of expressions. I'm just not sure of the right/best way to do this.

UPDATE:

I think I understand the issues using PHP's eval() function. But because of the number of possible combinations I am leaning towards using the DB to store the conditions (not sure about using eval() just yet)

Does it make any difference (safer) if there is no user facing interface that writes to the condition field/table? It could be something we manage on our end alone.

like image 289
Jason Avatar asked Aug 29 '11 11:08

Jason


2 Answers

i would be very careful about storing logic in the database.

  1. you code is no longer all in one place.
  2. logic in the database is unlikely to be under source control
  3. if you change the code and breaks all of that client specific logic, you have to go back into the database and edit it for every client.
  4. other people could have access to the database and could change the code to something malicious.

this might not be the best solution but i would suggest creating an abstract base class, then inherit from that, a class specific to each client.

Any functions that are customised can be added as a method to the base class, and overridden for client specific implementation.

use a switch statement to instantiate the class based on a client id or name (something that doesn't change) that you already store in the database.

switch ($client_name) {

case "abc ltd":
   $customlogic = new CustomLogicAbc();
   break;

case "zyx ltd":
   $customlogic = new CustomLogicXyz();
   break;

default: 
   $customlogic = new CustomLogicDefault();
   break;

}

if ($customlogic->doSomething($parm1, $parm2)) {
  // custom logic has been applied
}
like image 98
bumperbox Avatar answered Sep 20 '22 13:09

bumperbox


To elaborate on my comment:

Your last code is nearly what I meant:

$conditions = $row_rsConditions['condition_row'];    //Get "$foo == 3 || $bar > 3"
if(eval("return (" . $conditions . ");")) {
    $e = someFunction();
}

However I will warn you again to remember the risk of doing this. When you use code from the database it is likely that errors are within. At least some security check should be done on the data to avoid misuse.

Another option that is a bit more complicated but not that prone to misuse would be to encode the conditions. As it seems that you only compare 2 variables with a value each you could save for each variable something like:

0 !=
1 ==
2 >=
3 <=
4 >
5 <

To save the relation and additionally save the value to which it should be compared. That way there is no direct execution of code that is saved in the database.

like image 39
Nobody moving away from SE Avatar answered Sep 20 '22 13:09

Nobody moving away from SE