"dynamic" conditions?

I want to create a method or function to check for the presence of one or more variables, or a combination of variables, or relations of variables, in the query string of a URL ; the catch is I don’t know which variables I will want to check for or in what pairing or what condition.

checking for the presence of a single variable seems simple: isset($_GET[$vName]);

but I could also end up needing to know:

( isset($_GET[$vName]) && (( isset($_GET[$vName2]) || isset($_GET[$vName3]))) || $_GET[$vName]>$someNumber)) ;

in other words, I seem to be in need of an IF statement with dynamic conditions. Is there a way to do this w/o resorting to EVAL()?

Your question is a bit vague and would be helpful if you could supply:

  1. typical URLs that you would like to test
  2. all possible $_GET[‘parameters’]

This code may be helpful:



<pre style="">
<?php 
$url = 'http://dresden-phoenix.com?vName="Tom is vName"&vName2="dick is vName2"&vName3="Harry is vName3"';
echo '<br />'.$url;


print_r(parse_url($url));
// $params  = parse_url($url, PHP_URL_PATH);


echo '<br /><b>$_GET items &values : </b>';
  foreach($_GET as $get => $value)
  {
   echo '<br />' .$get .' => ' .$value;
  }


/* Set Defaults */ 
  $vName  = isset($_GET['vName'] )  ? $_GET['vName']  : NULL;
  $vName1 = isset($_GET['vName1'])  ? $_GET['vName1'] : NULL;
  $vName2 = isset($_GET['vName2'])  ? $_GET['vName2'] : NULL;
  $vName3 = isset($_GET['vName3'])  ? $_GET['vName3'] : NULL;
  $someNo = 123;


echo '<br /><br />';  
echo '<br />$vName : '  .$vName;  
echo '<br />$vName2 : ' .$vName2;  
echo '<br />$vName3 : ' .$vName3;  
echo '<br />$someNo : ' .$someNo;  
echo '<hr />';
if( (isset($vName) && $vName >= $someNo)
    || 
    (isset($vName) && (isset($vName2) || isset($vName3)) )
  ) 
{
  echo '<br />Yes : $vName >= $someNo || $vName2 || $vName3 is SET' ;
}else{
  echo '<br />Sorry - failed';
}
?>
</pre>



Output

http://dresden-phoenix.com?vName=“Tom is vName”&vName2=“dick is vName2”&vName3="Harry is vName3"Array
(
[scheme] => http
[host] => dresden-phoenix.com
[query] => vName=“Tom is vName”&vName2=“dick is vName2”&vName3=“Harry is vName3”
)

$_GET items &values :
vName => “Tom is vName”
vName2 => “dick is vName2”
vName3 => “Harry is vName3”

$vName : “Tom is vName”
$vName2 : “dick is vName2”
$vName3 : “Harry is vName3”
$someNo : 123[HR][/HR]
Yes : $vName >= $someNo || $vName2 || $vName3 is SET

This seems to be the crux of the problem. Even if you did resort to eval, how are you deciding what variables to check?

Yes, before you can even begin to write any code you’ll need to understand the logic involved.

True, you can use $_GET to determine which vars have been passed but that will only get you so far.

What I usually do in these situations is get out a lot of scrap paper and start scribbling away as the ideas come to mind just so I can get a visual in front of me.

This seems to be the crux of the problem. Even if you did resort to eval, how are you deciding what variables to check?

Am not. That’s exactly it.

Here is the non-code of what I am trying to achieve.

I am building a CMS/Templating system based on user defined DB tables. The system is based on a data objects ( data retrieved from the corresponding table)

Right now each data object is built at each individual template file.

i thought it might be nice to have a thisdoc() type function instead that would determine which variables are present, and use that to build a corresponding DB query for the data object.

examples:

url?cat=1
since $_GET[‘cat’] is set, use a corresponding query string ( one that may list all posts in category 1, for example)
url?post=15
since $_GET[‘ent’] is set, use a corresponding query string (one that retrieves post 15, for example)
url?post=15&cat=1
since $_GET[‘ent’] and $_GET[‘cat’] are set, use a corresponding query string (one that retrieves post 15,IF it’s in cat=1 for example)
url?pg=1
since $_GET[‘pg’] is set, use a corresponding query string (one that retrieves all post in category 1, if category one is marked as a page)

Since the tables in the DB are user defined, so are the query string variables/DB queries… this function would serve as a handler for that. So, I have NO ADVANCED knowledge of which variables will be needed at which point.

I mean, a user coudl decide to use this system to do a shopping cart, create a table for products, and use :

url?prod=5&cat=10&cheap=20
to use the ALSO USER GENERATED QUERY that retrieves ( 5 products, from category 20 that are cheaper than $20). I emphasize … the DB query itself is not important the user would determine this in a settings doc, this function is merely for the system to know which URL query strings go which which DB queries

I hope that’s clearer.

For the purpose of this exercise, I’m going to assume the settings doc goes something like this:

$mapUrlQueryToDbQuery = [
    'select * from post left join cat where cat.id = ?' => ['cat'],
    'select * from post where post.id = ?' => ['post'],
    'select * from post left join cat where post.id = ? and cat.id = ?' => ['post', 'cat'],
    'select * from prod left join cat where cat.id = ? and prod.price < ? limit ?' => ['prod', 'cat', 'cheap'],
];

In which case, you could probably select the appropriate DB query like so:

    foreach ($mapUrlQueryToDbQuery as $dbQuery => $urlQueries) {
        // Check if all the URL queries are present
        foreach ($urlQueries as $urlQuery) {
            // If one of the URL queries isn't defined, then move on to try the next set
            if (!isset($_GET[$urlQuery])) {
                continue 2;
            }
        }
        
        // If we get here, then all the URL queries are accounted for, so return the associated DB query
        return $dbQuery;
    }

I realize this might look a little crazy and putting the urls together might be a bit tricky but this seems to work based or putting the parameter between **, for example A for AND, GT for greater than etc.

<?php
/*
Example from OP
( isset($_GET[$vName]) && (( isset($_GET[$vName2]) || isset($_GET[$vName3]))) || $_GET[$vName]>$someNumber)) ;
*/
//Sample
// $url = 'http://page.com?vName*E*=Tom is vName*A*&*LB*=&vName2*E*=dick is vName2*O*&vName3*E*=Harry is vName3&*RB*=&*A*=&someNo*GT*=123 

//Parameters are put at the end of GET Keys OR Values and are surrounded by *, e.g. *A*
$keys = array("A" => "AND", "O" => "OR", "E" => "=", "GT" => ">", "GTE" => ">=", "LT" => "<", "LTE" => "<=", "LB" => "(", "RB" => ")"); 

$condition = "";
$condition_parts = array();

foreach($_GET as $get => $value):
	if(preg_match_all('/\\*(.*?)\\*/',$get,$match)) {
		//Remove parameter from GET
		$get = str_replace("{$match[0][0]}", '',$get);
		if(!empty($get)){
			$condition_parts[] = $get;
		}
		//Get KEY value
		$condition_parts[] = $keys[$match[1][0]];
	}elseif(!empty($get)){
		$condition_parts[] = $get;		 
	}
	
	if(preg_match_all('/\\*(.*?)\\*/',$value,$match)) {
		//Remove parameter from Value
		$value = str_replace("{$match[0][0]}", '',$value);
		if(!empty($value)){
			$condition_parts[] = "'" . $value . "'";
		}
		//Get KEY value
		$condition_parts[] = $keys[$match[1][0]];
	}elseif(!empty($value)){
		$condition_parts[] = "'" . $value . "'";
	}
endforeach;
  
  if(!empty($condition_parts)){
  $condition .= " WHERE ";
  }
  $condition .= implode(" ",$condition_parts);
  echo '<br />' .$condition;
  
  //Result: WHERE vName = 'Tom is vName' AND ( vName2 = 'dick is vName2' OR vName3 = 'Harry is vName3' ) AND someNo > '123'
?>

Some brilliant thinking shown above! But am off a bit.

When I originally coded my templating frame work , I had created a function called thisDoc().

Essentially it did what has described above ( checking for a contain based on the existence and values of variables in the URL query string) and then prepared a sql query for a data object. the problem is that the logic and output are hard coded… limiting its fuctionality.

I guess I was hoping to device a way to expand that.

since thisDoc() is essentially a sequence of if/elsif statements leading to the construction of an instance of a data object I was looking for way to expand that dynamically.

My theorized solution was iterating through array of conditions that would be evaluated and a corresponding string retrieved to build the query (or something like that).

$Arr['logic'][0]=create_function('','return isset($_GET['pg']))';
$Arr['sql'][0]='SELECT * FROM `Pages` WHERE `PageID`=".$_GET['pg'];
$Arr['logic'][1]=create_function('','return (isset($_GET['cat']) && isset($_GET['prod'])))';
$Arr['sql'][1]='SELECT * FROM `Products` WHERE `Category`=".$_GET['cat'];
$Arr['logic'][2]=create_function('','return (isset($_GET['sku']) || isset($_GET['prod'])))';
$Arr['sql'][2]='SELECT * FROM `Products` WHERE `ProdID=".$_GET['prod'];
&#8230;
foreach ($Arr['logic'] as $k=&gt;$v){
    if ($v()){
	$DataO= new RMCO($Arr['sql'][$k];
            break;
}

}

Maybe this is not as practical as I thought it would be.

Wow… this was a “DUH” moment.

Tho I still wish PHP could safely do a boolean eval of a string as described somehow; I just realized that in this particular scenario I don’t need to do the evaluation within the function.

The logical evaluation can be passed or stored before/at the time of the function call! Maybe someone mentioned this and I was just too exhausted to get it. If so, thanks for the inspiration.

In other words my array could be directly set :

$tests['logic'][]=isset($_GET['pg']);
$tests['logic'][]=(isset($_GET['pg']   ) || isset($_GET['cat']   ) ;
$tests['logic'][]=(isset($_GET['prod'] ) && ((isset($_GET['cat'])   && $_GET['cat']==1  ) || isset($_GET['pg']  ));
...

now that was was obvious…duh!

thanks everyone for all the help!

Although this wasn’t a situation where you needed to do any string boolean evaluation, if ever you need to in the future, you should check out the Symfony ExpressionLanguage component.