zend conversion between query and DB_Select - php

so I'm using this program http://code.google.com/p/ecartcommerce/source/browse/library/Ecart/Db/Table/Select/Disassemble.php?edit=1 to generate a string that corresponds to the zend db select command for creating that query..
but the thing screws up when I use an IN() statement in WHERE
so suppose I have
"SELECT * FROM j WHERE id IN (1,2,3,5,6)";
and I convert this using that class,
when I inspected the output, it stripped out the parentheses between the numbers in the IN clause, so it became
->where("id IN 1,2,3,4,5,6"), while it's supposed to be ->where("id IN (1,2,3,4,5,6)")
Anyone knows how to fix this?
I suspect it has something to do with the _addWhere method:
protected function _addWhere($where)
{
$result = '';
$where = 'AND ' . $where;
$replacement = true;
while ($replacement) {
$replacement = false;
$parts = preg_split(
'/(\(.+\)+)/U', $where, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
);
foreach ($parts as $part) {
if (!preg_match('/\(.+?\)/', $part)) {
continue;
}
if (strstr($part, ' AND ') || strstr($part, ' OR ')) {
continue;
}
$replacement = preg_replace('/^\s*\((.+)\)\s*$/', '$1', $part);
$where = str_replace($part, $replacement, $where);
}
}
$parts = preg_split(
'/(\(.*\))/U', $where, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
);
foreach ($parts as $part) {
if (preg_match('/^\(.*\)$/', $part)) {
$replacement = str_replace(
array('AND', 'OR'), array('AND--', 'OR--'), $part
);
$where = str_replace($part, $replacement, $where);
}
}
$parts = preg_split(
'/(AND|OR)\s/', $where, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
);
$type = 'where';
for ($i = 0 ; $i < count($parts) ; $i++) {
if ('OR' == $parts[$i]) {
$type = 'orWhere';
} else {
$type = 'where';
}
// $subQuery = str_replace('--', '', trim($parts[++$i],'() '));
$subQuery = preg_replace('/^\s*\((.+)\)\s*$/', '$1', $parts[++$i]);
$subQuery = str_replace('--', '', $subQuery);
$result .= "\r\t" . "->{$type}(\""
. $this->_replaceLongTableName(trim($subQuery)) . '")';
}
return $result;
}
It specifically screws up in the $replacement = preg_replace('/^\s*\((.+)\)\s*$/', '$1', $part); line...

To use IN parameter in where clause, try the following way
$i = array(1,2,3,4,5,6);
$select = $this->select()->from('table','*')->where('i = (?)',$i);
when the parameter for where is an array, Zend automatically splits by ","

Related

First word of a comma separated sentence php

My string is : Hi my, name is abc
I would like to output "Hi Name".
[Basically first word of comma separated sentences].
However sometimes my sentence can also be Hi my, "name is, abc"
[If the sentence itself has a comma then the sentence is enclosed with ""].
My output in this case should also be "Hi Name".
So Far I've done this
$str = "hi my,name is abc";
$result = explode(',',$str); //parsing with , as delimiter
foreach ($result as $results) {
$x = explode(' ',$results); // parsing with " " as delimiter
forach($x as $y){}
}
You can use explode to achieve YOUR RESULT and for IGINORE ' OR " use trim
$str = 'hi my,"name is abc"';
$result = explode(',',$str); //parsing with , as delimiter
$first = explode(' ',$result[0]);
$first = $first[0];
$second = explode(' ',$result[1]);
$second = trim($second[0],"'\"");
$op = $first." ".$second;
echo ucwords($op);
EDIT or if you want it for all , separated values use foreach
$str = 'hi my,"name is abc"';
$result = explode(',',$str); //parsing with , as delimiter
$op = "";
foreach($result as $value)
{
$tmp = explode(' ',$value);
$op .= trim($tmp[0],"'\"")." ";
}
$op = rtrim($op);
echo ucwords($op);
Basically it's hard to resolve this issue using explode, str_pos, etc. In this case you should use state machine approach.
<?php
function getFirstWords($str)
{
$state = '';
$parts = [];
$buf = '';
for ($i = 0; $i < strlen($str); $i++) {
$char = $str[$i];
if ($char == '"') {
$state = $state == '' ? '"' : '';
continue;
}
if ($state == '' && $char == ',') {
$_ = explode(' ', trim($buf));
$parts[] = ucfirst(reset($_));
$buf = '';
continue;
}
$buf .= $char;
}
if ($buf != '') {
$_ = explode(' ', trim($buf));
$parts[] = ucfirst(reset($_));
}
return implode(' ', $parts);
}
foreach (['Hi my, "name is, abc"', 'Hi my, name is abc'] as $str) {
echo getFirstWords($str), PHP_EOL;
}
It will output Hi Name twice
Demo

Regex for route matching in PHP

I am working on my mini url router in PHP. So far I've got regex for extracting variables in the url enclosed in {}(By looking at Symfony's router code) :
public function parse($pattern)
{
$matches = '';
$variables = array();
$pos = 0;
preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
foreach ($matches as $match)
{
$varName = substr($match[0][0], 1, -1);
if(is_numeric($varName)) {
throw new Exception('Argument cannot be a number');
}
if (in_array($varName, $variables)) {
throw new \LogicException(sprintf('More then one occurrence of variable name "%s".', $varName));
}
$variables[] = $varName;
}
return ['variables' => $variables];
}
So this method extracts the vars, now I need a regex to match the pattern of the route with the url. I started learning about regexes, but I still am not that good to wrap my head around this.
This will work: \/hello\/{?([^\/}]+)}?
(At least it does on the examples you provided:)
/hello/{name}
/hello/Sam
Explanation
\/ is an escaped /
hello finds hello, in case you didn't realize.
{? finds a {, if there is one.
([^\/}]+) finds everything that's not a / or }
}? finds a }, if there is one.
For anyone that might be interested, I got it, thanks to Laurel's answer.
This is the updated version of the method it still needs some work though :
$matches = '';
$variables = array();
$pos = 0;
$reg = '#';
$nextText = '';
preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
foreach ($matches as $match)
{
$varName = substr($match[0][0], 1, -1);
$precedingText = substr($pattern, $pos, $match[0][1] - $pos);
$pos = $match[0][1] + strlen($match[0][0]);
$nxt = $pos - strlen($pattern);
if($nxt == 0) $nxt = strlen($pattern);
$nextText = substr($pattern, $nxt);
//$precedingText = substr($precedingText, 1, -1);
$precSegments = explode('/', $precedingText);
$precSegments = array_splice($precSegments, 1);
//$temp = 5;
echo 'nxt ' . $nextText . '<><br>';
if(strlen($precedingText) > 1)
{
foreach($precSegments as $key => $value)
{
$reg .= '\/';
$reg .= $value;
}
$reg .= '{?([^\/}]+)}?';
}
else
{
$reg .= '{?([^\/}]+)}?';
}
$nextText = str_replace('/', '\/', $nextText);
if(is_numeric($varName)) {
throw new Exception('Argument cannot be a number');
}
if (in_array($varName, $variables)) {
throw new \LogicException(sprintf('More then one occurrence of variable name "%s".', $varName));
}
$variables[] = $varName;
}
if(count($matches) < 1)
{
$reg .= str_replace('/', '\/', $pattern);
}
$reg = $reg . $nextText;
$reg .= '#';
if($pattern == '/')
{
$reg = '#^[\/]+$#';
}
return ['variables' => $variables, 'regex' => $reg];

PHP how to find uppercase in array

I have an array with many words, but some senteces are in uppercase. For example:
THIS SENTENCE IS UPPERCASE
this sentece is in lowercase
And I want to split this two sentences by \r\n, but I cant find how to do it
Here is how I retrive this array:
$result_pk_info = array();
while ($row = odbc_fetch_array($sql_pk_info))
{
$opisanie = iconv("cp1257", "UTF-8", trim($row['opis']));
$id = iconv("cp1257", "UTF-8", trim($row['pacientid']));
$date = iconv("cp1257", "UTF-8", trim($row['data']));
$desc = explode('##$', $opisanie);
$all_info = "<tr><td>".$desc[1]."</td></tr>";
$result_pk_info[] = $all_info;
}
in $desc I have words array in which I want to search and split uppercase and lowercase.
So can anyone help me with it?
UPD the text which I have hase something like this structure:
SENTENCE IN UPPERCASE Sentece in lower case
This function is what you're looking for :
function split_upper_lower ($string)
{
$words = explode (' ', $string);
$i = 0;
foreach ($words as $word)
{
if (ctype_upper ($word))
$new_string_array[++$i]['type'] = 'UPPER';
else
$new_string_array[++$i]['type'] = 'LOWER';
$new_string_array[$i]['word'] = $word;
}
$new_string = '';
foreach ($new_string_array as $key => $new_word)
{
if (!isset ($current_mode))
{
if (ctype_upper ($new_word))
$current_mode = 'UPPER';
else
$current_mode = 'LOWER';
}
if ($new_word['type'] === $current_mode)
{
$new_string .= $new_word['word'];
if (isset ($new_string_array[$key + 1]))
$new_string .= ' ';
}
else
{
$new_string .= "\r\n" . $new_word['word'];
if (isset ($new_string_array[$key + 1]))
$new_string .= ' ';
if ($current_mode === 'UPPER') $current_mode = 'LOWER';
else $current_mode = 'UPPER';
}
}
return $new_string;
}
Tested it with br :
$string = 'HI how ARE you doing ?';
echo split_upper_lower ($string);
Output :
HI
how
ARE
you doing ?
Use preg_match: http://php.net/manual/en/function.preg-match.php
$string = 'THIS SENTENCE IS UPPERCASE';
$string2 = 'this sentece is in lowercase';
if(preg_match ( '/[A-Z ]$/' , $string))
{
echo 'uppercase';
}
else
{
echo 'lowercase';
}
Use this in your loop through $desc. Where $string is one element of an array containing one string.
/[A-Z ]$/ will match all uppercase with spaces. You can just upgrade your regexp to grab something else from strings.
If I understood your question you can do like this ...
$desc = array ("abcd","ABCD","bbb","B");
foreach($desc as $value) {
if(ctype_upper($value)) {
// character is upper
} else {
// character is lower
}
}
This can be done using preg_match_all(). Use the following code,
$result_pk_info = array();
while ($row = odbc_fetch_array($sql_pk_info))
{
$opisanie = iconv("cp1257", "UTF-8", trim($row['opis']));
$id = iconv("cp1257", "UTF-8", trim($row['pacientid']));
$date = iconv("cp1257", "UTF-8", trim($row['data']));
$desc = explode('##$', $opisanie);
//converting $desc array to string
$string = implode(" " , $desc);
//Upper case Matching
$upprCase = preg_match_all('/[A-Z]/', $string, $uprmatches, PREG_OFFSET_CAPTURE);
if($upprCase){
foreach ($uprmatches as $match)
{
foreach($match as $value)
//Iam a uppercase
print $UpperCase = $value[0];
}}
//Splitting with \r\n
print "\r\n";
//lower case matching
$lowrCase = preg_match_all('/[a-z]/', $string, $lowrmatches, PREG_OFFSET_CAPTURE);
if($lowrCase){
foreach ($lowrmatches as $match)
{
foreach($match as $value)
//Iam a lowercase
print $lowerCase = $value[0];
}}
}

how to highlight search results

hello i have a search function in that i will search a db for keywords. i would like to highlight the keywords and found a second function that i would like to implement into my search function.
so i have this code for the search:
<?php
function searchText($keywords){
global $db;
$returned_results = array();
$where2 = "";
$keywords = preg_split('/[\s]+/', $keywords);
$total_keywords = count($keywords);
foreach ($keywords as $key=>$keyword){
$where2 .= "`column` LIKE '%$keyword%'";
if ($key != ($total_keywords - 1)){
$where2 .= " OR ";
}
}
$results_text = "SELECT `a`, `b`, LEFT(`c`, 150) as `c` FROM `table` WHERE $where2";
$results_num_text = ($query2 = mysqli_query($db, $results_text)) ? mysqli_num_rows($query2) : 0;
if ($results_num_text === 0){
return false;
} else {
while ($row = mysqli_fetch_assoc($query2)){
$returned_results[] = array(
'ab' => $row['ab'],
'cd' => $row['cd'],
);
}
return $returned_results;
}
}
?>
and would like to implement a second function into it:
<?php
function mark_words ($text, $words, $colors = false)
{
if (!$colors || !is_array($colors) ) {
$colors = array('#ff9999', '#ffff99', '#ff99ff', '#99ffff','#99ff99');
}
$c = 0;
foreach ($words as $w) {
$w = preg_quote(trim($w));
if($w=='') {
continue;
}
$regexp = "/($w)(?![^<]+>)/i";
$replacement = '<b style="background-color:'.$colors[$c].'">\\1</b>';
$text = preg_replace ($regexp,$replacement ,$text);
$c++;
if ($c >= count($colors)) {
$c=0;
}
}
return $text;
}
$example = <<< EOT
some text is here inside
EOT;
$search = array('some','is', 'inside');
echo mark_words($example, $search);
?>
so i have this code that doesnt work:
<?php
function searchText($keywords, $colors = false){
global $db;
if (!$colors || !is_array($colors) ) {
$colors = array('#ff9999', '#ffff99', '#ff99ff', '#99ffff','#99ff99');
}
$c = 0;
$returned_results = array();
$where2 = "";
$keywords = preg_split('/[\s]+/', $keywords);
$total_keywords = count($keywords);
foreach ($keywords as $key=>$keyword){
$regexp = "/($w)(?![^<]+>)/i";
$replacement = '<b style="background-color:'.$colors[$c].'">\\1</b>';
$text = preg_replace($regexp,$replacement ,$keywords);
$c++;
if ($c >= count($colors)) {
$c=0;
}
$where2 .= "`b` LIKE '%$keyword%'";
if ($key != ($total_keywords - 1)){
$where2 .= " OR ";
}
}
$results_text = "SELECT `a`, LEFT(`b`, 150) as `b`, `c` FROM `table` WHERE $where2";
$results_num_text = ($query2 = mysqli_query($db, $results_text)) ? mysqli_num_rows($query2) : 0;
if ($results_num_text === 0){
return false;
} else {
while ($row = mysqli_fetch_assoc($query2)){
$returned_results[] = array(
'ab' => $row['a'],
'cd' => $row['b'],
);
}
return $returned_results;
$highlight = array($keywords);
echo mark_words($highlight);
}
}
?>
as i looked for it how to do so i found two possibilities. the first would be a function the second would be directly to highlight it from the select query:
SELECT
REPLACE(`col`, 'foobar', '<span class="highlight">foobar</span>') AS `formated_foobar`
FROM
…
WHERE
`col` LIKE "%foobar%"
so my question is how can i implement the second function into the search function or would it be better to use the second method?
if there is someone who could help me i really would appreciate. thanks a lot.
You shouldn't make it too hard for yourself. All you need it to replace every occurrence of a word with the word wrapped in the span with the required style applied. This should work for you:
function highlight_word( $content, $word, $color ) {
$replace = '<span style="background-color: ' . $color . ';">' . $word . '</span>'; // create replacement
$content = str_replace( $word, $replace, $content ); // replace content
return $content; // return highlighted data
}
function highlight_words( $content, $words, $colors ) {
$color_index = 0; // index of color (assuming it's an array)
// loop through words
foreach( $words as $word ) {
$content = highlight_word( $content, $word, $colors[$color_index] ); // highlight word
$color_index = ( $color_index + 1 ) % count( $colors ); // get next color index
}
return $content; // return highlighted data
}
// words to find
$words = array(
'normal',
'text'
);
// colors to use
$colors = array(
'#88ccff',
'#cc88ff'
);
// faking your results_text
$results_text = array(
array(
'ab' => 'AB #1',
'cd' => 'Some normal text with normal words isn\'t abnormal at all'
), array(
'ab' => 'AB #2',
'cd' => 'This is another text containing very normal content'
)
);
// loop through results (assuming $output1 is true)
foreach( $results_text as $result ) {
$result['cd'] = highlight_words( $result['cd'], $words, $colors );
echo '<fieldset><p>ab: ' . $result['ab'] . '<br />cd: ' . $result['cd'] . '</p></fieldset>';
}
Using Regular Expressions to replace content would do as well, though using str_replace() is a bit faster.
The functions accepts these arguments:
highlight_word( string, string, string );
highlight_words( string, array, array );
The above example results in:
By using str_ireplace instead of str_replace, the function will work case insensitive
I would not use the SQL method. As time goes on, and you have more and more highlighting rules, that will become unmanageable. Also trickier to handle the cases where you need to highlight foo differently to foobar, but one contains the other.
Separate your data handling from your formatting.

A function to only select the column names from a MYSQL update statment

I have a string (MYSQL update statment):
$string = "UPDATE myTable SET grade=99.9, name='moe', city='Taiz',pass_id=0202 where ID=99";
I want a PHP function to help me get the column names so the strings becomes like:
$columns = "grade,name,city,pass_id";
I tried using this code but didn't work, like expected:
$beginningPos = strpos($string, '=');
$endPos = strpos($string, ',');
$textToDelete = substr($string, $beginningPos, ($endPos + strlen($end)) - $beginningPos);
return str_replace($textToDelete, '', $string);
try this script
//use strtolower($string) if needed
$string = "UPDATE myTable SET grade=99.9, name='moe', city='Taiz',pass_id=0202 where ID=99";
if ( strpos($string, 'where') !== false){
$string = explode('where', $string);
unset($string[1]);
}
$exp = explode('=', $string[0]);
$columns = '';
foreach ( $exp as $e ) {
$res = str_replace(',', ' ', $e);
$res = explode(' ', $res);
$res = array_pop($res);
if ( $res)
$columns .= $res .',';
}
$columns = rtrim($columns, ',');
Output
string(23) "grade,name,city,pass_id"

Categories