I've got this code:
function searchMovie($query)
{
$this->db->where("film_name LIKE '%$query%'");
$movies = $this->db->get ("films", 40);
if($this->db->count > 0)
{
return $movies;
}
return false;
}
Javascript code from my submit form button strips all special characters like ; : ' / etc. from query string, and then redirects user to search uri (szukaj/query). So for example if film_name is Raj: wiara, and user searches for raj: wiara, the query looks like raj wiara and user doesn't get any results. I was thinking about exploding query into single words and then foreach word do a SELECT from db, but it would give multiple results of same movie. Don't want to change the javascript code, and I think I can't make that film names without the special characters like :.
Or maybe create another column in db for film_keywords and add there all words of movie separated by , or something and then search this column?
MySQL's Full Text Search functions are your friend here:
http://dev.mysql.com/doc/refman/5.7/en/fulltext-search.html
Will return a series of matches and give a score so you return in best-match order.
Warning: $this->db->where("film_name LIKE '%$query%'"); is open to SQL injection. Anyone can circumnavigate the JavaScript so you must always clean up input server-side. This is best done using the DB functions as well, not just stripping characters - so check whatever library you are using in order to do this.
You could indeed explode your string, using this answer's solution.
function searchMovie($query)
{
$queries = preg_split('/[^a-z0-9.\']+/i', $query);
foreach ($queries as $keyword){
$this->db->where("film_name LIKE '%$keyword%'");
}
$movies = $this->db->get ("films", 40);
if($this->db->count > 0)
{
return $movies;
}
return false;
}
This will create multiple ANDconditions for your db where, so the result will be filtered.
Related
I've got a database search field where I want the user to be able to input simple boolean logic and have that translated to a mySQL search string.
So for instance if the user inputs: (php AND mysql) OR ajax
I'd like to convert that to:
((c.Skillset LIKE '%php%' AND c.Skillset LIKE %mysql%) OR c.Skillset LIKE '%ajax%')
Is there a fairly simple way of doing this? I'm having particular trouble coming up with a solution for the brackets, if it wasn't for that it would be quite straightforward.
The following assumes you have some constant called SQL_PREFIX_STRING defined.
$string = '(php AND mysql) OR java';
preg_match_all('/[a-z]+/', $string, $skills); // puts the skills in an array
$skills = $skills[0]; // shift array to get the matching values
array_walk($skills, function (&$skill) {$skill = '%'.$skill.'%';}); // add wildcards to parameters
$query_string = preg_replace('/[a-z]+/', 'c.Skillset LIKE ?', $string); // create the ? parameters for the SQL string
$pdoStatement = $pdo->prepare(SQL_PREFIX_STRING.$sql); // prepare
$pdoStatement->execute($skills); // execute
I'm working on building a social network from HTML, PHP, and a MySQL database, and I cant figure how to make this PHP code to work. Please remember, I'm totally not a pro at PHP.
What I'm working on now is a function, atreplace($text), that has the preg_replace() function in it to find the # mentions in a post caption, comment, or wherever else I use it, to make them into clickable links. Now that's pretty easy, except the #mentions in the strings it would process are user id numbers instead of the user name. For example, a string in a post caption for my social network would look like this:
"Went to Disneyland with my friends #214432 and #163728 today.". But what the post caption originally said was this: "Went to Disneyland with my friends #billysmith and #hi_im_kelly today.".
I wrote the script (not included because it doesn't have to do with the question) that processes the post data and inserts it into the MySQL database to replace the # mentions to be the user number id of the user that was mentioned instead of the user name in situations where people would have changed their username, then it wouldn't have to edit peoples posts where they mentioned someone that changed their username.
Problem
When it uses the atreplace() function to echo out the post caption when someone is viewing their feed, of course it will echo out "#214432" and "#163728" (from the example above) in the post caption instead of "#billysmith" and "#hi_im_kelly", which I would expect, because a different php script edited it and changed the usernames that were mentioned to be the user id, which is a number.
This is what I want
I want to write a function like the one I have below (get_username($id)). I only included get_username($id) to show what I want to do. I dont really know a lot about how to use the preg_replace() function yet.
As you can see, I tried passing the $1, which would be the user number id that I want it to replace with the username, with the get_username('$1) function, but it doesn't work. (I know I used that $1 wrong somehow). Although in the get_username() function, when I try returning the $id, it does output the user number id right. But when I used the $id in the mysql_query(), it didn't even show up.
In case you didn't understand all that, first, I want to put the string that has the # mentions in it, into the atreplace() function. This function will find all the # user mentions, remember, they are the users number id. Then, it will put each mention into the get_username() function. That function will get the username from a mysql database where the id equals the user number id that the atreplace() function found, then it will return the username, and in the end, will replace the # mention...
Can someone please show me how I could change the get_username() function to make it work? Or just write a new one.
<?php
function get_username($id){
$undata = mysql_query("select `username` from `accounts` where `id`='$id';");
$un = mysql_fetch_assoc($undata);
return "<a href='#'>#".$un['username']."</a>";
}
function atreplace($text){
$replaced = preg_replace('/\#(\w+)/', get_username('$1'), $text);
return($replaced);
}
?>
regarding mysql_* being deprecated and using prepared statements along with preg_replace_callback:
$pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'localonly', 'localonly', array(
PDO::ATTR_EMULATE_PREPARES=>false,
PDO::MYSQL_ATTR_DIRECT_QUERY=>false,
PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION
));
...
function atreplace($text, $pdo) {
$stmt = $pdo->prepare('
SELECT
`username`
FROM
`so_profiles`
WHERE
`id`=?
');
$mesg = preg_replace_callback(
'/\#(\w+)/',
function ($match) use($stmt) {
$stmt->execute( array($match[1]) );
$users = $stmt->fetchAll(); // yes, there should be only one....
return empty($users) ? '[unknown user]' : $users[0];
},
$text
);
return $mesg;
}
In case anyone ever has that same problem, I got the answer thanks to #VolkerK
I just changed it to be one function:
function atreplace($text){
$mesg = preg_replace_callback('/\#(\w+)/',
function ($match){
$matchedit = preg_replace('/\#(\w+)/','$1', $match[0]);
$und = mysql_query("select `username` from `so_profiles` where `id`='".$matchedit."';");
$un = mysql_fetch_array($und);
return "<a>#".$un['username']."</a>";
},
$text);
return($mesg);
}
So let me give you some information, i have a blog system which is backed to a database, the database holds the title of the articles. Now i have tried to create a "related news" feature, and it is rather basic, it just takes the title of the existing page and splits it up like so (Note that $row_object_title is just the title pulled from the database):
$row_object_title_lower = strtolower($row_object_title);
$keywords = explode(" ",$row_object_title_lower);
I then run it through my function:
exclude_conjuctions($keywords);
code for that function(looks for certain words and removes it from the array:
function exclude_conjuctions($array){
global $keywords_new;
$keywords_new = $array;
$conjuctions = array("here","to","and","but","or","nor","for");
$counter = count($keywords_new);
foreach($conjuctions as $conjuction){
for($i=0;$i <= $counter;$i++){
if ($keywords_new[$i] == $conjuction){
unset($keywords_new[$i]);
}
}
}
return $keywords_new;
}
So now i will build my query to retreive all articles that have the keywords in the title:
$sql = '';
foreach ($keywords_new AS $keyword)
{
if ($sql != '')
$sql .= ' OR ';
$sql .= "object_title LIKE '%$keyword%'";
}
$squery = 'SELECT object_title FROM example_table WHERE '.$sql;
NOW. It seems to be working okay, but there are times when it returns a title which does not have the same words as the current article, so i investigated it and it seems it picks up parts of the word and returns it, which is of course not what we want, if you are confused take a look at this image:
http://puu.sh/7UhhW.jpg
Note how i search for "dow" and those letters are found in both the current title and the retrieved titles. Of course i need it to only return related articles that have the full words in the title, not part of the words. What am i doing wrong guys? maybe my MySQL query needs to be changed? maybe there is a better solution? would love some help.
This is a problem as you can imagine.
Thanks for the help in advance.
Try doing LIKE '% {$keyword} %'
Also your query is vulnerable for SQL Injections.
How can I prevent SQL injection in PHP?
EDIT : A better way to do this would be using a Regular Expression:
REGEXP '[[:<:]]{$keyword}[[:>:]]'
Instead of LIKE...
Try using the === operator instead of the == operator to compare strings. A good reason why can be found here
Also, you are wrapping your query with % on each side. That says to return all matches that CONTAIN those strings. Thus 'Dow' is contained in 'Down' and would be returned. You probably want to add a space around the %'s to only get matches that equal your keywords.
Could you implement the "LIKE" search to include a preceding and succeeding space? You would possibly need to have three conditions though to cater for words at the start and end of sentence:
$sql .= "object_title LIKE '% $keyword %' OR LIKE '$keyword %' OR LIKE '% $keyword'";
I have a database table containing some Permanent Texts which I will be outputting to my user interactions. The problem is that I need to change some parts of these Permanent Text answers when querying the Database.
For example this is one of the responses I will be giving to the user:
I'm sorry, your answer is wrong. The correct answer is "ANSWER". Don't demoralize yourself and keep training!
But as you see the ANSWER should be the number or text I would like to replace during the query so I get the correct result, as an example result:
I'm sorry, your answer is wrong. The correct answer is "Option 1". Don't demoralize yourself and keep training!
I am doing these queries inside CodeIgniter (PHP Framework) and this is the style of code I'm using:
public function mo_response_content($mo_response_content_id)
{
$this->db->select('*');
$this->db->where('id', $mo_response_content_id);
// Code to add for replacing part of the result
$query = $this->db->get('actions_mo_contents');
$row = $query->row();
if ($row)
{
return $row;
} else
{
return NULL;
}
}
How can I replace the ANSWER string during the database query?
Use the MySQL REPLACE() function as the following:
$this->db->select("*, REPLACE(string_column, 'ANSWER', 'replaceTextHere') AS 'response'");
I have some columns in my table, descriptions column contains some information like;
a1b01,Value 1,2,1,60|a1b01,Value2,1,1,50|b203c,Value 1,0,2,20
with a SQL command, i need to update it.
In there, I'll use a PHP function for updating, if first and second parameters exist in current records (in description column) together.
Eg: if user wants to change the value of description that includes a1b01,Value 1 I'll execute a SQL command like that;
function do_action ($code,$value,$new1,$new2,$newresult) {
UPDATE the_table SET descriptions = REPLACE(descriptions, $code.','.$value.'*', $code.','.$value.','.$new1.','.$new2.','.$newresult)";
}
(star) indicates that, these part is unknown (This is why i need a regex)
My question is : how can i get
a1b01,Value 1,2,1,60|
part from below string
a1b01,Value 1,2,1,60|a1b01,Value2,1,1,50|b203c,Value 1,0,2,20
via regex, but a1b01 and Value 1 should be get as parameter.
I just want that; when I call do_action like that;
do_action ("a1b01","Value 1",2,3,25);
record will be : a1b01,Value 1,2,3,25|a1b01,Value2,1,1,50|b203c,Value 1,0,2,20(first part is updated...)
You don't necessarily need to use a regular expression to do this, you could use the explode function since it is all delimited
So you could do as follows:
$descriptionArray = explode('|', $descriptions); //creates array of the a1b01,Value 1,2,1,60 block
//then for each description explode on ,
for($i = 0; i < count($descriptionArray); $i++){
$parameters = explode(',', $descriptionArray[$i]);
do_action ($parameters[0],$parameters[1],$parameters[2],$parameters[3],$parameters[4]);
}