I have made a prepared statement, but I keep getting printed my else statement, which in this case is 0 results. I do not get any errors in my code. Is there something I am missing here?
<?php
include 'dbconnection.php';
error_reporting(E_ALL); ini_set('display_errors', 1);
if (mysqli_connect_errno()) { echo "Error: no connexion allowed : " . mysqli_connect_error($mysqli); }
if(isset($_POST["headline"], $_POST["description"])) {
$head = trim($_POST["headline"]);
$desc = trim($_POST["description"]);
}
$query = ("SELECT headline, description FROM articles WHERE headline=? AND description=?");
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $head, $describe);
$stmt->execute();
$stmt->bind_result($head, $describe);
$stmt->store_result();
if ($stmt->num_rows > 0) {
while($stmt->fetch()){
echo"[ $head -> $describe ]<br />";
}
}
else
{ echo"[ 0 results ]"; }
$stmt->close();
?>
Related
I am trying to learn how to use prepared statements in my PHP, to get data out from MySQL database. At the moment I am not getting anything printed out.
I need to have a while loop there is going through my rows in the database. Is that correct?
Am I on the correct way here, or what am I missing? I made some comments in the code, to describe what I am doing.
<?php
$stmt = $mysqli->prepare("SELECT * FROM fantasies WHERE headline = ? AND description = ? AND place = ? ORDER BY reg_date DESC LIMIT 3");
// Execute prepared statement
if ($stmt->execute()) {
$success = true;
}
// Make variables ready
$head = null;
$desc = null;
$plac = null;
// Bind result to variables
$stmt->bind_result($head, $desc, $plac);
while ($stmt->fetch()) {
// What should go here?
echo "Headline: ".$head."Description: ".$desc."Place: ".$place;
}
// Close statement
$stmt->close();
// Close connection
$mysqli->close();
if($success) {
echo "Selected Succesfull";
} else {
echo "Failed: " . $stmt->error;
}
}
?>
That code when executed it should give you an error :
Invalid parameter number: no parameters were bound
You need to bind your parameters as you are using placeholders
$stmt->bind_param("sss", $headline, $description, $place); //missing from your code
where "sss" is the dataType in this case a string and $headline, $description, $place are your variables that you replacing with placeholders
Your code should be
<?php
$stmt = $mysqli->prepare("SELECT * FROM fantasies WHERE headline = ? AND description = ? AND place = ? ORDER BY reg_date DESC LIMIT 3");
//bind parameters
$stmt->bind_param("sss", $headline, $description, $place);
if ($stmt->execute()) {
$stmt->bind_result($head, $desc, $plac);
while ($stmt->fetch()) {
echo "Headline: " . $head . "desc: " . $desc . "Place: " . $plac;
}
$stmt->close();
} else {
echo "error" . $mysqli->error;
}
$mysqli->close();
?>
EDITED CODEI have a mysqli line of code: $stmt->bind_param("ss", $_POST['skills'], $_POST['city']); in a working query.
I've found the need to change to PDO and have used:$stmt->bindValue(':skill', $skills, PDO::PARAM_STR);
$stmt->bindValue(':city', $city, PDO::PARAM_STR);
I get no results except the echoed "No result found. Did you enter a city?" nor error messages although there is a connection to the db as evidenced in the search form in which the select list of 'city' is loaded. The full query:
try {
global $pdo;
if(isset($_POST['search'])) {
$skills = htmlspecialchars($_POST['skills']);
$city = htmlspecialchars($_POST['city']);
$stmt = $pdo->prepare('SELECT skill.skill_name, team.city FROM skill JOIN team ON skill.skill_id=team.skill WHERE skill.skill_name LIKE :skills AND team.city LIKE :city');
$skills = "%".$skills."%";
$city = "%".$city."%";
$stmt->bindParam(':skills', $skills, PDO::PARAM_STR);
$stmt->bindParam(':city', $city, PDO::PARAM_STR);
$stmt->execute();
if ($stmt->rowCount() > 0){
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
echo $row['skill'] . " is available in " . $row['city'];
}
}
else {
echo "No result found. Did you enter a city?";
}
}
}//try
catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
Thanks.
If you really need to use LIKE then you need a wildcard somewhere in the string. As a placeholder has to represent a complete data literal, and if you want to use LIKE you have to create the parameter with the wildcards included like this.
try {
global $pdo;
if(isset($_POST['search'])) {
$skills = '%' . htmlspecialchars($_POST['skills']) . '%';
$city = '%' . htmlspecialchars($_POST['city']) . '%';
$stmt = $pdo->prepare('SELECT skill.skill_name, team.city
FROM skill
JOIN team ON skill.skill_id=team.skill
WHERE skill.skill_name LIKE :skill
AND team.city LIKE :city');
$stmt->bindValue(':skill', $skills, PDO::PARAM_STR);
$stmt->bindValue(':city', $city, PDO::PARAM_STR);
$stmt->execute();
if ($stmt->rowCount() > 0){
$rows = $stmt->fetchAll();
foreach ($rows as $row) {
echo $row['skill_name'] . " is available in " . $row['city'];
}
}else{
echo "No result found. Did you enter a city?";
}
}
}
catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
A minor edit by ML: Corrected $row['skill'] to $row['skill_name']
This method is part of a larger class, and am trying to get it to return an array of objects containing the same classes. However, it doesn't seem to be entering the while loop, and I can't figure out why. Any suggestions?
The expected result would be an array of objects containing this data http://sqlfiddle.com/#!9/b6e23/1.
public static function getAllFacts($groupID)
{
$factTable = array();
$conn = new mysqli($GLOBALS['hostName'], $GLOBALS['userName'], $GLOBALS['password'], $GLOBALS['database']);
if ($conn->connect_error)
{
echo "Database connection error (source table)<br>";
}
$query = "SELECT factID, sourceID, factTXT, citationID, noteGroupID, factCreated, factsGroupID FROM facts WHERE factsGroupID = ?";
$stmt = $conn->prepare($query);
if ($stmt)
{
$stmt->bind_param("i", $groupID);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result(
$factID,
$sourceID,
$factTXT,
$citaitionID,
$noteGroupID,
$factCreated,
$factsGroupID
);
$row = 0;
while ($stmt->fetch())
{
$numRows = $stmt->num_rows;
echo "numRows: " . $numRows . "<br>";
$factTable[$row] = new self($factID, $sourceID, $factTxt, $citationTxt, $noteGroupID, $factCreated, $factsGroupID, $numRows);
$row++;
}
$stmt->close();
}
else
{
echo "Statement failed. (source table) <br>";
}
return $factTable;
}
I'm building a simple form and want to secure this against the following SQL-injections:
- blind-injection
- boolean-based
- blind injection
- UNION query-based
- Stacked queries
- error-based injections
I thought that I had it all secured, but when I run SQL-map it still exploits my database.
<?php
$input = $_GET['input'];
if ($input) {
$db = mysqli_connect("localhost", "sec", "dubbelgeheim", "bookshop");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$escaper = real_escape_string($input);
$statement = $db->prepare("SELECT * FROM productcomment WHERE ProductId = ? LIMIT 1");
$statement->bind_param("s", $escaper);
$statement->execute();
$result = $statement->get_result();
$statement->close();
$count = $result->num_rows;
if ($count > 0) {
while ($row = $result->fetch_assoc()) {
echo "Product:" . $row['ProductId'] . "<br>";
echo "Annotation:" . $row['Comment'] . "<br>";
echo "TestOK!<br>";
}
}
else {
echo 'No record!';
}
$result->free();
$db->close();
}
?>
Did I forget something?
Can anyone help?
Thanks in advance!
Your problem is caused by you displaying mysqli_connect_error(). This is OK for testing but should NOT be used in production code. You also don't need $escaper = real_escape_string($input);.
Try this instead
/* check connection */
if (mysqli_connect_errno()) {
file_put_contents('MySQLiErrors.txt',date('[Y-m-d H:i:s]'). mysqli_connect_error()."\r\n", FILE_APPEND);
exit();
}else{
$statement = $db->prepare("SELECT * FROM productcomment WHERE ProductId = ? LIMIT 1");
$statement->bind_param("s", $input);
}
I've made the following script that shows blogposts. $_MULT[0] shows 'blog', $_MULT[1] shows the ID of the blogpost.
I'm wondering:
1) Is this script safe for SQL injection?
2) What if I removed ctype_digit() ? Would it still be safe then?
<?php
error_reporting(E_ALL);
$db = new PDO('mysql:host=localhost;dbname=blablabla','blablabla','passwd');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
echo '<h2>Blog</h2>';
$iTijd = time();
$_MULT = explode("/", $_GET['p']);
if($_MULT[0] == 'blog' AND isset($_MULT[1]))
{
if(ctype_digit($_MULT[1]))
{
// query
$sql = "SELECT Titel, Post, Datum FROM Blog WHERE Id = :Id AND Status = :Status AND Datum < :Tijd LIMIT 1";
// prepare query
$stmt = $db->prepare($sql);
// bind values
$stmt->bindParam(':Id', $a=$_MULT[1], PDO::PARAM_INT);
$stmt->bindParam(':Status', $a='1', PDO::PARAM_INT);
$stmt->bindParam(':Tijd', $a=$iTijd, PDO::PARAM_INT);
// execute query
$stmt->execute();
// select data from db
$aRow = $stmt->fetch(PDO::FETCH_ASSOC);
// show blogpost
echo '<h4>'. $aRow['Titel'] .'</h4><br />';
$datum = $aRow['Datum'];
$datum = date("d-m-Y", $datum);
echo '<i>'. $datum.'</i> - '. $aRow['Post'];
}
else
{
echo "<h2>404 - Pagina niet gevonden</h2>";
}
}
else
{
// query
$sql = "SELECT Id, Titel FROM Blog WHERE Status = :Status AND Datum < :Tijd ORDER BY Id DESC LIMIT 10";
// prepare query
$stmt = $db->prepare($sql);
// bind values
$stmt->bindParam(':Status', $a='1', PDO::PARAM_INT);
$stmt->bindParam(':Tijd', $a=$iTijd, PDO::PARAM_INT);
// execute query
$stmt->execute();
echo '<br /><ul>';
// select data from db
while($aRow = $stmt->fetch(PDO::FETCH_ASSOC))
{
echo '<h4><li>'. $aRow['Titel'] .'</li>
</h4>';
}
echo '</ul>';
if($stmt->rowCount() == 0)
{
echo '<p>Er zijn nog geen blogposts toegevoegd.</p>';
}
}
?>
Is that safe? And what should I do with this? Just leave it?
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Strange code, but if You want use it change if statement to:
if($_MULT[0] == 'blog' && ! empty($_MULT[1])) { ... }
if(ctype_digit( (string) $_MULT[1])) { ... }