Converting PHP query to PDO query - php

I have some php that is receiving a variable from jquery and querying the DB. I recently learned that I need to use PDO to prevent SQL Injections and such so I have been trying to convert my query to it. I am new at php anyway so this is turning out to be more difficult than I thought (even though all the articles I read looked quite straightforward)...The DB connection is working and 'name' is receiving the right value but it is not updating the page like it used to. I am guessing it has to do with my loop that contains the json_encode. Below is my old php and then my attempt at turning it into PDO format.
Old PHP:
$dbstylename = $_POST['name'];
$result = mysql_query("SELECT * FROM style where stylename like '$dbstylename'");
$array = mysql_fetch_row($result);
echo json_encode($array);
mysql_close($con);
?>
New PDO attempt:
<?php
include 'db.php';
try {
$dbConnection = new PDO('mysql:host=$dbhost;dbname=$dbhost;', $user, $pass);
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
#Prepare the query
$dbstylename = $_POST['name'];
$result = $dbConnection->prepare('SELECT * FROM style where stylename like :dbstylename');
#bind
$result->bindParam(':dbstylename', $dbstylename, PDO::PARAM_STR);
#execute
if ($result->execute(array($dbstylename))) {
while ($row = $result->fetch()) {
json_encode($row);
}
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
?>
================UPDATE==============================
In addition to #MadaraUchiha great answer and follow up help I had to change my jQuery from this (which worked before PDO):
$.ajax({
url: '../test.php',
type: 'POST',
data: {'name' : target},
dataType: 'json',
success: function(data) {
var styleid = data[0];
var stylename = data[1];
var stylecss = data[2];
$('#codeTest').html("<b>id: </b><br />"+styleid+"<br /><b> stylename: </b><br />"+stylename+"<br /><b> stylecss: </b><br />"+stylecss);
}
});
To this:
$.ajax({
url: '../test.php',
type: 'POST',
data: {'name' : target},
dataType: 'json',
success: function(data) {
var styleid = data.styleid;
var stylename = data.stylename;
var stylecss = data.stylecss;
$('#codeTest').html("<b>id: </b><br />"+styleid+"<br /><b> stylename: </b><br />"+stylename+"<br /><b> stylecss: </b><br />"+stylecss);
}
});

Let me start with this, it's great that you're working on improving from the old ext/mysql to PDO. Well done!
Well, first, you don't need to check for errors! Since you've set PDO::ATTR_ERRMODE to PDO::ERRMODE_EXCEPTION, an Exception would be thrown if there's an error! so your if statement on
if ($result->execute(array($dbstylename))) {
Is redundant.
Second, since you've already bound the parameter with bindParam, passing it again with the array is also redundant.
Lastly, if you only expect one result, you can drop the while loop, or even use $result->fetchAll(PDO::FETCH_ASSOC) to fetch all of the result into a single array.
Now for the real problem, you aren't echoing the result of json_encode(), like you used to in the first script (You're just calling it without doing anything with the result).
Corrected code, with all of the above taken into account:
<?php
include 'db.php';
try {
$dbConnection = new PDO('mysql:host=$dbhost;dbname=$dbhost;', $user, $pass);
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
#Prepare the query
$dbstylename = $_POST['name'];
$result = $dbConnection->prepare('SELECT * FROM style where stylename like :dbstylename');
#bind
$result->bindParam(':dbstylename', $dbstylename, PDO::PARAM_STR);
#execute
$result->execute();
$row = $result->fetch(PDO::FETCH_ASSOC);
echo json_encode($row);
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
?>
Other than that, you're PDO code is flawless, keep it up!

Also sequence of json encoded strings with array elements are not equal to hole json encoded array. Replace while loop with
echo json_encode($result->fetchAll());

In my original post I mentioned my jQuery change. However, I read up a bit more about PDO in the manual (specifically: http://www.php.net/manual/en/pdostatement.fetch.php) and found that if I changed $row = $result->fetch(PDO::FETCH_ASSOC); from #MadaraUchiha answer to $row = $result->fetch(PDO::FETCH_BOTH); I could keep my original jQuery that used the array/bracket notation.

Related

JSON not encoding as json or UTF-8?

I am having some headaches with JSON not returning as JSON. I get no errors, just no data. The browser shows the data in the response.
I know it's not returning as JSON because setting the dataType in the AJAX section causes it to display nothing. If I remove the dataType statement, it displays the data.
I've played around with encoding in the connection string, in the queries, as a header, and in the AJAX section all to no avail. My database is in UTF-8, general_ci.
AJAX:
$.ajax({
contentType: 'application/json; charset=UTF-8',
data: {'career' : $career},
dataType: 'json',
url: 'functions.php',
success: function(data) {
$("careerdata").html(data);
},
PHP:
if (isset($_GET['career'])) {
require_once 'config.php';
$query = $dbconnect->prepare("select * from jobs where Category = :category");
$query->bindParam(':category', $category);
$category = $_GET['career'];
$query->execute();
$result = $query->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($result);
$dbconnect = null;
return;
} else {
echo 'No career data found.';
};
Connection file:
try {
$dbconnect = new PDO("mysql:host=$host;dbname=$database", $user, $pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$dbconnect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
};
If any more info is needed, please let me know.
Working page is https://www.shardsmith.com/career.php and the actual query is https://www.shardsmith.com/functions.php (but it won't work independently because of the GET variable).
It seems that the MySQL (php) client does assume another client encoding than UTF-8. You can request the correct encoding using
$dbhconnect->exec("SET NAMES utf8");
directly after you connect to the database.
Alternatively, you can use PDO::MYSQL_ATTR_INIT_COMMAND (see http://php.net/manual/de/ref.pdo-mysql.php) in your connection config:
$dbconnect = new PDO("mysql:host=$host;dbname=$database", $user,
$pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
And be careful with unchecked frontend parameters: this is an open door for SQL injections. Either use a prepared statement like this:
$query = $dbconnect->prepare("select * from jobs where Category = :cat");
$query->execute(array(':cat' => $_GET['career']));
or escape the input paramerers first:
$cat = $dbhconn->quote($_GET['career']);
$res = dbhconnect->query("select * form jobs where Category = {$cat}")->fetchAll();
I ended up figuring it out myself. The json itself was fine. At some point I completely forgot about each-looping through the key-value pairs in order to actually display them. For example:
$.each(data, function(key,value) {
var $itemid = value.ItemID;
var $db = value.DB;
var $job = value.Job;
var $recipe = value.Recipe;
var $level_range = value.Level_Range;
var $level = value.Level;
var $grade = value.Grade;
var $rarity = value.Rarity;
var $complete = value.Complete;
$("careerdata table").append("<tr class=\"recipe\" id=\""+$recipe+"\">"
+"<td>"+$level+$grade+"</td>"
+"<td class=\"icon\"><img style=\"background: url(\'/images/items/"+$job+"/"+$itemid+".png\') 0 1px/42px 42px;\" src=\"/images/items/reflection.png\" /></td>"
+"<td class=\""+$rarity+"\">"+$recipe+"</td>"
+"<td><input class=\"complete\" type=\"checkbox\" value=\""+$complete+"\"></td>"
+"</tr>");
});

json_encode() isn't sending data back to AJAX call

So I'm trying to create and implement a live search function. Here's my PHP code.
<?php
ini_set('display_errors', 1);
error_reporting(~0);
define('DB_USER', '*****');
define('DB_PASSWORD', '*****');
define('DB_SERVER', 'localhost');
define('DB_NAME', 'MUSIC');
if (!$db = new mysqli(DB_SERVER, DB_USER, DB_PASSWORD, DB_NAME)) {
die($db->connect_errno.' - '.$db->connect_error);
}
$arr = array();
$sql = "SELECT * FROM main WHERE titles LIKE '%%'";
$result = $db->query($sql) or die($mysqli->error);
if ($result->num_rows > 0) {
while ($obj = $result->fetch_object()) {
$arr[] = array('title' => $obj->titles);
}
}
echo json_encode($arr);
?>
The script I'm calling:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#keyword').on('input', function() {
var searchKeyword = $(this).val();
if (searchKeyword.length >= 3) {
$.post('search.php', { keywords: searchKeyword }, function(data) {
alert("Here");
$('ul#content').empty()
$.each(data, function() {
alert("Here as well");
$('ul#content').append('<li>' + this.title + '</li>');
});
}, "json");
}
});
});
</script>
And the little portion of HTML that applies to the code:
<form role="form" method="post">
<input type="text" class="form-control" id="keyword" placeholder="Enter keyword"></form><ul id="content"></ul>
Now in this, my script isn't receiving any data, at least not to get it to signal the "alert("Here as well")". However, the first "alert("Here")" does come up. Additionally, I know the script is entering search.php, as I tested it with inserting into my database, and it did insert on every keyup. Any ideas why it isn't returning any data? The database entries have a title, an artist, and an ID right now.
You'll notice in the script that there was a "keyword" setting that gets sent in. I removed this since I thought it was unnecessary when I'm just trying to get it to send (usually the keyword would be in the LIKE portion of the SQL statement). However could this be causing the problem? Couldn't see how.
Thanks for the help.
First thing, never use or die(), especially with the mysqli constructor (hint: it will never be falsy).
Second, if you encounter an error, you should respond in such a way that external consumers (such as your JS application) can understand that an error has occurred.
Third, use a prepared statement with parameter binding. This should go without saying.
<?php
// these should really be set in your environment's php.ini
ini_set('display_errors', 'On');
error_reporting(E_ALL);
// set mysqli to throw exceptions
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$db = new mysqli('localhost', '*****', '*****', 'MUSIC');
$stmt = $db->prepare("SELECT `id`, `titles` from `main` WHERE `titles` LIKE CONCAT('%', ?, '%')");
$stmt->bind_param('s', $_POST['keywords']);
$stmt->execute();
$stmt->bind_result($id, $titles);
$response = [];
while($stmt->fetch()) {
$response[] = ['id' => $id, 'title' => $titles];
}
$stmt->close();
header('Content-type: application/json');
echo json_encode($response);
exit;
} catch (Exception $e) {
http_response_code(500);
echo $e;
}
Of course, if your query doesn't contain any results, your JS $.each will not iterate anything. You'd need to handle such a case client-side by checking data.length.
Looks to me like you should also try FULLTEXT indexing and a MATCH query instead of LIKE.

Why im not receiving data to php? Undefined index

I'm trying to send a value from my phonegap app via ajax to php and then check that value with my sql db. Now since there is an undefined index gli2 the php file won't even receive or send data to my sql db, but it will give me the result 'You can eat'. Can somebody help my ?
Here is my php file:
<?php
$conn = new mysqli('localhost', 'root', '', 'test');
if ($conn->connect_error) {
die("Connection error: " . $conn->connect_error);
}
$gli2 = $_POST['gli2'];
$result = $conn->query("SELECT smt FROM product WHERE smt='${gli2}' and BarCode =0");
$row = $result->fetch_assoc();
if ($row['smt'] == '0' ) {
echo '<script language="javascript">';
echo 'alert("You can eat")';
echo '</script>';
}else{
echo '<script language="javascript">';
echo 'alert("You cannot eat")';
echo '</script>';
}
?>
And here is my ajax:
$.ajax({
type: "POST",
url: 'http://localhost/test/testing.php',
data: {gli2: document.getElementById("galima1").value,},
success: function() {
console.log('success');
},
dataType: 'application/json',
});
This is wrong syntax here:
smt='${gli2}'
You need to use, for inline variable expansion:
smt='{$gli2}'
So that the full code becomes:
$result = $conn->query("SELECT smt FROM product WHERE smt='{$gli2}' and BarCode=0");
It is also better (not compulsory) to use backticks for better readability and safety.
$result = $conn->query("SELECT `smt` FROM `product` WHERE `smt`='{$gli2}' and `BarCode`=0");
See the position of the { and $. This is not like Rails or other templating engines. Also, your code is susceptible to SQL Injection Attack. It would be better to pass $gli2 to the built-in function mysqli_real_escape_string() to get it cleaned.
The variable in query ${gli2} does not evaluate to anything.
As it has a curly brace after $ sign.
Change
$result = $conn->query("SELECT smt FROM product
WHERE smt='${gli2}' and BarCode =0");
To
$result = $conn->query("SELECT smt FROM product
WHERE smt='{$gli2}' and BarCode =0");

Try to return JSON data generated with SQL statement from PHP script to JS webpage but get null instead

I want to return JSON data from a resulted SQL statement in a PHP script upon pressing Submit button, but I receive null instead.
I'll be using the returned JSON to filter-show markers on my Google Map, but for now I just want to get the data back across to my jQuery page from PHP script so I can manipulate/use it.
Submit button:
HTML
<input type="submit" id="filter" value="Filter" />
JS
$('#myform').on('submit', function(e) {
e.preventDefault();
var myData = $('#myform').serializeArray();
$.getJSON('myscript.php', myData, function(json){
alert(json);// actually filter for later
});
});
PHP script:
// action is a hidden form control I use to check if form was submitted
if(isset($_POST["action"])){
if(isset($_POST["color"]) && isset($_POST["zipcode"])){
// try to open a connection to a MySQL server
$connection = mysql_connect($host, $username, $password) or die("Could not connect" . mysql_error());
// select the active MySQL database to work with
$db_selected = mysql_select_db($database, $connection) or die("Can\'t use db:" . mysql_error());
$query = 'sql statement to return resutls based on what color and zipcode was provided';
$result = mysql_query($query) or die("Can\'t do that: " . mysql_error());
}
// close connection to the database
echo json_encode($result);
mysql_close($connection);
}
You can't return the result object of a mysql_query call directly. You first have to parse it with functions like mysql_fetch_array or alike (PHP docu).
...
$result = mysql_query($query);
if ( $result === false ) {
die("Can\'t do that: " . mysql_error());
}
$retVal = array();
while( $row = mysql_fetch_array( $result ) ) {
$retVal[] = $row;
}
...
echo json_encode( $retVal );
EDIT
According to the jQuery spec for getJSON (link), the data is sent using GET parameters and not using POST. So you would have to change all the $_POST appearances in your PHP code to either $_GET or $_REQUEST.
Besides this, you should return some error messages if your variables are not set. Right now (according to your code) just an empty document is returned.
Before the echo you should declare the returned content type:
header('Content-Type: application/json');
If you want to check for the receival of the data you can use:
$.ajax({
url: url,
data: myData,
success: function(json) {},
error: function(json) {} // this should allow you to check if data is received (but since the content type is set to text/html and $.getJSON expectr application/json it won't be a success)
});

No data when attempting to get JSONP data from cross domain PHP script

I am trying to pull latitude and longitude values from another server on a different domain using a singe id string. I am not very familiar with JQuery, but it seems to be the easiest way to go about getting around the same origin problem. I am unable to use iframes and I cannot install PHP on the server running this javascript, which is forcing my hand on this.
My queries appear to be going through properly, but I am not getting any results back. I was hoping someone here might have an idea that could help, seeing as I probably wouldn't recognize most obvious errors here.
My javascript function is:
var surl = "http://...omitted.../pull.php";
var idnum = 5a; //in practice this is defined above
alert("BEFORE");
$.ajax({
url: surl,
data: {id: idnum},
dataType: "jsonp",
jsonp : "callback",
jsonp: "jsonpcallback",
success: function (rdata) {
alert(rdata.lat + ", " + rdata.lon);
}
});
alert("BETWEEN");
function jsonpcallback(rtndata) {
alert("CALLED");
alert(rtndata.lat + ", " + rtndata.lon);
}
alert("AFTER");
When my javascript is run, the BEFORE, BETWEEN and AFTER alerts are displayed. The CALLED and other jsonpcallback alerts are not shown.
Is there another way to tell if the jsoncallback function has been called?
Below is the PHP code I have running on the second server. I added the count table to my database just so that I can tell when this script is run. Every time I call the javascript, count has had an extra item inserted and the id number is correct.
<?php
header("content-type: application/json");
if (isset($_GET['id']) || isset($_POST['id'])){
$db_handle = mysql_connect($server, $username, $password);
if (!$db_handle)
{
die('Could not connect: ' . mysql_error());
}
$db_found = mysql_select_db($database, $db_handle);
if ($db_found)
{
if (isset($_POST['id'])){
$SQL = sprintf("SELECT * FROM %s WHERE loc_id='%s'", $loctable, mysql_real_escape_string($_POST['id']));
}
if (isset($_GET['id'])){
$SQL = sprintf("SELECT * FROM %s WHERE loc_id='%s'", $loctable, mysql_real_escape_string($_GET['id']));
}
$result = mysql_query($SQL, $db_handle);
$db_field = mysql_fetch_assoc($result);
$rtnjsonobj -> lat = $db_field["lat"];
$rtnjsonobj -> lon = $db_field["lon"];
if (isset($_POST['id'])){
echo $_POST['jsonpcallback']. '('. json_encode($rtnjsonobj) . ')';
}
if (isset($_GET['id'])){
echo $_GET['jsonpcallback']. '('. json_encode($rtnjsonobj) . ')';
}
$SQL = sprintf("INSERT INTO count (bullshit) VALUES ('%s')", $_GET['id']);
$result = mysql_query($SQL, $db_handle);
$db_field = mysql_fetch_assoc($result);
}
mysql_close($db_handle);
} else {
$rtnjsonobj -> lat = 404;
$rtnjsonobj -> lon = 404;
echo $_GET['jsonpcallback']. '('. json_encode($rtnjsonobj) . ')';
}?>
I am not entirely sure if the jsonp returned by this PHP is correct. When I go directly to the PHP script without including any parameters, I do get the following.
({"lat":404,"lon":404})
The callback function is not included, but that much can be expected when it isn't included in the original call.
Does anyone have any idea what might be going wrong here?
Thanks in advance!
Change this part of the code
jsonp: "jsonpcallback",
with:
jsonpCallback : "jsonpcallback",

Categories