I have a code in php it takes a well formatted string such as 'field,operator,value' and produces a WHERE statment to MySQL database query.
if the two fields names below end with the same characters such as 'id' like 'id' and 'classid' it produces strange behavior. such as the following test.php file:
<?php
$where = $_GET['where'];
$tokens = multiexplode(array("^", "~", "(", ")"), $where);
$where= str_replace("~"," OR ",$where);
$where = str_replace("^", " AND ", $where);
foreach ($tokens as $item) {
if (!empty($item)) {
$where = str_replace($item, getOperand($item), $where);
}
}
echo 'WHERE '.$where;
function multiexplode($delimiters, $string)
{
$unifydelimters = str_replace($delimiters, $delimiters[0], $string);
$conditions = explode($delimiters[0], $unifydelimters);
return $conditions;
}
function getOperand($item)
{
$extokens = explode (",", $item);
switch (trim($extokens[1])) {
case 'eq':
return trim($extokens[0]) . " = '" . trim($extokens[2]) . "' ";
break;
case 'neq':
return trim($extokens[0]) . " != '" . trim($extokens[2]) . "' ";
break;
default:
return "";
break;
}
}
If you test it in the browser like this:
http://localhost/test/test.php?where=id,eq,1^classid,eq,1X
Where X is any number from 0 to infnity it will echo the following line:
note that both fields id and classid end with 'id'
id = '1' AND classid='1' X
But if tested with the following urls it works fine:
http://localhost/test/test.php?where=id,eq,1^classid,eq,MX where M>1 and X is any number
http://localhost/test/test.php?where=id,eq,1^class,eq,1X , X is any digit
http://localhost/test/test.php?where=id,neq,1^classid,eq,1X,, X is any digit
Any idea why this is happenning??
Thanks,
Related
I am refactoring some legacy PHP code (version 5.5) and I need to refactor a function to use preg_replace_callback() from preg_replace() (this is because of a \e evaluation deprecation) however what is being passed into the only 2 preg_replace() calls are arrays of search patterns and arrays of replacements.
I am aware I need to pass in a callback function to preg_replace_callback() but what would be the way to go about this when each pattern is different?
function format($in, $options = 0)
{
if (!$options) {
$options = FORMAT_BREAKS | FORMAT_HTMLCHARS | FORMAT_CENSOR;
}
if ($options & FORMAT_CENSOR) {
if (!$this->replaces_loaded) {
$this->get_replaces();
}
if ($this->censor) {
$in = preg_replace($this->censor, '####', $in);
}
}
if ($options & FORMAT_MBCODE) {
$search = array(
'~(^|\s)([a-z0-9-_.]+#[a-z0-9-.]+\.[a-z0-9-_.]+)~i',
'~(^|\s)(http|https|ftp)://(\w+[^\s\[\]]+)~ise'
);
$replace = array(
'\\1[email]\\2[/email]',
'\'\\1[url]\' .wordwrap(\'\\2://\\3\', 1, \' \', 1) . \'[/url]\''
);
$brackets = (strpos($in, '[') !== false) && (strpos($in, ']') !== false);
if ($brackets) {
$b_search = array(
'~\[code](.*?)\[/code]~ise',
'~\[php](.*?)\[/php]~ise',
'~\[php=([0-9]+?)](.*?)\[/php]~ise',
'~\[img](http|https|ftp)://(.*?)\[/img]~ise',
'~\[url](.*?)\[/url]~ise',
'~\[url=(http|https|ftp)://(.+?)](.+?)\[/url]~ise'
);
$b_replace = array(
'\'[code]\' . function (array $matches){ return base64_encode(\'\\1\') . \'[/code]\'',
'\'[php]\' . base64_encode(\'\\1\') . \'[/php]\'',
'\'[php=\\1]\' . base64_encode(\'\\2\') . \'[/php]\'',
'\'[img]\' . wordwrap(\'\\1://\\2\', 1, \' \', 1) . \'[/img]\'',
'\'[url]\' . wordwrap(\'\\1\\2\', 1, \' \', 1) . \'[/url]\'',
'\'[url=\' . wordwrap(\'\\1://\\2\', 1, \' \', 1) . \']\\3[/url]\''
);
$search = array_merge($search, $b_search);
$replace = array_merge($replace, $b_replace);
error_log(print_r($replace));
}
$in = preg_replace($search, $replace, $in);
$brackets = (strpos($in, '[') !== false) && (strpos($in, ']') !== false); //We may have auto-parsed a URL, adding a bracket
}
$strtr = array();
if ($options & FORMAT_HTMLCHARS) {
$strtr['&'] = '&';
$strtr['"'] = '"';
$strtr['\''] = ''';
$strtr['<'] = '<';
$strtr['>'] = '>';
}
if ($options & FORMAT_BREAKS) {
$strtr["\n"] = "<br />\n";
}
if ($this->user['user_view_emoticons'] && ($options & FORMAT_EMOTICONS)) {
if (!$this->replaces_loaded) {
$this->get_replaces();
}
$strtr = array_merge($strtr, $this->emotes['replacement']);
}
$in = strtr($in, $strtr);
if (($options & FORMAT_MBCODE) && $brackets) {
$search = array(
'~\[(/)?([bi])]~i',
'~\[u]~i',
'~\[s]~i',
'~\[/[us]]~i',
'~\[url](h t t p|h t t p s|f t p) : / /(.+?)\[/url]~ise',
'~\[url=(h t t p|h t t p s|f t p) : / /(.+?)](.+?)\[/url]~ise',
'~\[email]([a-z0-9-_.]+#[a-z0-9-.]+\.[a-z0-9-_.]+)?\[/email]~i',
'~\[email=([^<]+?)](.*?)\[/email]~i',
'~\[img](h t t p|h t t p s|f t p) : / /(.*?)\[/img]~ise',
'~\[(right|center)](.*?)\[/\1]~is',
'~\[code](.*?)\[/code]~ise',
'~\[php](.*?)\[/php]~ise',
'~\[php=([0-9]+?)](.*?)\[/php]~ise',
'~\[color=(\S+?)](.*?)\[/color]~is',
'~\[font=(.+?)](.*?)\[/font]~is',
'~\[size=([0-9]+?)](.*?)\[/size]~is'
);
$replace = array(
'<\\1\\2>',
'<span style=\'text-decoration:underline\'>',
'<span style=\'text-decoration:line-through\'>',
'</span>',
'\'\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'\'',
'\'\\3\'',
'\\1',
'\\2',
'\'<img src="\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'" alt="\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'" />\'',
'<div align="\\1">\\2</div>',
'$this->format_code(\'\\1\', 0)',
'$this->format_code(\'\\1\', 1)',
'$this->format_code(\'\\2\', 1, \'\\1\')',
'<span style=\'color:\\1\'>\\2</span>',
'<span style=\'font-family:\\1\'>\\2</span>',
'<span style=\'font-size:\\1ex\'>\\2</span>'
);
if ((substr_count($in, '[quote]') + substr_count($in, '[quote=')) == substr_count($in, '[/quote]')) {
$search[] = '~\[quote=(.+?)]~i';
$search[] = '~\[quote]~i';
$search[] = '~\[/quote]~i';
$replace[] = '<table style="width:90%; margin-left:5%; margin-right:5%;" border="0" cellpadding="3" cellspacing="0"><tr><td><b>\\1 ' . $this->lang->main_said . ':</b></td></tr><tr><td class="quote">';
$replace[] = '<table style="width:90%; margin-left:5%; margin-right:5%;" border="0" cellpadding="3" cellspacing="0"><tr><td><b>' . $this->lang->main_quote . ':</b></td></tr><tr><td class="quote">';
$replace[] = '</td></tr></table>';
}
$in = preg_replace_callback($search, $replace, $in);
$in = str_replace(array(' ', "\t", '&#'), array(' ', ' ', '&#'), $in);
}
return $in;
}
I tested trying to place an anonymous functions directly into the replacement arrays but was served the error: Object of class Closure could not be converted to string. But perhaps I may have gone about it incorrectly?
$replace = array(
'\\1[email]\\2[/email]',
"'\'\\1[url]\'" . function (array $matches) {return wordwrap($matches[1], $matches[2], $matches[3], $matches[4]); } . " \'[/url]\''"
);
Advice would be much appreciated.
Create an associative array where the keys contain regex patterns and the values contain the callbacks (no prepending/appending strings to the callbacks).
I am not going to rewrite that behemoth from my phone, so I'll demonstrate a single replacement.
Feed your array of patterns and callbacks to preg_replace_callback_array().
Code: (Demo)
$patternCallbacks = [
'~\[code](.*?)\[/code]~is' =>
function($m) {
return '[code]' . base64_encode($m[1]) . '[/code]';
},
// add more elements as needed...
];
echo preg_replace_callback_array(
$patternCallbacks,
'This is my [code]script[/code] to display'
);
Output:
This is my [code]c2NyaXB0[/code] to display
Edit, since you cannot use preg_replace_callback_array(), you will need to make iterated calls of preg_replace_callback().
Code: (Demo)
$patternCallbacks = [
'~\[code](.*?)\[/code]~is' =>
function($m) {
return '[code]' . base64_encode($m[1]) . '[/code]';
},
'~\[php(?:=\d+)?]\K(.*?)\[/php]~is' =>
function($m) {
return base64_encode($m[1]) . '[/php]';
},
];
$text = <<<TEXT
This is my [code]script[/code] to display.
It has [php]unnumbered tag
code[/php] and [php=8]numbered tag code[/php].'
TEXT;
foreach ($patternCallbacks as $pattern => $callback) {
$text = preg_replace_callback($pattern, $callback, $text);
}
echo $text;
Output:
This is my [code]c2NyaXB0[/code] to display.
It has [php]dW5udW1iZXJlZCB0YWcKIGNvZGU=[/php] and [php=8]bnVtYmVyZWQgdGFnIGNvZGU=[/php].
When I type about three keywords or more it seems to only search the last keyword i.e sydney+region+nsw it will only search nsw.
I want it to search multiple keywords or the complete search term when inputted.
This is the code:
if($_REQUEST['searchkey']!="" && $_REQUEST['searchkey']=="search_record"){
//Remove any html/javascript.
$keyword = secureValue($_REQUEST['keyword']);
$cat_id = intval($_REQUEST['cat_level_root']);
$subcat_id = intval($_REQUEST['cat_level_one']);
$sub_subcat_id = intval($_REQUEST['cat_level_two']);
$stateId = intval($_REQUEST['classi_state']);
$hometownId = intval($_REQUEST['classi_zipcode']);
$servicesId = intval($_REQUEST['classified_desc9']);
$cityId = intval($_REQUEST['classi_city']);
$priceId = intval($_REQUEST['classified_title9']);
$ad_key = intval($_REQUEST['ad_id']);
$types = array();
$types_x = explode(" ",$keyword);
$keyword = trim($_REQUEST['keyword']);
foreach($types_x as $keyword) {
$x++;
if($x==0)
$types[]=($keyword!="" && $keyword!="Enter Your Keywords..") ? " " : "";
}
$types=implode($types);
$columns = "SELECT SQL_CALC_FOUND_ROWS * ";
$sql = " FROM tbl_classified
WHERE clsd_sub_subcat_id=1395 AND CONCAT(classified_title, ' ',
classified_desc, ' ', classified_type6, ' ', classified_title2, ' ",
classified_type, ' ', classified_type2, ' ', classified_type3, ' ',
classified_desc3, ' ', classified_type5) LIKE '%$keyword%'
and classified_status='Active'
and paid_status!='Pending'
ORDER BY classified_post_date,classified_featured asc $types";
$sql = $columns.$sql;
$rs_classi=db_query($sql);
$res_classi = mysql_fetch_array(db_query("Select FOUND_ROWS() as total"));
$reccnt=$res_classi['total'];
}
You explode the keyword string with spaces. $types_x = explode(" ",$keyword);
Explode with + (eg. explode("+", $keyword)) or use urldecode before explode.
I am trying a "Keyword" search. I am looking in the fields ARTWORK_title and ARTWORK_keywords. The ARTWORK_keywords field is where the user can enter multiple tags to search on.
I have built a query up and feel this is the right way, But I am just not getting ARTWORK_title passed back through in the DB Query.
My PHP Function is as follows....
$my_keywords = explode(",", $search_string);
$searchfields = array('ARTWORK_title', 'ARTWORK_keywords');
$this->db->select('*');
$this->db->from('artwork');
$this->db->where('ARTWORK_status', '1');
//$where_string = '(';
foreach($my_keywords as $keyword)
{
foreach($searchfields as $field)
{
$where_string = $field . ' LIKE \'%' . $keyword . '%\' ';
}
//$where_string .= substr($where_string, 4) . ')';
$this->db->where($where_string);
}
However when profiling the SQL Query I am getting the following MySQL Query back....
SELECT *
FROM (artwork)
WHERE ARTWORK_status = '1'
AND ARTWORK_keywords LIKE '%Blue%'
AND ARTWORK_keywords LIKE '%Orange%'
It is just not getting the ARTWORK_title field in the query at all.
Any ideas where I am going wrong?
Many Thanks in advance.
You are erasing the $where_string value with each iteration.
Modify it like this:
$where_string = '';
$counter = 0;
foreach($my_keywords as $keyword)
{
foreach($searchfields as $field)
{
if ($counter > 0) {
$where_string .= ' AND ';
}
$where_string .= $field . ' LIKE \'%' . $keyword . '%\' ';
$counter++;
}
}
I am creating a findSpellings function that has two parameters $word and $allWords. $allwords is an array that has mis-spellings of words that could sound similar to the $word variable. What I am trying to accomplish is to print out all words that are similar to the $word based on the soundex function. I am having trouble printing out the array with words. My function that I have is below. Any help would be greatly appreciated:
<?php
$word = 'stupid';
$allwords = array(
'stupid',
'stu and pid',
'hello',
'foobar',
'stpid',
'supid',
'stuuupid',
'sstuuupiiid',
);
function findSpellings($word, $allWords){
while(list($id, $str) = each($allwords)){
$soundex_code = soundex($str);
if (soundex($word) == $soundex_code){
//print '"' . $word . '" sounds like ' . $str;
return $word;
return $allwords;
}
else {
return false;
}
}
}
print_r(findSpellings($word, $allWords));
?>
if (soundex($word) == $soundex_code){
//print '"' . $word . '" sounds like ' . $str;
return $word;
return $allwords;
}
You can't have 2 returns, the first return will exit the code.
You could just do something like this:
if (soundex($word) == $soundex_code){
//print '"' . $word . '" sounds like ' . $str;
$array = array('word' => $word, 'allWords' => $allWords);
return $array;
}
And then just retrieve the values out of $array like so:
$filledArray = findSpellings($word, $allWords);
echo "You typed".$filledArray['word'][0]."<br/>";
echo "Were you looking for one of the following words?<br/>";
foreach($filledArray['allWords'] as $value)
{
echo $value;
}
I'm using a javascript plugin this is the line which I need help from u
<script type="text/javascript">
$('ul#news').newswidget({ source: ['http://rss.news.yahoo.com/rss/us', 'http://rss.news.yahoo.com/rss/world', 'http://feeds.bbci.co.uk/news/rss.xml'],
I would like to add URL data from MySQL
I'm using it with while loop like this
$('ul#news').newswidget({ source:[<?php
while($rssrow = mysql_fetch_array($rss))
{
echo "'"."$rssrow[rss_name]"."'".",";
}
?>],
It doesn't work properly :(.
I need to get like URL,URL,RUL like this.
that means no comma for the last one
any one please help me
You can actually do that pretty easily by a simple reorganization:
if($rssrow = mysql_fetch_array($rss))
{
echo "'".$rssrow['rss_name']."'";
while($rssrow = mysql_fetch_array($rss))
{
// note no quotes -- they are redundant
// prepend the comma
echo ","."'".$rssrow['rss_name']."'";
}
}
It does make for an extra step for the reader, but it does have the benefit of not needing substring, a new array, or a flag.
You could just build the string and remove the last comma:
$result = '';
while($rssrow = mysql_fetch_array($rss))
{
$result .= "'"."$rssrow[rss_name]"."'".",";
}
echo ($result != '') ? substr($result, 0, -1) : "''";
OR use implode():
$result = array();
while($rssrow = mysql_fetch_array($rss))
{
$result[] = $rssrow[rss_name];
}
echo "'" . implode($result, "','") . "'";
(both of these methods will output '' if the result set is empty.)
$urls = "";
while($rssrow = mysql_fetch_array($rss))
{
$urls.= "'$rssrow[rss_name]',";
}
echo substr($urls, 0, -1);
I wonder why no comment points out that you should definitely escape your output. If an entry contains a ', all solutions aside from Dmitry F’s first will break badly.
$('ul#news').newswidget({ source:[<?php
$arr = array();
while($rssrow = mysql_fetch_array($rss))
{
$arr[] = '"' . str_replace('"', '\"', $rssrow['rss_name']) . '"';
}
echo implode(',', $arr);
?>],
here is a little bit different approach:
<?php
$news = array(
'source' => array(
'http://example.com',
'http://example.com'
)
);
$news_json = json_encode($news);
?>
<script>
$('ul#news').newswidget(<?php echo $news_json; ?>);
</script>
another variation:
$url = array();
while($rssrow = mysql_fetch_array($rss))
{
$url[] = '"' . $rssrow['rss_name'] . '"';
}
echo implode(',', $url);