I am working on Expression Builder, where user can add many rules.
I am trying to convert rules into the one expression, but PHP always consider as string and always return true.
Is there any way to make that expression executable?
public function translate($record = null){
$rule = $this->rule;
$conditions = [];
if( count($rule->rules) ){
$last_key = key( array_slice( $rule->rules, -1, 1, TRUE ) );
foreach ($rule->rules as $key => $value) {
$conditions[] = '"'.$record->{$value->field} .'" ' . $this->operator($value->operator) .' "'. $value->value.'"';
}
}
$condition = implode(' '.$rule->condition.' ', $conditions);
return $condition;// result : "Full Packaged Product" == "Full Packaged Product" AND "No" != "Y"
}
// using here
foreach( $records as $ind => $record ){
foreach( $rules as $rule){
// $condition = $rule->translate(collect($record));
$condition = $rule->translate($record);
if($condition){
dump('Pass', $condition);
}else{
dump('Fail', $condition);
}
}
}
Also I tried to use eval() PHP function, but no luck!
Thanks,
Kaleem
You could use eval() if you're sure that code is safe.
Usage:
eval('$res = "yes" == "no" ;');
var_dump($res); // bool(false)
Related
I want to make a method that returns keys and values. But only if the keys include the following string "_1" and "__last".
If only one matches then exit the function, only if the two string are included in the key, return the key with the value for a weather.
$infoList = array("_key_1"=>array("time"=>9, "day"=>"Tuesday", "weather"=>"sunny",
"humidity"=>"80%"),
"_key_2"=>array("time"=>5, "day"=>"Tuesday", "weather"=>"cloudy"),
"_key__last"=>array("time"=>3, "day"=>"Sunday", "weather"=>"rainy"))
public function getData() {
$list = array();
foreach($infoList as $key){
if(preg_match('/(_key)_(_1)/', $key) && preg_match('/(_key)_(__last)/', $key) == TRUE){
$list[$key] = $list[$key]["weather"]
}
}
return $list
}
You are making your life so much more difficult that it need be, use str_contains() its easier than building complex REGEX's and getting very confused by the look of it :)
I also fixed a number of other mistakes, such as the foreach that was not going to work, so check all the code.
It is also better to pass data to a function/method otherwise you get into scoping issues!
$infoList = array("_key_1"=>array("time"=>9, "day"=>"Tuesday", "weather"=>"sunny", "humidity"=>"80%"),
"_key_2"=>array("time"=>5, "day"=>"Tuesday", "weather"=>"cloudy"),
"_key__last"=>array("time"=>3, "day"=>"Sunday", "weather"=>"rainy"));
function getData(Array $infoList) {
$list = [];
$found = 0;
foreach($infoList as $key => $val) {
if( str_contains($key, '_1') || str_contains($key, '__last') ) {
$list[$key] = $val["weather"];
$found++;
}
}
if ( $found >= 2 ) {
return $list;
} else {
return false;
}
}
$res = getData($infoList);
if ( $res !== false ){
print_r($res);
} else {
echo 'Not Found';
}
RESULTS
Array
(
[_key_1] => sunny
[_key__last] => rainy
)
If you want to stick with RegEx, you can use positive lookaheads, the same way you check for passwords characters :
<?php
$pattern = '/^(?=.*_1)(?=.*_last).*$/';
$shouldMatch = [
'_1_last',
'foo_1bar_lasthello',
'_last_1',
'foo_lastbar_1hello'
];
echo 'next ones should match : ' . PHP_EOL;
foreach ($shouldMatch as $item)
{
if (preg_match($pattern, $item))
echo $item . PHP_EOL;
}
$shouldNOTMatch = [
'_2_first',
'bar_lasthello',
'foo_las_1hello'
];
echo 'next ones should NOT match : ' . PHP_EOL;
foreach ($shouldNOTMatch as $item)
{
// v------------ check
if (!preg_match($pattern, $item))
echo $item . PHP_EOL;
}
Output :
next ones should match :
_1_last
foo_1bar_lasthello
_last_1
foo_lastbar_1hello
next ones should NOT match :
_2_first
bar_lasthello
foo_las_1hello
I use the below block of code to validate Unique username.
function validateRepositoryUnique($field, $list, &$valid) {
if ( preg_grep('/^'.preg_quote($field->value).'$/i', $list) == -1) {
$valid = false;
$field->valid = false;
$field->error = '"' . $field->value . '" already exists.';
return false;
}
return true;
}
Example.
$filed->value = "test";
$list = array('test','test1','Test');
However I passed "test" in $filed->value. the Boolean kept showing value bool(true) when i did var_dump(validateRepositoryUnique($field, $list, &$valid));
And whatever I have inputted "test", "abc", "a", the Boolean kept return value bool(true).
My intention is when text found in array, it will return the $valid's value to false and print out the error.
Apology for my bad English and my basic knowledge of PHP programming language.
preg_grep does not return -1 if it finds no results. If returns an array of what it found. You can see the output in the example below.
Notice that I somewhat rewrote your function.
function validateRepositoryUnique($field, $list, &$valid) {
$preg = preg_grep('/^'.preg_quote($field->value).'$/i', $list) ;
var_dump($preg);
echo "\n";
if ( count($preg) == 0 ) {
$valid = false;
$field->valid = false;
$field->error = '"' . $field->value . '" already exists.';
return false;
}
return true;
}
$v;
$list = ['square', 'round', 'long'];
$f1 = new stdclass;
$f1->value = 'round';
$result = validateRepositoryUnique($f1, $list, $v);
var_dump($result);
echo "\n";
$f1->value = 'grass';
$result = validateRepositoryUnique($f1, $list, $v);
var_dump($result);
echo "\n";
$f1->value = 'triangle';
$result = validateRepositoryUnique($f1, $list, $v);
var_dump($result);
echo "\n";
Can I pass values into this query? If so, what is the format of $arr?
$sql = "SELECT * FROM tree WHERE tree_id IN ($1);";
$result = pg_query_params($sql, [$arr]);
$sql = "SELECT * FROM tree WHERE tree_id = ANY ($1)";
$result2 = pg_query_params($sql2,[$arr]);
$arr format example = "{12,13}"
If your SQL statement contains an IN clause which takes a varying number of parameters, then it's somewhat tricky to use a parameterized query. As you've found out, you can solve this by using ANY instead of IN (documentation here), and then passing a PostgreSQL array as the sole query parameter.
$sql = 'SELECT * FROM tab WHERE id = ANY ($1);';
$id_array = [ 1, 2, 3 ]; // id_array can be of any size
$result = pg_query_params($sql, [ toPostgresArray($id_array) ]);
Whereby toPostgresArray() is the following helper function, which converts a PHP array into a PostgreSQL array:
function toPostgresArray($values) {
$strArray = [];
foreach ($values as $value) {
if (is_int($value) || is_float($value)) {
// For integers and floats, we can simply use strval().
$str = strval($value);
} else if (is_string($value)) {
// For strings, we must first do some text escaping.
$value = str_replace('\\', '\\\\', $value);
$value = str_replace('"', '\\"', $value);
$str = '"' . $value . '"';
} else if (is_bool($value)) {
// Convert the boolean value into a PostgreSQL constant.
$str = $value ? 'TRUE' : 'FALSE';
} else if (is_null($value)) {
// Convert the null value into a PostgreSQL constant.
$str = 'NULL';
} else {
throw new Exception('Unsupported data type encountered.');
}
$strArray[] = $str;
}
return '{' . implode(',', $strArray) . '}';
}
I'm having a problem that the code is returning "Men" for all of the "Women" values because it also contains the term "Men." I've tried "~\bWord\b~" in vain.
How can the code below be edited to return different values?
function replaceWords($value) {
//here are predefined values
$predefined = array(
array(
'search'=>'Women',
'replaceWith'=>'Women'
),
array(
'search'=>'Men',
'replaceWith'=>'Men'
)
);
//search and replace
$found = false;
foreach ($predefined as $item) {
$search = array_map('trim', explode(',', $item['search']));
foreach ($search as $s) {
if (strstr(strtolower($value), strtolower($s))) {
$found = true;
$value = $item['replaceWith'];
break;
}
}
}
return ($found)?$value:"";
}
Help is much appreciated.
simply don't use strtolower()
"Women" and "Men" won't match if you keep it case sensitive.
This worked for me:
if (preg_match("/\b".strtolower($s)."\b/i", strtolower($value)) ) {
I have a function that builds a MySQL query from the supplied arguments. My current code is:
($args can be an empty array or up to a set of 5 field_names=>array_of_ids ...)
if( !(empty( $args )) )
{
$flag = 0;
$sql_append = '';
foreach( $args as $field_name => $id_array )
{
if( $flag == 0 )
{
$where_connector = " WHERE ";
$flag = 1;
}
else
{
$where_connector = " AND ";
}
${ $field_name . '_string'} = join(',',${ $field_name . '_ids'});
$sql_append .= $where_connector . 'link_id IN ($ids)";
}
}
I'm self-taught and so constantly worry about best practices. I seem to remember some sort of function that handles arguments, perhaps in a way that can be applied here more efficiently. Any ideas?
To neatly construct your WHERE $fieldname IN($ids) clauses from a $fieldname=>$id_array array, you can try this :)
function buildWhereIns(array $args)
{
if(!is_array($args) || empty($args)) return "";
$ids = array_map(function($item){
return implode(',',$item);
}, array_values($args));
$fields = array_map(function($item,$id){
return $item.' IN('.$id.') ';
}, array_keys($args),$ids);
return = count($fields) > 0 ? count($fields) > 1 ? " WHERE " . implode(' AND ', $fields) : " WHERE " . array_shift($fields) : "";
}
I would say that the larger issue here is that you should be using some sort of technique to protect your code against SQL injection. For example, PHP's built-in PDO classes provide a really easy way to do this: http://www.php.net/manual/en/pdo.prepared-statements.php.
In general, though, if you want a loop that behaves differently on the first or last iteration, your method isn't bad. The other obvious method is to just do the first (or last) iteration outside the loop, and then perform the iterations which are the same inside the loop body.