Variable in SQL select - php

I'm trying to make a search bar with PHP to show the product that we got in store with a get script. Now I want to put the variable I get in my SQL query like this:
$search = $_GET['q'];
$sql = "SELECT
`product`.`productcode`,
`product`.`productnaam`,
`product`.`prijs`,
`product`.`voorraad`,
`afbeelding`.`image_id`,
`afbeelding`.`image_ctgy`
FROM `product`, `afbeelding`
WHERE `product`.`productcode` = `afbeelding`.`image_id` AND `afbeelding`.`image_ctgy` = $search
GROUP BY `productnaam`
ORDER BY `productnaam`;";
How do I make it so the variable doesn't mess with the query?

Take a look at PDO prepared statements.
They allow you to use a variable inside your query without worrying about MySQL injections too much.
$stmt = $dbh->prepare("SELECT
`product`.`productcode`,
`product`.`productnaam`,
`product`.`prijs`,
`product`.`voorraad`,
`afbeelding`.`image_id`,
`afbeelding`.`image_ctgy`
FROM `product`, `afbeelding`
WHERE `product`.`productcode` = `afbeelding`.`image_id` AND `afbeelding`.`image_ctgy` = :search
GROUP BY `productnaam`
ORDER BY `productnaam`");
$stmt->bindParam(':search', $search);

$search = mysqli_real_escape_string($_GET['q']);
$sql = "SELECT product.productcode, product.productnaam, product.prijs, product.voorraad, afbeelding.image_id, afbeelding.image_ctgy FROM product, afbeelding WHERE product.productcode = afbeelding.image_id AND afbeelding.image_ctgy = '" . $search . "' GROUP BY productnaam ORDER BY productnaam";
Or use PDO instead (OOP):
$dbh = new mysqli($servername, $username, $password, $dbname);
$stmt = $dbh->prepare("SELECT product.productcode, product.productnaam, product.prijs, product.voorraad, afbeelding.image_id, afbeelding.image_ctgy FROM product, afbeelding WHERE product.productcode = afbeelding.image_id AND afbeelding.image_ctgy = :search GROUP BY productnaam ORDER BY productnaam");
if ($stmt->execute([':search' => $_GET['q']])) {
while ($row = $stmt->fetch()) {
print_r($row);
}
}
If you're using an older version of php, replace [':search' => $_GET['q']] with array(':search' => $_GET['q'])

Use filter_input(). It will make sure the send $_GET variable is a secure string.
In your example:
// q is the name of the $_GET variable.
$search = filter_input(INPUT_GET, 'q', FILTER_SANITIZE_SPECIAL_CHARS);

Related

Trying to get a result not displaying

I'm just trying to get something basic to appear for now and it's not working. It should display 1 on the screen. Is my logic wrong? I paste my statement in console and get 1.
<?php
$sql = mysqli_query("Select moist_measure_avail from sigh_in_account where moist_measure_avail = '1'");
$result = mysqli_fetch_array($sql);
echo $result['moist_measure_avail'];
First of all you should have to create a connection
<?php
$conn = mysqli_connect("localhost "," root","","dbname");
?>
And then you have to include the conn variable in your query
$sql = mysqli_query( $conn, " SELECT moist_measure_avail from sigh_in_account WHERE moist_measure_avail = '1'");
The sql statements must be either all caps or all small
$sql = mysqli_query("Select moist_measure_avail from sigh_in_account where moist_measure_avail = '1'");
pass connection as first param in above method. something like this
$sql = mysqli_query($conn,"Select moist_measure_avail from sigh_in_account where moist_measure_avail = '1'");
where $conn is mysql connection

SQL in php, make partial search using LIKE

I am trying to make SQL in php to return all the entries that matches a keyword that is entered by the user (from search bar).
I want to return all the entries that their name "partial" matches with the keyword.
I want at least to match the keyword, if an entry name in database before has space and after maybe another letter/space.
For example I have three entries with names "Milk", "Semi skimmed Milk" and "Full Milk 2". If the keyword is "Milk" or "milk" or "MiLK", I want to get all these three entries.
The only case I am thinking it might be the problem is case sensitive.
I tried with a keyword that exists exactly in database, but my app (on android) stops .
Based on user3783243 answer.
PHP FILE
<?php
$servername = "";
$username = "";
$password = "";
$dbname = "";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT name FROM items WHERE name LIKE CONCAT ('%', ?, '%')";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $keyword);
$res = $stmt->get_result();
while($row = $res->fetch_assoc()) {
echo $row["name"] . ",";
}
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo $row["name"] . ",";
}
} else {
echo "0";
}
$conn->close();
?>
Your query should be:
$sql = "SELECT * FROM items WHERE name LIKE CONCAT ('%', ?, '%')";
and then $keyword should be bound with whatever syntax the driver you are using supports.
As is your query would have been:
SELECT * FROM items WHERE name LIKE CONCAT ('%', Milk, '%')
and you wanted Milk to be a string so it needed to be quoted. As is mysql would have thought that was a column.
Alternatively you could do:
$keyword = '%' . $_POST['keyword'] . '%';
$sql = "SELECT * FROM items WHERE name LIKE CONCAT ?";
that is the same and still requires the binding though.
The binding also takes away the SQL injection. See How can I prevent SQL injection in PHP? and/or https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#Defense_Option_1:_Prepared_Statements_.28with_Parameterized_Queries.29
Per update.. replace:
$keyword =$_POST['keyword'];
$sql = "SELECT * FROM items WHERE name LIKE '%$keyword%)";
$result = $conn->query($sql);
with:
$sql = "SELECT name FROM items WHERE name LIKE CONCAT ('%', ?, '%')";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $keyword);
$stmt->execute();
$res = $stmt->get_result();
if(empty($conn->errno) && !empty($res)) {
while($row = $res->fetch_assoc()) {
echo $row["name"] . ",";
}
} else {
echo '0';
//print_r($conn->errno);
}
$conn->close();
...
also remove
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo $row["name"] . ",";
}
} else {
echo "0";
}
$conn->close();
In this case you can convert the input in search bar to either upper or lower case by default then apply query in db like
For Upper case:
$keyword =strtoupper($_POST['keyword']);
$sql = "SELECT * FROM items WHERE upper(name) LIKE '%$keyword%)";
Or for lower case:
$keyword =strtolower($_POST['keyword']);
$sql = "SELECT * FROM items WHERE lower(name) LIKE '%$keyword%)";

Prepared statement LIKE wildcard

I've made a function that accepts a search column, search term and an id number, and am trying to construct a prepared statement and fetch results, and return in json.
Here is what I have:
function searchBooks($searchColumn, $searchTerm, $teacherid) {
$books = array();
$link = connect_db();
$sql = "SELECT * FROM book WHERE teacher_id = ? AND ? LIKE ?";
$searchTerm = "%{$searchTerm}%";
$stmt = $link->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param('iss', $teacherid, $searchColumn, $searchTerm);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_array(MYSQLI_BOTH)) {
$book = new Book();
$book->id = $row['id'];
$book->title = $row['title'];
$book->author = $row['author'];
$book->ar_quiz = $row['ar_quiz'];
$book->ar_quiz_pts = $row['ar_quiz_pts'];
$book->book_level = $row['book_level'];
$book->type = $row['type'];
$book->teacher_id = $row['teacher_id'];
array_push($books, $book);
}
mysqli_stmt_close($stmt);
return json_encode($books);
}
I'm using a test page that passes values that I know should return results (using 'the' as a wildcard and 'title' for search column):
echo searchBooks('title', 'the', 1);
...but I am not getting any results at all... [] output on the test page.
Assume connect_db() retrieves a connection. Assume I'm doing all my error checking and everything in my controller level, and might add stuff like that later. Just trying to get results right now. Thanks in advance for anything you can point out.
searchcolumn cannot be a bind variable. You can't bind table/column names
$sql = sprintf("SELECT * FROM `book` WHERE teacher_id = ? AND `%s` LIKE ?", $searchColumn);
$searchTerm = "%{$searchTerm}%";
$stmt = $link->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param('is', $teacherid, $searchTerm);
It would also be a good idea to whitelist $searchColumn, validating that it really is a column in your book table before executing this
EDIT
And why bother using fetch_array(MYSQLI_BOTH) when you're only using associative values from the array? Using fetch_assoc() would be better, or you could be even cleverer, and use fetch_object(), and then you wouldn't need to populate your Book object property by property
Consider:
while ($book = $result->fetch_object('Book')) {
array_push($books, $book);
}

mysql query fails if name has more then 1 words

I began to create a website for my small real estate business.
I played a bit with functions http://www.php.net mysql and I managed to make a page accessed via AJAX and returning html content for the search engine.
I have a database already populated with apartments and houses
The problem is that if the apartment name is "apartment" I return html content if "apartment with 3 rooms" it no longer write anything.
I do not understand where I was wrong:
<?php
$search = $_GET['selected'];
$link = mysql_connect('localhost', 'root', '');
mysql_select_db('houses', $link);
function searchHouse($search, $link){
$query = "select * from houses where name=$search limit 1";
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);
$query2 = "select * from houses_info where house_id=$row[id]";
$result2 = mysql_query($query2);
$row = mysql_fetch_assoc($result2);
return $row;
}
$result = searchHouse($search, $link);
echo $result['house_sq'];
echo "<br>";
echo $result['house_rooms'];
echo "<br>";
echo $result['house_bathrooms'];
echo "<br>";
echo $result['house_address'];
?>
you should know if you "played" with php.net that mysql_* functions are deprecated and are no longer maintained. It's a red box on top of the page informing you that.
you have a big MySQL injection hole there, you are not escaping $string at all
your problem is that you are not adding quotes to $string like: '$string'
you should stat using PDO to get rid of the bad code and SQL Injections holes.
you can wrap those 2 selects into a single select:
<?php
function searchHouse($search, $link){
$search = mysql_real_escape_string($search);
$query = "select * from houses_info where house_id IN (select * from houses where name='".$search."' limit 1)";
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);
return $row;
}
?>
since you are already building that website you can start moving to PDO, read this tutorial, your code will be more like this:
<?php
$db = new PDO('mysql:host=localhost;dbname=houses;charset=UTF-8', 'root', '', array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
$search = $_GET['selected'];
function searchHouse($search){
global $db;
$query = $db->prepare("select * from houses_info where house_id IN (select * from houses where name=:search limit 1)");
$query->execute(array(':search' => $search));
$row = $query->fetch(PDO::FETCH_ASSOC);
return $row;
}
$result = searchHouse($search);
?>
try:
$query = "select * from houses where name='".mysql_real_escape_string($search)."' limit 1";
and remember to always sanitize user input before passing it to sql to avoid sql injections.
Your first query should be:
$query = "select * from houses where name like $search% limit 1";
Strings need to be quoted in queries. Also, this is vulnerable to MySQL injection, make sure to escape $search with mysql_real_escape_string. Or even better yet use MySQLi or PDO instead of the old mysql_ functions.
$query = "select * from houses where name=$search limit 1";
Should be:
$query = "select * from houses where name='$search' limit 1";
Although you REALLY need to escape $search because it came from a user, even if they aren't malicious, any search queries with a single quote in it will break;
$search = $_GET['selected'];
Should be:
$search = mysql_real_escape_string($_GET['selected']);
(Anybody have the copy paste handy with the links to tutorials for MySQLi/PDO and such?)

Php on zend, how to escape a variable for a query?

im doing some queries in Zend Framework and i need to make sure no SQL injection is possible in the next kind of formats. I can use mysql_escape(deprecated) and wont do all the work. If i try to use real_mysql_escape it wont be able to grab the conection with the database and i cant find how zend_filter would solve the problem.
The query im doing (simplied) have the next sintaxes:
$db = Zend_Registry::get('db');
$select = "SELECT COUNT(*) AS num
FROM message m
WHERE m.message LIKE '".$username." %'";
$row = $db->fetchRow($select);
What is the best way to prevent SQL INJECTION with this framework?
Easy:
$db->quote($username);
So:
$username = $db->quote($username . '%');
$select = 'SELECT COUNT(*) AS num
FROM message m
WHERE m.message LIKE ' . $username;
$row = $db->fetchRow($select);
$sql = 'SELECT * FROM messages WHERE username LIKE ?';
$row = $db->fetchRow($sql, $username);
Reference: http://framework.zend.com/manual/en/zend.db.html
When working with a model you can use:
$bugs = new Bugs();
$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));

Categories