Statements works in SQL, but not in PDO - mysql

I'm converting from SQL to PDO, and everything has gone well until this statement.
My SQL does what it should and does NOT output the message "This user has no private images". But for some reason, when changing to PDO, the same message is shown when it should not be.
Any ideas?
Original SQL:
$result = mysql_query("SELECT * FROM tbl_private_photos WHERE profile = $usernum AND photo_deleted != 'Yes' LIMIT 1");
if (mysql_num_rows($result)!==1) { die("This user has no private images");}
My PDO:
$sql = "SELECT * FROM tbl_private_photos WHERE profile = :usernum AND photo_deleted != 'Yes' LIMIT 1";
$q = $conn->prepare($sql); // the default way of PDO to manage errors is quite the same as `or die()` so no need for that
$q->bindValue(':usernum',$usernum,PDO::PARAM_INT);
$q->execute();
if($r = $q->fetch(PDO::FETCH_ASSOC)!==1)
{
die("This user has no private images");
}

PDO::fetch() returns in this case an array or false. You don't want to compare the fetch result explicitly to the integer 1 then assign it to a variable--it will always be true because a 1 !== array() is always true, and 1 !== false is always true.
Instead you should see if your result set is empty or false.
Try this instead:
$r = $q->fetch(PDO::FETCH_ASSOC);
if(empty($r))
{
die("This user has no private images");
}

Related

MYSQL Prepared Statements Select Row_Count

I have a simple SQL Query:
$stmt = $db_main->prepare("SELECT id FROM user WHERE username=? AND mail=? LIMIT 1");
$stmt->bind_param('ss', $username, $mail);
$stmt->execute();
And I want to know, if it found an user. So I want to count the rows found.
I already tried to use rowCount (Not safe for SELECT) or num_rows or just looking if the result id is numeric (Which '' would not be, I hoped...)
There has to be an easy way to count the selected row, hasn't be?
Check number of rows returned with:
$stmt->num_rows;
Check for instance this site.
p.s.: added as per question in comment: use fetch() in order to get the next record.
...
$stmt->execute();
$stmt->bind_result($user_id); // access id
$stmt->store_result(); // optional: buffering (see below)
if ($data = $stmt->fetch()) {
do {
print("Id: " . $user_id);
} while ($data = $stmt->fetch());
} else {
echo 'No records found.';
}
Regarding store_result() from the documentation:
"You must call mysqli_stmt_store_result() for every query ..., if and only if you want to buffer the complete result set by the client ..."

Zend Framework - join query

I build a function
public function getBannedByLogin($commentId)
{
$sql = $this->getDbAdapter()->select()
->from(array('comments' => 'comments'), array())
->join(array('users' => 'qengine_users'),
'comments.bannedBy = users.userId',
array())
->where('commentId = ?', $commentId)
;
$row = $this->fetchRow($sql);
return $row['login'];
}
And there are problems, that does'nt work! :D
Let's I explain you. Column 'bannedBy' from comments returns id of user, who give a ban. I need to join this with table users to load a login field. Where i have mistakes?
I assume the code works in the sense of not throwing an exception. If so, your code is OK, you just specifically tell Zend_Db not to select any columns.
public function getBannedByLogin($commentId)
{
$sql = $this->getDbAdapter()->select()
->from(array('comments' => 'comments'))
->join(array('users' => 'qengine_users'),
'comments.bannedBy = users.userId')
->where('commentId = ?', $commentId)
;
$row = $this->fetchRow($sql);
return $row['login'];
}
The last argument to from() and join() functions is an array of columns you wish to select. If you pass in an empty array, no columns are selected. No argument = select everything. You can, of course, specify only the columns you need too.

Function returns 1 instead of result (PDO)

I have a function which is printed below. THis is meant to dynamicly draw user data from the database using PDO (that situation is clear and all works well). But, instead of returning the result (i e. an email for you("email)), it returns the number 1.
Here's my setup:
public function you($row) {
if(isset($_COOKIE["SK"])) {
$pw = $this->baseXencode($_SESSION["password"]);
$usr = $this->baseXencode($_SESSION["username"]);
$q = "SELECT $row FROM SN_users WHERE username=':USR' AND password=':PW'";
$this->netCore->q($q);
$this->netCore->bind(":PW", $pw);
$this->netCore->bind(":USR", $usr);
$result = $this->netCore->single();
$result = $result[$row];
return $result;
} else {
$q = "SELECT $row FROM SN_users WHERE username='Anonymous' AND password='Anonymous'";
$this->netCore->q($q);
$result = $this->netCore->single();
$result = $result[$row];
return $result;
}
}
}
$this->netCore->q() = PDO query
$this->netCore->single() PDO fetch(PDO::FETCH_ASSOC)
As for ->bind, self-explanatory.
Please help, will be very much appreciated.^^
When using parametrized queries, you don't put the parameters in quotes. That prevents the parameters from being substituted, since it's treated as a literal string. So it should be:
$q = "SELECT $row FROM SN_users WHERE username=:USR AND password=:PW";
I'm surprised it's returning 1. I'd expect your code to cause an error, because single() should be returning false, and false[$row] is not valid.
You should also check that a row was returned; if the username and password are not valid, you won't get an result. So it should be:
$result = $this->netCore->single();
if ($result) {
return $result[$row];
} else {
return false;
}
And the caller of you() needs to check the value as well.

insert query through php doesn't update MySQL database

I have user input coming in from a form (possible null fields - yes, the database is set up to work with null values), and I need to insert the information into a table in the database.
Just some more information: I'm making this application in Titanium
This is the code that sends all the parameters to the PHP file:
saveButton.addEventListener('click', function() {
var xhr = Ti.Network.createHTTPClient();
var url = ""; //url is in here; I just took it out for privacy
xhr.open("GET", url);
var params = {
query : "enterAsset",
barcode : barcodeTextField.value, //all these textfields are editable by the user
assetClass : assetClassTextField.value,
manufacturer : manufacturerTextField.value,
model : modelTextField.value,
serialNum : serialNumTextField.value,
custodian : custodianTextField.value,
status : statusTextField.value,
loginName : LOGIN_NAME,
divisionID : DIVISION_ID,
dateBuy : dateBoughtTextField.value,
priceBuy : priceTextField.value,
dateInSvc : dateInServiceTextField.value,
dateLastSvc : dateLastServiceTextField.value,
};
xhr.onload = function() {
alert("Successful entry"); //this alert does appear when the button is pressed
};
xhr.send(params);
});
This is the code in the PHP file after connecting to the database:
$query = $_GET['query'];
switch($query) { //this switch statement exists so we can access the database for multiple queries from the same .php file. We know it works because the "login" query works just fine.
case "data":
//unimportant stuff is in here
break;
case "clients":
//more irrelevant stuff in here
break;
case "login": //this works, but it's not trying to insert anything
$username = $_GET['username'];
$password = $_GET['password'];
$stmt4 = $con->prepare('CALL Get_user_auth(:username,:password)');
$stmt4->bindParam(':username',$username,PDO::PARAM_STR);
$stmt4->bindParam(':password',$password,PDO::PARAM_STR);
$stmt4->execute();
$results = $stmt4->fetchAll(PDO::FETCH_ASSOC);
$stmt4->closeCursor();
break;
case "search":
//more irrelevant stuff in here
break;
case "enterAsset":
$barcode = '12345';
$assetClass = 'test';
$manufacturer = 'test';
$model = 'test';
$serialNum = 'test';
$custodian = 'test';
$locationID = '1';
$status = 'test';
$dateBuy = 'test';
$priceBuy = 'test';
$dateInSvc = 'test';
$dateLastSvc = 'test';
$loginName = 'jane';
$divisionID = '1';
$stmt6 = $con->prepare('CALL Enter_new_asset(:divisionID,:barcode,:assetClass,:manufacturer,:model,:serialNum,:custodian,:status,:locationID,:dateBuy,:priceBuy,:dateInSvc,:dateLastSvc,:loginName)');
$stmt6->bindParam(':divisionID',$divisionID,PDO::PARAM_INT,11);
$stmt6->bindParam(':barcode',$barcode,PDO::PARAM_STR,128);
$stmt6->bindParam(':assetClass',$assetClass,PDO::PARAM_STR,10);
$stmt6->bindParam(':manufacturer',$manufacturer,PDO::PARAM_STR,10);
$stmt6->bindParam(':model',$model,PDO::PARAM_STR,10);
$stmt6->bindParam(':serialNum',$serialNum,PDO::PARAM_STR,20);
$stmt6->bindParam(':custodian',$custodian,PDO::PARAM_STR,20);
$stmt6->bindParam(':status',$status,PDO::PARAM_STR,10);
$stmt6->bindParam(':locationID',$locationID,PDO::PARAM_INT,11);
$stmt6->bindParam(':dateBuy',$dateBuy,PDO::PARAM_STR,13);
$stmt6->bindParam(':priceBuy',$priceBuy,PDO::PARAM_STR,10);
$stmt6->bindParam(':dateInSvc',$dateInSvc,PDO::PARAM_STR,13);
$stmt6->bindParam(':dateLastSvc',$dateLastSvc,PDO::PARAM_STR,13);
$stmt6->bindParam(':loginName',$loginName,PDO::PARAM_STR,20);
$stmt6->execute();
$stmt6->closeCursor();
break;
default:
$results = "FAIL.";
break;
}
This returns "null" when I specify the "enterAsset" query, which is expected because it shouldn't be returning anything.
The stored query for Enter_new_asset is:
INSERT INTO TBL_ASSET_DATA (Division_ID, Barcode_Tag, Asset_Class, Manufacturer, Model, Serial_Num, Custodian, Status, Location_ID, Date_buy, Price_buy, Date_in_svc, Date_last_svc, Updated_by)
VALUES(divisionID,barcode, assetClass, manufacturer, model, serialNum, custodian, status, locationID, dateBuy, priceBuy, dateInSvc, dateLastSvc, loginName)
EDIT: I tried hardcoding in some values for the variables, and now I'm getting this error: Parse error: syntax error, unexpected '';' (T_CONSTANT_ENCAPSED_STRING) in /homepages/21/d265224452/htdocs/brillient_wordpress/AMproxy.php on line 90
This is the code at line 90:
$stmt6 = $con->prepare('CALL Enter_new_asset(:divisionID,:barcode,:assetClass,:manufacturer,:model,:serialNum,:custodian,:status,:locationID,:dateBuy,:priceBuy,:dateInSvc,:dateLastSvc,:loginName)');
My question is: Why is the database not updating with the entered information? A new entry is not appearing in the TBL_ASSET_DATA. Other questions with this issue seem to be using MySQLi or the deprecated mysql commands, and this is using PDO.
Thank you for your help in advance.
EDIT I got my database to update by replacing
$stmt6 = $con->prepare('CALL Enter_new_asset(:divisionID,:barcode,:assetClass,:manufacturer,:model,:serialNum,:custodian,:status,:locationID,:dateBuy,:priceBuy,:dateInSvc,:dateLastSvc,:loginName)');
with:
$sql = "INSERT INTO TBL_ASSET_DATA(Division_ID, Barcode_Tag, Asset_Class, Manufacturer, Model, Serial_Num, Custodian, Status, Location_ID, Date_buy, Price_buy, Date_in_svc, Date_last_svc, Updated_by) VALUES(:divisionID,:barcode, :assetClass, :manufacturer, :model, :serialNum, :custodian, :status, :locationID, :dateBuy, :priceBuy, :dateInSvc, :dateLastSvc, :loginName)";
$stmt6 = $con->prepare($sql);
but I'm wondering whether this is secure.
You seem to be missing a quote to close your string here:
$dateLastSvc = 'test;
This is making you code behave incorrectly. You can easily pick ushc typo errors if using an editor with context highlighting. For example, I could pick this up right away in looking at the highlighting that even Stack Overflow does.

PHP PDO succinct mySQL SELECT object

Using PDO I have built a succinct object for retrieving rows from a database as a PHP object with the first column value being the name and the second column value being the desired value.
$sql = "SELECT * FROM `site`"; $site = array();
foreach($sodb->query($sql) as $sitefield){
$site[$sitefield['name']] = $sitefield['value'];
}
I now want to apply it to a function with 2 parameters, the first containing the table and the second containing any where clauses to then produce the same result.
function select($table,$condition){
$sql = "SELECT * FROM `$table`";
if($condition){
$sql .= " WHERE $condition";
}
foreach($sodb->query($sql) as $field){
return $table[$field['name']] = $field['value'];
}
}
The idea that this could be called something like this:
<?php select("options","class = 'apples'");?>
and then be used on page in the same format as the first method.
<?php echo $option['green'];?>
Giving me the value of the column named value that is in the same row as the value called 'green' in the column named field.
The problem of course is that the function will not return the foreach data like that. That is that this bit:
foreach($sodb->query($sql) as $field){
return $table[$field['name']] = $field['value'];
}
cannot return data like that.
Is there a way to make it?
Well, this:
$sql = "SELECT * FROM `site`"; $site = array();
foreach($sodb->query($sql) as $sitefield){
$site[$sitefield['name']] = $sitefield['value'];
}
Can easily become this:
$sql = "SELECT * FROM `site`";
$site = array();
foreach( $sodb->query($sql) as $row )
{
$site[] = $row;
}
print_r($site);
// or, where 0 is the index you want, etc.
echo $site[0]['name'];
So, you should be able to get a map of all of your columns into the multidimensional array $site.
Also, don't forget to sanitize your inputs before you dump them right into that query. One of the benefits of PDO is using placeholders to protect yourself from malicious users.