I have implemented searching using Query having LIKE clause with % wild cards on both side.
I have column having names of countries. If I search with P or PAK it shows result But If I search it with 'I live in Pakistan' it doesn't compare.
The thing I understand is it matches with the sub string.
Is it possible to make its vice versa like I pass the string 'I live in Pakistan' and it matches with characters in fields and gets the result of Pakistan.
Instant help would be appreciated.
you could use the like() function from codeigniter framework.
$this->db->like();
This function enables you to generate LIKE clauses, useful for doing searches.
Note: All values passed to this function are escaped automatically.
Simple key/value method:
$this->db->like('title', 'match');
// Produces: WHERE title LIKE '%match%'
If you use multiple function calls they will be chained together with AND between them:
$this->db->like('title', 'match');
$this->db->like('body', 'match');
// WHERE title LIKE '%match%' AND body LIKE '%match%
If you want to control where the wildcard (%) is placed, you can use an optional third argument. Your options are 'before', 'after' and 'both' (which is the default).
$this->db->like('title', 'match', 'before');
// Produces: WHERE title LIKE '%match'
$this->db->like('title', 'match', 'after');
// Produces: WHERE title LIKE 'match%'
$this->db->like('title', 'match', 'both');
// Produces: WHERE title LIKE '%match%'
If you do not want to use the wildcard (%) you can pass to the optional third argument the option 'none'.
$this->db->like('title', 'match', 'none');
// Produces: WHERE title LIKE 'match'
See This
I think what you Need is to search and compare for every word in the provided text, i think this will be helpfull.
$temp = array();
$str = array();
$str = explode(' ', $string);
foreach ( $str as $word) {
if (strlen($word) > 2) {
$this->db->or_like('country_name', $word, 'both');
} else {
continue;
}
}
$countries = $this->db->get('countries');
i think in $countries you will have all the needed result.
You could replace the whitespaces with commas, and then use find_in_set. Assuming your string is $str, consider this query:
SELECT *
FROM countries c
WHERE c.name LIKE '%$str%' OR
FIND_IN_SET(c.name, REPLACE($str, ' ', ',')) > 0
Try this
public function searchCountry($value)
{
$value = $value;
$query = $this->db->query("SELECT * FROM table_name WHERE country LIKE '%$value%' ");
$result = $query->result_array();
return $result;
}
This could work (disclaimer: not tested):
public function searchCountry($value)
{
$sql = "SELECT DISTINCT FROM `countries`";
$value = explode(' ', $value);// use all words from query
$first_match = FALSE;
foreach ($value as $k => $v)
{
if (strlen($v) >= 3)// exclude 1 and 2 letter words if want
{
if ( ! $first_match)
{
$sql .= " WHERE `name` LIKE %$v%";
}
else
{
$sql .= " OR `name` LIKE %$v%";
}
}
}
$sql .= " LIMIT 50";
$query = $this->db->query($sql);
$result = $query->result_array();
return $result;
}
but you probably should use #Mureinik solution.
You can use a regular expression trick for this purpose:
where country regexp replace($str, ' ', '|')
This constructs the expression:
where country regexp 'I|live|in|Pakistan'
which the evaluates to true because of the rules for regular expressions.
Related
I am carrying out a little experiment, appending the string JERRY to every sql keyword in the sql statement by checking from an array of SQL keywords which I specify. I want to remove the string JERRY from the search variable, so that if I typed a' UNION (SELECT 1, fname, username, password FROM users);-- in the search input field, the printed sql statement should look like this;
SELECTJERRY * FROMJERRY shopping WHEREJERRY title LIKEJERRY '%a' UNION (SELECT 1, fname, username, password FROM users);-- %'
The goal is that I don't want the SQL Keywords in the input search variable to have the string JERRY.
BUT right now, this is what I get;
SELECTJERRY * FROMJERRY shopping WHEREJERRY title LIKEJERRY '%a' UNIONJERRY (SELECT 1, fname, username, password FROMJERRY users);-- %'
How can i achieve this?
$search = $_GET['search'];
if (empty($search)) {
echo "Please fill in the search bar";
exit();
}
$keywords = ["SELECT", "FROM", "WHERE", "LIKE", "AND", "OR", "ON","UNION", "JOIN"];
$sql = "SELECT * FROM shopping WHERE title LIKE '%$search%'";
$splittedSql = explode(" ", $sql);
foreach ($splittedSql as $sl) {
if (in_array($sl, $keywords)) {
$newstatement = $sl . "JERRY" . ' ';
} else {
$newstatement = $sl . ' ';
}
echo $newstatement;
}
The issue is that you're checking your static query with a user supplied $search value included in it. Achieving your desired results would require a limit on the keyword replacements.
One approach would be to first check the user supplied $search value for the specified keywords, If it exists, alter your static query. Then you can apply the user supplied $search value after-the-fact, which can be accomplished easily using sprintf.
Instead of exploding the query, you can use preg_replace to apply the keyword values all at once, using a capture group () and replacement value of $1JERRY.
You can use word boundaries \b on the pattern to avoid false positives on words like sAND, tON,lORe, etc.
Lastly using stripos to check the $search value as opposed to in_array() and the /i regex modifier, will allow the $keyword matching and replacements to be case-insensitive.
Approach 1: https://3v4l.org/ie2Mj
$search = 'a\' UNION (SELECT 1, fname, username, password FROM users);--';
$keywords = ["SELECT", "FROM", "WHERE", "LIKE", "AND", "OR", "ON","UNION", "JOIN"];
//sprintf requires textual percent signs to be escaped as %%
$query = 'SELECT * FROM shopping WHERE title LIKE \'%%%s%%\'';
foreach ($keywords as $w) {
if (false !== stripos($search, $w)) {
//found a keyword build the replacement capture groups.
$patterns = '/\b(' . implode('|', $keywords) . ')\b/i';
$query = preg_replace($patterns, '$1JERRY', $query);
break;
}
}
printf($query, $search);
An alternative to iterating over the $keywords would be to use preg_match to determine if the $search value contains a keyword value.
Approach 2: https://3v4l.org/iVbBc
$search = 'a\' UNION (SELECT 1, fname, username, password FROM users);--';
$keywords = ["SELECT", "FROM", "WHERE", "LIKE", "AND", "OR", "ON","UNION", "JOIN"];
$patterns = '/\b(' . implode('|', $keywords) . ')\b/i';
$query = 'SELECT * FROM shopping WHERE title LIKE \'%%%s%%\'';
if (preg_match($patterns, $search)) {
$query = preg_replace($patterns, '$1JERRY', $query);
}
printf($query, $search);
Results for both approaches:
SELECTJERRY * FROMJERRY shopping WHEREJERRY title LIKEJERRY '%a' UNION (SELECT 1, fname, username, password FROM users);--%'
Since $search will be affected by explode , using whitespace, we can prevent this by replacing whitespaces with unique characters:
$search = str_replace(" ","uniquecharacters",$search);
and then replace those unique characters back with white space/s
$keywords = ["SELECT", "FROM", "WHERE", "LIKE", "AND", "OR", "ON","UNION", "JOIN"];
$search = str_replace(" ","uniquecharacters",$search);
$sql = "SELECT * FROM shopping WHERE title LIKE '%$search%'";
$splittedSql = explode(" ", $sql);
foreach ($splittedSql as $sl) {
if (in_array($sl, $keywords)) {
$newstatement = $sl . "JERRY" . ' ';
} else {
$newstatement = str_replace("uniquecharacters"," ",$sl);
$newstatement = $sl . ' ';
}
echo $newstatement;
}
I have Chinese php search queries.
I want to split up any query up into individual characters.
ex: 你好 (ni hao, hello) split into 你 and 好
my query is set like:
$q = $_REQUEST["q"];
the results I want to split is set up like:
$results4 = $db->query( "SELECT CHS, PIN, DEF FROM FOUR
WHERE CHS LIKE '%".$q."%' OR PIN LIKE '%".$q."%'");
while ($row4 = $results4->fetchArray()) {
How can I split up the keyword and look up all the components?
If you want it all in one query you will have to generate the whole query. If you were looking for an exact match you could use something similar to the in_array() function, but with LIKE it doesn't work.
You could however loop through the array of characters and put together the WHERE part programatically.
Like this
$where = array();
foreach ( $qtwo as $word ) {
$where[] = "CHS LIKE '%" . $word . "%'";
}
$where = implode(' OR ', $where);
Use this $where variable in your query
You can use str_split to convert a string in an array of chars
$chars = str_split($q)
In my MySQL database I have this table which contains multiple artists. They are placed in a field called formated_name and returns strings like for example Lady Gaga, so far so good. What I want to achieve is that it returns ladygaga so I can use it for my url later on. My whole function looks like this:
public function artistname_get($artist_id)
{
$this->load->database();
$sql = "SELECT formated_name FROM artists WHERE artist_id = '".$artist_id."'";
$query = $this->db->query($sql);
$data = $query->result();
if($data) {
$this->response($data, 200);
} else {
$this->response(array('error' => 'Couldn\'t find any artist with that name!'), 404);
}
}
So how can I achieve this?
Try out this simple way.
To remove spaces in string.
By using PHP
$string = 'Lady Ga ga';
$value=str_replace(' ','',$string);
echo strtolower($value);
By using MySQL
$sql = "SELECT REPLACE( formated_name, " ", "" ) FROM artists WHERE artist_id = '".$artist_id."'";
Mysql offers string function for this as well if you do not want to do it with php.
ToLower function:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_lower
Replace to replace spaces:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_replace
But you should additionally use something for url_encode and url_decode within php. Otherwise you may experiance problems with artists like "A & B"
Use
str_replace() and `strtolower()`
to remove space and to convert string to lowercase.
PHP version:
$string = strtolower(str_replace(' ', '', $string));
$artist_url = strtolower(str_replace(' ', '', $artist_formatted_name));
$string = strtolower(str_replace(' ', '', $string));
Try this,
SELECT LOWER(REPLACE(formated_name, ' ', '')) AS formated_name
You have to do is Just use mysql functions LOWER and REPLACE together to get rid of space and capital letters
Try Something like this.....
<?php
$string = 'Lady Gaga';
$value=str_replace(' ','',$string);
echo strtolower($value);
?>
If you want to put it in URL you should clear also from special characters etc.
Use this function to convert string into alias.
function toAlias ($string) {
return strtolower (preg_replace('/[^A-Za-z0-9\-]/', '', str_replace(' ', '-', $string)));
}
I am trying to do a search query to see if a textarea contains some keywords. I'm having a bit of trouble though plugging my textarea's values into the query.
This is my query:
$match = $this->input->post('wStory');
$this->db->where("`terms` LIKE '%$match%'");
$query = $this->db->get('filter_tbl');
return $query->num_rows();
The $match is my text field and what I have been trying to do is split up the words inside and then run through each individual word. I have tried using PHPs' explode() function which sort of works, but in this case it doesn't work because it turns the string into an array.
Is there any way I can split up the strings in my textarea to just words and run through the words in the like statement, Or is there just something I'm missing?
The query you're currently running is doing a check for a specific phrase, rather than checking for any of the specified words.
You need to do the following:
$match = $this->input->post('wStory');
// break search phrase into keywords
$keywords = explode(' ', $match);
// Build query
foreach ($keywords as $keyword)
{
$keyword = trim($keyword);
$this->db->or_where("`terms` LIKE '%$keyword%'");
}
$query = $this->db->get('filter_tbl');
return $query->num_rows();
The explode(' ', $match) does not take into account any punctuation that might separate words.
Isn't there a $this->db->like("terms", $match); method?
See http://ellislab.com/codeigniter/user-guide/database/active_record.html#like
I think fulltext search is the way to go. The url Rob W posted also gives this:
$this->db->where('MATCH (field) AGAINST ("value")', NULL, FALSE);
which in you care would be something like
$this->db->where('MATCH (terms) AGAINST ("$match")', NULL, FALSE);
Edit: After reading some further, this might be better (or atleast better readable):
$this->db->where('MATCH (terms) AGAINST ("$match")');
Try this:
$match = $this->input->post('wStory');
//Getting words from textarea and put them into array
$wordsArray = explode(' ',$match);
if (!empty($wordsArray)) {
//use where_in() instead of where()
$this->db->where_in("`terms`", $wordsArray);
$query = $this->db->get('filter_tbl');
return $query->num_rows();
}
The search query is:
"product1 prod2 prod4"
I need to make the mysql
SELECT *
FROM tableprod
WHERE (prod LIKE '%product1%'
AND prod LIKE '%prod2%'
AND prod LIKE '%prod4%')
using the mysql_real_escape_string for the input query...
Simple string manipulation:
$terms = explode(' ', $search);
$bits = array();
foreach ($terms as $term) {
$bits[] = "prod LIKE '%".mysql_real_escape_string($term)."%'";
}
$query = "SELECT * FROM tableprod WHERE (".implode(' AND ', $bits).")";
If you can meet the constraints, you migh be better off just using a FULLTEXT index which would save you the trouble of having to split the string, plus you'd get the bonus of being able to use basic boolean operators for the search (and/or/not)
without a loop(i've always tried to avoid loops):
$str = "product1 prod2 prod4";
$sql = "select * from tableprod where (prod like '%" . str_replace( ' ', '%\' AND prod LIKE \'%', $str ) . '%\')';
if it's possible you will have more than one space inbetween items use preg_replace