PHP MySQL: Search database for string (in array) missing results - php

I am creating a feature which searches a database for a string. The PHP shows no errors using a PHP validator and, if the search term doesn't exist, it returns the correct errors. My problem is that, when searching for the term 'abandon hastily' in the column of the database entitled 'collocation' (which is currently the only entry in the database), no results are returned. Though I can see using phpMyAdmin that this entry does definitely exist.
The string is entered by a user into an input field using the following HTML:
<form action='http://www.murkyfiles.esy.es/search.php' method='GET'>
<center>
<p><label for='search'>Please enter your question as accurately as possible:</label></p>
<p><input type='search' size='90' name='search'></p>
<p><input type='submit' name='submit' value='Find answer'></p>
</center>
</form>
The term entered is searched on the database using the following PHP:
<?php
$button = $_GET [ 'submit' ];
$search = $_GET [ 'search' ];
$host = "[HOST URL]";
$username = "[USERNAME]";
$password = "[PASSWORD]";
$database = "[DATABASE]";
$searchlength = strlen($search);
if( !$button )
echo "You didn't submit a keyword";
else {
if( strlen( $search ) <= 1 )
echo "Search term too short";
else {
echo "You searched for <b> $search </b> <hr size='1' > </ br > ";
// Connect to database
$con = mysqli_connect ( $host, $username, $password );
if(!$con) {
die('Could not connect: ' .PDO::errorInfo());
}
mysqli_select_db ( $con, $database );
$search = str_split($search, $searchlength);
$construct = " SELECT * FROM 'coll_test' WHERE collocation LIKE '%$search%' ";
$run = mysqli_query( $con, $construct );
//Fetch and return search results.
if ($foundnum == 0)
echo "Sorry, there are no matching results for <b> $search[0] </b>.
</ br >
</ br > 1. Try presenting your Something is wrong in a more academic manner. Guidance can be found on the majority of University websites without need for registration.
</ br > 2. Try more common words/phrases with similar meaning. This search focuses on colloquialisms - commonly used phrases within a language.
</ br > 3. Please check your spelling";
else {
echo "$foundnum results found !<p>";
while ( $runrows = mysqli_fetch_assoc($run) ) {
$collocation = $runrows ['collocation'];
echo "<a href='$url'> <b> $title </b> </a> <br> $desc <br> <a href='$url'> $url </a> <p>";
}
}
}
}
I have looked at various similar questions and none of them offer solution.
To clarify, the database table column headers are as follows:
collocation | left | right | length | google-results | bing-results | yahoo-results | url-link | wiki | date
There is, so far, only one entry in my database:
collocation = abandon hastily
left = abandon
right = NULL
length = 2
google-results = 24000000
bing-results = 386000
yahoo-results = 385000
url-link = oxforddictionary.so8848.com/search1?word=abandon
wiki = 0
date = [TIMESTAMP]

A quite rewrite, with notes below:
$con = mysqli_connect ( $host, $username, $password, $database );
//$search = str_split($search, $searchlength); ///??? See below
$searchSafe = preg_replace("/[^0-9a-z-_ ]/i","",$search); //example only.
$construct = " SELECT COUNT(*) AS found FROM `coll_test`
WHERE collocation LIKE '%".$searchSafe."%' ";
$run = mysqli_query($con, $construct);
$result = mysqli_fetch_array($run);
print $result['found']." number of results found!"; //for example.
1) You can include the database reference in the MySQLi connection function.
2) str_split returns an array but you are using the result as a string. This is confusing and incorrect, what do you intend to do with this?
$_GET['search'] will always be a string type, so you do not need to use it as an array or any array-based messing around with it.
3) Having outside functions manually returning a number_rows count can be inaccurate, instead use COUNT within the SELECT statment.
4) You forgot to return the result of your actual query! So above I have inserted a mysql_fetch_array result to see the number of results. You also did not define a value for your $foundnum variable.
5) You are mixing PDO with MySQLi, these two connection methods are mutually exclusive. They do not mix.
6) You are wide open to SQL injection and database compromise you need to use Prepared Statements (as well exampled by Saty ) and use something like preg_replace (or another REGEX parser) to remove invalid characters from strings, such as:
$searchSafe = preg_replace("/[^0-9a-z-%_ ]/i","",$search); //example only.
The above would mean only 0-9 or a-z (case insensitive, /i) or -, % or _ are allowed in the string.
7) table or column names ('coll_test') should not be encased in single quotes, instead they shold be encased in backticks, if at all. In MySQL single quotes are for containing data strings only.

Wrap off quotes form table and column name instead use backtick and your code is open for sql injection user prepare and bind statement to prevent it
$search = $_GET ['search'];// get your value
$like = "%$search%";//
$stmt = $con->prepare("SELECT `collocation`,`left`,`right` FROM `coll_test` WHERE collocation LIKE ?");
$stmt->bind_param('s', $like);
$stmt->execute();
$stmt->bind_result($collocation,$left,$right);
$rows = $stmt->num_rows;// check your query return result of not
if ($rows > 0) {
while ($stmt->fetch()) {// fetch data from query
printf ("%s (%s)\n", $collocation,$left,$right);
// fetch data form result set
}
} else {
echo "Sorry, there are no matching results for <b> $search </b>.";
}

Related

PHP MySqli show result for similar terms (Keyword)

Let me explain fast what i want to do!
I want to show similar rows from my database by a PHP term.
I have a table called "games" and a column called "title" that titles are looks like "Rockstar - GTA V".
So i want to remove all words after dash and use new string as keyword to search in database.
My CMS use this code to show post title inside the loop:
$_smarty_tpl->tpl_vars['game']->value['title']
I just found a code to convert "Rockstar - GTA V" to "Rockstar":
<?php $mygame = strstr($_smarty_tpl->tpl_vars['game']->value['title'], '-', true); echo($mygame); ?>
When i put this code in my "Single template file", it work fine and trim the title as i want and it work good in every game's single page.
So i want to make a section in single page to display all games made by that company (i mean that trimmed word from title). I tried some codes and nothing! This is what i tried:
<?php
$connect = mysqli_connect("localhost", "dbname", "dbpass", "dbuser");
$connect->set_charset('utf8mb4');
mysqli_set_charset($link, 'utf8mb4');
$gamecompany = strstr($_smarty_tpl->tpl_vars['game']->value['title'], '-', true);
$query = 'SELECT * FROM games WHERE title = "'.$gamecompany.'" ORDER BY game_id ASC LIMIT 50';
$result = mysqli_query($connect, $query);
if(mysqli_num_rows($result) > 0)
{
$output .= '<div class="list">';
while($row = mysqli_fetch_array($result))
{
$output .= '<li class="game">'.$row["title"].'</li>';
}
$output .= '</div>';
echo $output;
}
else
{
echo 'Nothing Found';
}
?>
So i used $gamecompany to trim and get a game's company and use it as a keyword in query. But everytime it just show "Nothing Found". When i have some games with keyword "Rockstar" in my database But it won't display that and just pass the conditions statement and can't show nothing.
Tried another keywords (Directly in my code) but won't work!
And one note: My titles are in "Arabic" language and it should be UTF8. Is this my problem? or just a wrong coding?
Using LIKE you can find all occurences with 'Rockstar', but to be safe, convert it to lower case and remove any extra spaces that might occur. Also, lets protect ourselves from SQL attacks with a prepared statement.
$gamecompany = strtolower(trim(strstr($_smarty_tpl->tpl_vars['game']->value['title'], '-', true))); // put it in lower case, trim any excess white space
$query = 'SELECT * FROM games WHERE LOWER(title) LIKE ? ORDER BY game_id ASC LIMIT 50';
$stmt = $conn->prepare($query);
$value = "%$gamecompany%"; // The % allows us to find any titles that have our search string in them
$stmt->bind_param("s", $value);
$stmt->execute();
$result = $stmt->get_result();
For you requirement
title = "'.$gamecompany.'"
is not going to work. You'll need to either use likewise search or full-text search
Likewise
title like '$gamecompany'
Full-Text - For full-text to work, you'll need to have full-text index for that column
MATCH (title) AGAINST (:gamecompany IN NATURAL LANGUAGE MODE)
You can create Full-text index like this
ALTER TABLE games ADD FULLTEXT(title)
Try using the LIKE keyword inside the query , and for the Arabic part make sure both the web app and the database uses the same encoding , i once had this problem and when both of them followed the same encode it worked out.

Filters not working (Executing different PHP queries based on parameters)

I am trying to implement filters which will help users refine there search for other users. Here is an image of my search parameters just to provide you with a graphical representation of what I will soon convey:
There are three filters:
Gender
Age
Similarity in studies
By default, I want to convey all users on the system. So when a user goes onto users.php, every single user will be displayed, then, when the filters are applied, refine the results accordingly.
Not all three parameters have to be completed to start the search, for example, a user can simply search a female user and it should display all female users on search click.
I have tried to implement different queries for each scenario, but all users are always being displayed. If I specify I want to search for a female and then click search, it will do nothing, still showing me all users.
Also, I am struggling with the similarity in studies parameter. The way this works is that in a table called user_bio I am storing data regarding what the user is studying, the user can choose to not provide this information, so studying can also be empty in my table.
The way I want it to work is to look at what the logged in user is studying, and then find words which match in other peoples bio's. For example, I am currently logged in as Conor, and Conor is studying Computer Science. Ideally, an algorithm will run which searches other users bio from the user_bio table, and return all the users who have computer or science in their bio's. Im pretty sure this concerns the LIKE clause but I have never used it before so I cannot be certain.
Here is my current approach:
// processing filters
$refined_gender = htmlentities (strip_tags(#$_POST['gender']));
$age_from = htmlentities (strip_tags(#$_POST['age_from']));
$age_to = htmlentities (strip_tags(#$_POST['age_to']));
$studying = htmlentities (strip_tags(#$_POST['studying']));
$get_all_users = mysqli_query ($connect, "SELECT * FROM users" );
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
if (isset($_POST['submit'])){
// if gender parameter is used ...
if ($refined_gender){
$gender_statement = mysqli_prepare ($connect, "SELECT * FROM users WHERE gender = ?");
mysqli_stmt_bind_param($gender_statement, "s", $refined_gender);
mysqli_stmt_execute ($gender_statement);
mysqli_stmt_close($gender_statement);
}
// if studying parameter used...
if ($studying) {
// see explanation below...
}
// if gender and age parameter used...
if ($refined_gender && $age_from && $age_to){
$gen_and_age_statement = mysqli_prepare ($connect, "SELECT * FROM users WHERE gender = ? AND age BETWEEN ? AND ?");
mysqli_stmt_bind_param($gen_and_age_statement, "sss", $refined_gender, $age_from, $age_to);
mysqli_stmt_execute ($gen_and_age_statement);
mysqli_stmt_close($gen_and_age_statement);
}
}
Summary, what I need:
The SELECT * FROM users query to be executed by default on users.php. This will show all the users in the system.
For any filter to be applied. Not all filters need to be applied to get a result, a user can search for a female and click search, loading all female users in the system.
I need the query to change based on what filters have been applied. So if a user has searched for a male user, and the other two options are not selected, then query will be "SELECT * FROM users WHERE gender = '$var_here'.
Here iam providing code such that how can you write multiple filter option inside a single query..but here i didn't mention about your 3rd filter option studing,because its about another table and you were not mentioned it clearly such that it's linked to this table using foreign keys or following relational database structure.any way multi filter option is as follows..here i added database connect and escape injection's functions...if u don't need that neglect that part..
function escape($e_string)
{
global $connect;
if(!isset($connect))
{
// DATABASE CONNECTION QUERY
$connect = mysqli_connect("servername", "username", "password", "");
if (!$connect)
die("Connection failed: " . mysqli_connect_error());
}
$e_string = trim(utf8_encode($e_string));
$e_string = mysqli_real_escape_string($connect,$e_string);
return $e_string;
}
// processing filters
$refined_gender = isset($_POST['gender']) ? escape($_POST['gender']) : '';
$age_from = isset($_POST['age_from']) ? escape($_POST['age_from']) : '';
$age_to = isset($_POST['age_to']) ? escape($_POST['age_to']) : '';
$studying = isset($_POST['studying']) ? escape($_POST['studying']) : '';
$query = "SELECT * FROM users WHERE 1=1";
if (isset($_POST['submit'])){
$addstring1 = $addstring2 = $addstring3 = $and1 = $and2 = $and3 = "";
$andcnt =3;
if($refined_gender != '')
$addstring1 = " gender = '$refined_gender'";
if($age_from != '')
$addstring2 = " age >= '$age_from'";
if($age_to != '')
$addstring3 = " age <= '$age_to'";
for($i=1;$i<=$andcnt;$i++)
${"and".$i} = ${"addstring".$i} != '' ? " AND" : "";
$query .= $and1.$addstring1.$and2.$addstring2.$and3.$addstring3;
}
$get_all_users = mysqli_query ($connect, $query);
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
Instead of this code:
htmlentities (strip_tags(#$_POST['gender']));
you should validate it, like so:
$gender = filter_input(INPUT_POST, 'gender', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^[mf]$/i']]);
$ageFrom = filter_input(INPUT_POST, 'age_from', FILTER_VALIDATE_INT, [ 'default' => 1, 'min_range' => 1, 'max_range' => 100]);
$ageTo = filter_input(INPUT_POST, 'age_to', FILTER_VALIDATE_INT, [ 'default' => 1, 'min_range' => 1, 'max_range' => 100]);
$studying = filter_input(INPUT_POST, 'gender', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^(similar|different|same)$/i']]);
This is simpler and more secure.
Each input should be properly validated.
Avoid using #.
Once you have the values, you can concatenate them in to your query, like so:
$types = '';
$values = [];
$query = 'SELECT * FROM users';
$where = [];
// empty tests for both null (no data in input) and false (invalid data)
if (!empty($gender)) {
$where[] = 'gender = ?';
$types .= 's';
$values[] = &$gender;
}
if (!empty($ageFrom)) {
$where[] = 'age >= ?';
$types .= 'i';
$values = &$ageFrom;
}
if (!empty($ageTo)) {
$where[] = 'age <= ?';
$types .= 'i';
$values = &$ageTo;
}
if (!empty($studying)) {
$field = 'user_bio';
// Get the $user_bio value of the current user from the database
// Change the $user_bio into a regular expression collection of words
$regexp = '('.str_replace(' ','|',$user_bio).')';
// Set up the where
switch ($studying) {
case 'same':
$comparison = '= ?';
break;
case 'different':
$comparison = 'NOT REGEXP (?)';
break;
case 'similar':
$comparison = 'REGEXP (?)';
break;
}
$where[] = $field.' '.$comparison;
$types .= 's';
$values[] = &$user_bio;
}
if (count($where) > 0) {
$query .= ' WHERE '.implode(' AND ',$where);
}
// new mysqli ( host,
$mysqli = new mysqli('localhost','root','','stuff');
$stmt = $mysqli->prepare($query);
// This allows you to use a variable number of arguments with the prepared statement
// Note the use of the ampersands on the array assignment, this ensures they are passed by reference
$params = array_merge([$types],$values);
call_user_func_array([$stmt,'bind_param'],$params);
$stmt->execute();
// Bind a variable for each column
$stmt->bind_result($user_name);
while ($stmt->fetch()) {
var_dump($result);
}
(I'm not sure why the answers already provided don't address your question sufficiently.)
I'd approach it like this. First, get rid of that first query execution to pull all users. Instead, use just a single query.
Dynamically prepare the SQL text. Start the statement with the "SELECT ... FROM users". (We'll handle appending an ORDER BY as the last step.
I'd conditionally check each "filter", to see if I need to append a condition to the WHERE clause or not.
At the start of the SQL, we'll include a "WHERE 1=1".
$sql = "SELECT ... FROM users u"
$sql .= " WHERE 1=1";
The "WHERE 1=1" is basically useless. The optimizer is going to throw that away. The reason we add it is just to make our code easier later. We can just append our next filter with " AND condition", and not worry about whether this is the first one, and we need to use WHERE instead of AND.
We'll initialize a string and an array, to hold our bind types string "sssis" whatever it needs to be, and an array of references to the values we want to pass in.
$bind_type = "";
$bind_vals = array();
The processing for each filter is going to be icky... but we can do it. Check if we need to append anything to the SQL. If we do, figure out what needs to be added, including any bind placeholders. And append the type of the bind parameter ("i", "s", whatever) to the $bind_type string, and push (the reference to) a value into our $bind_vals array.
if ( $refined_gender ) {
// figure out what that SQL text needs to look like
// append the string to the SQL text
$sql .= " AND u.gender = ?";
// append type to string, and push a reference to the value into array
$bind_types .= "s";
$bind_val[] = &$refined_gender;
}
Our code in there is going to be more complicated than that. That's just handling an equality comparison. We're just keeping things simple now, to illustrate the pattern.
We repeat the same kind of thing for each filter we might need to add. Check if it's needed, figure out what we need to append to the SQL text, append to the bind_types string and push (a reference to) the value into the bind_vals array.
For working this out, I'd start with working on just one condition, and get that working, to get the kinks worked out. When we add more filters, and things go awry, I know where to look for the problem. (I know what was working before.)
When I'm done with the WHERE clause, I append any ORDER BY and LIMIT that I need. This could be conditional, but in the end, we're going to wind up doing something like this:
$sql .= " ORDER BY u.id DESC LIMIT 50";
When I'm done with all that, I've got a string containing SQL text that looks something like this:
SELECT ...
FROM users u
WHERE 1=1
AND u.gender = ?
AND u.age_from >= ?
AND u.age_to <= ?
ORDER BY u.id DESC
LIMIT 50
(in this example, it contains three bind placeholders. If we've done it right,
we'll have a $bind_types string containing three characters, e.g. "sii"
And we'll have a $bind_vals array that contains references to three values.
Now, we can call mysqli_stmt_prepare. If there's not an error in our SQL, we should get back a statement handle.
$stmt = mysqli_prepare($conn,$sql);
(Check the return from the prepare.)
Now we just need to bind our parameters. And this is where mysqli makes things a little hairy. If we were using PDO (or Perl DBI), calling the "bind parameter/bind value" would be easy. Those would let us pass an array of the bind values. But not mysqli. He won't let us call mysqli_stmt_bind_param with an array as an argument.
We need to run a function call like this:
mysqli_stmt_bind_param($stmt, $bind_types, &$refined_gender, &$age_from, ... );
And our problem is that we have a variable number of arguments.
There is a workaround.
We can use the call_user_func_array function.
Because the code is using procedural style and not object oriented style, the handle to the prepared statement is the first argument, the second argument is the bind types string, followed by the bind values. The bind values are already in an array. We just need to get all of those into one hugh jass array.
The array_merge function seems to be custom designed for doing this.
// array_merge(array($stmt), array($bind_types), $bind_vals)
That will return us a single array. Which is exactly what we need for calling the call_user_func_array function. We aren't going to need that array anywhere else (unless we're debugging, and we want to print it out).
We only need to call mysqli_stmt_bind_param if we have at least one bind placeholder in our statement. So we can shortcut around this if our $bind_types string is empty. (And we know $bind_types won't be "0" because our code never appended a "0" to it.)
if ($bind_types) {
call_user_func_array('mysqli_stmt_bind_param', array_merge(array($stmt), array($bind_types), $bind_vals) );
}
The first argument (to call_user_func_array) is the name of the function we want to execute, and the second argument is the hugh jass array that we want converted into a list.
And the whole point of doing that is making it dynamic, we can pass in one, two, three, bind values.
At this point, we're ready to execute the statement, and fetch the results.
Again, important to point out: mysqli_stmt_bind_param expects the bind values to be passed by reference, not by value. And that's why we pushed references to the values into the bind_vals array.
I'm not sure what question you asked.
But definitely ditch that first call to mysqli_query. That's going to return all rows in the users table.
With one or two conditions, the approach of static SQL and static bind types, and listing out the bind values is workable.
But when we get three, four, five possible filters, and all the possible combinations, that's going to be unweildy.
So we go with a more dynamic approach, dynamically creating the query, and pushing our bind values on an array as go.
This Html page:
<form method="POST" action="">
<input type="radio" name="rbo_gender" value="male">Male
<input type="radio" name="rbo_gender" value="female">Female
Age From<select name="agefrom">
<?php
for($i=10;$i<50;$i++):
?>
<option value="<?php echo $i?>"><?php echo $i?></option>
<?php
endfor;
?>
</select>
Age To<select name="ageto">
<?php
for($i=10;$i<50;$i++):
?>
<option value="<?php echo $i?>"><?php echo $i?></option>
<?php
endfor;
?>
</select>
Studying:
<input type="radio" name="rbo_type" value="similar">Similar
<input type="radio" name="rbo_type" value="exact">Exactly same
<input type="radio" name="rbo_type" value="different">Different
<input type="submit" name="btnsearch" value="Search">
</form>
This is php part:
if($_POST["btnsearch"])
{
if(!empty($_POST["rbo_gender"]))
{
$gender = $_POST["rbo_gender"];
$cond .= " and gender = '".$gender."'";
}
if(!empty($_POST["agefrom"]))
{
$agefrom = $_POST["agefrom"];
$cond .= " and age >= '".$agefrom."'";
}
if(!empty($_POST["ageto"]))
{
$ageto = $_POST["ageto"];
$cond .= " and age <= '".$ageto."'";
}
if(!empty($_POST["rbo_type"]))
{
$user_type = $_POST["rbo_type"];
switch($_POST["rbo_type"])
{
case "similar": $cond .= " and user_bio like '%".$ageto."%'";
break;
case "exact": $cond .= " and user_bio = '".$ageto."'";
break;
case "different":$cond .= " and user_bio ! like '%".$ageto."%'";
break;
}
}
$query = "select * from users where 1 ".$cond;
}
Please update query as per mysqli() & use bind param. Also instead of use # try to use filter_input you can use REGEXP instead of like also. I have created the variable to use bind_param purpose.

Building interactive WHERE clause for Postgresql queries from PHP

I'm using Postgresql 9.2 and PHP 5.5 on Linux. I have a database with "patient" records in it, and I'm displaying the records on a web page. That works fine, but now I need to add interactive filters so it will display only certain types of records depending on what filters the user engages, something like having 10 checkboxes from which I build an ad-hoc WHERE clause based off of that information and then rerun the query in realtime. I'm a bit unclear how to do that.
How would one approach this using PHP?
All you need to do is recieve all the data of your user's selected filters with $_POST or $_GET and then make a small function with a loop to concatenate everything the way your query needs it.
Something like this... IN THE CASE you have only ONE field in your DB to match with. It's a simple scenario and with more fields you'll need to make it so that you add the field you really need in each case, nothing too complex.
<?php
//recieve all the filters and save them in array
$keys[] = isset($_POST['filter1'])?'$_POST['filter1']':''; //this sends empty if the filter is not set.
$keys[] = isset($_POST['filter2'])?'$_POST['filter2']':'';
$keys[] = isset($_POST['filter3'])?'$_POST['filter3']':'';
//Go through the array and concatenate the string you need. Of course, you might need AND instead of OR, depending on what your needs are.
foreach ($keys as $id => $value) {
if($id > 0){
$filters.=" OR ";
}
$filters.=" your_field = '".$value."' ";
}
//at this point $filters has a string with all your
//Then make the connection and send the query. Notice how the select concatenates the $filters variable
$host = "localhost";
$user = "user";
$pass = "pass";
$db = "database";
$con = pg_connect("host=$host dbname=$db user=$user password=$pass")
or die ("Could not connect to server\n");
$query = "SELECT * FROM table WHERE ".$filters;
$rs = pg_query($con, $query) or die("Cannot execute query: $query\n");
while ($row = pg_fetch_row($rs)) {
echo "$row[0] $row[1] $row[2]\n";
//or whatever way you want to print it...
}
pg_close($con);
?>
The above code will get variables from a form that sent 3 variables (assuming all of them correspond to the SAME field in your DB, and makes a string to use as your WHERE clause.
If you have more than one field of your db to filter through, all you need to do is be careful on how you match the user input with your fields.
NOTE: I did not add it here for practical reasons... but please, please sanitize user input.. ALWAYS sanitize user input before using user controlled data in your queries.
Good luck.
Don't do string concatenation. Once you have the values just pass them to the constant query string:
$query = "
select a, b
from patient
where
($x is not null and x = $x)
or
('$y' != '' and y = '$y')
";
If the value was not informed by the user pass it as null or empty. In the above query the x = $x condition will be ignored if $x is null and the y = '$y' condition will be ignored if $y is empty.
With that said, a check box will always be either true or false. What is the exact problem you are facing?
Always sanitize the user input or use a driver to do it for you!
I have created a Where clause builder exactly for that purpose. It comes with the Pomm project but you can use it stand alone.
<?php
$where = Pomm\Query\Where::create("birthdate > ?", array($date->format('Y-m-d')))
->andWhere('gender = ?', array('M'));
$where2 = Pomm\Query\Where::createWhereIn('something_id', array(1, 15, 43, 104))
->orWhere($where);
$sql = sprintf("SELECT * FROM my_table WHERE %s", $where2);
$statement = $pdo->prepare($sql);
$statement->bind($where2->getValues());
$results = $statement->execute();
This way, your values are escaped and you can build dynamically your where clause. You will find more information in Pomm's documentation.

why does this search of a mysql database produce no results? Using LIKE for the first time

Editing someone else's code here, so I can't change the field in the database called title or change to MySQLi etc :/
The code connects to the DB without problems, but always pulls in zero results.
$strSQL = "SELECT * FROM newproducts WHERE 'title' LIKE ('%$q%')";
$sql = mysql_query($strSQL) or die(mysql_error());
$num_rows = mysql_num_rows($sql);
if ( $q == '' ) {
echo '<p class="black-text">Please provide a search term.</p>';
}
else if ( $num_rows <= 0 ) {
echo '<p class="black-text">Your search for <b>'.$q.'</b> returned <b>0</b> results.</p>';
}
else {
echo '<p class="black-text">Your search for <b>'.$q.'</b> returned <b>'.$num_rows.'</b> result(s).<br/><br/>';
while($row = mysql_fetch_assoc($sql)) {
echo '- '.$row['title'].' [Read more]<br/>';
}
echo '</p>';
}
Could it be a case issue? I've tried searching for lower and upper strings, but still zero results.
In MySQL single quotes denote strings:
SELECT * FROM newproducts WHERE 'title' LIKE ('%$q%')
Should be
SELECT * FROM newproducts WHERE title LIKE ('%$q%')
Additionally, you are testing for if ($q == '') after you have performed the query - you may want to do that before - but that isn't causing your issue.
And lastly, you are at risk of SQL injection by using potentially unsafe user input - but I'm not going to delve into that as it isn't directly related to your question. Most PHP developers are using prepared statements these days to make their queries safer (and because the old style of running queries is going to be deprecated).

PHP: replace a "variable" from mysql query (Table's content)

I am trying to echo a variable, from a mysql query, like this:
<?php
...//FYI: mysql connection already established
//Table: title
//col: page | title
//row: html | "$domain_name: Welcome"
$page_id = basename(getcwd());
$domain_name = "Name of My Domain";
$sql = "SELECT title FROM mydatabase.title WHERE page = '$page_id' ";
//The query's result is 1 row
$dbq = mysql_query ($sql);
$dba = mysql_fetch_array( $dbq );
echo $dba["title"];
//it outputs: $domain_name: Welcome", instead of "Name of My Domain: Welcome"
?>
What am I doing wrong?
I am trying to replace the "variable [$domain_name] in the table's content for it's php value. -I thought " (double quotes) are supposed to replace the variable with it's value.
PS. I am a beginner
EDIT 2/7/2012, 3:14pm: Forgot to mention. The query works OK. $dba['title'] has "$domain_name: Welcome" as a value. The problem is, it is not replacing $domain_name
I thought " (double quotes) are supposed to replace the variable with it's value.
That works only in case when you specify the string in your code. If the string comes from outside - it doesn't have such magic behaviour.
So the only solution you could go with is:
echo str_replace('$domain_name', $domain_name, $dba["title"]);
Or you could go with some sort of template engine like Twig or Smarty and treat your database value as a template, and your variables as the data.
You can replace it on database level:
$sql = 'SELECT REPLACE(title, \'$domain_name\',\''.$domain_name.'\') as title FROM mydatabase.title WHERE page = '.intval($page_id);
//The query's result is 1 row
$dbq = mysql_query ($sql);
$dba = mysql_fetch_array( $dbq );
echo $dba["title"];
(Note the single quotes)

Categories