fetchColumn() not saving result to variable - php

So the query I am running can have 0, 1, or many results. I need to store the number of rows in a query to a variable. Using PDO I should be able to do that using the fetchColumn() method. But it is not givng ANY result. When I echo out $numrows I am getting nothing, not even a zero. I know it is probably something really small but I have been staring at this code for an hour now and I need a fresh set of eyes guys.
try {
$count = $db->prepare('SELECT COUNT(*) FROM location WHERE location.zip = :input');
$count->bindValue(':input', $input);
$numrows = $count->fetchColumn();
} catch (Exception $e) {
// Problem on MySQL PDO interaction - error message passed
$error = $e->getMessage();
}

You forgot to add just after binding the values, before fetchColumn():
$count->execute();

Related

PHP: How do I get my IF statement to work with PDO select?

I want my below PDO select to work with the bottom two IF statements?
The first IF I just want to make sure there is no error.
The second IF I want to check how many rows it returns. I know that this number of rows == 0 will not work.
Is there a way to do that?
try {
$conn = new PDO('mysql:host=localhost;dbname=zs', 'zs', 'rlkj08sfSsdf');
$conn ->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo $e->getMessage();
die();
}
$stmt = $conn->prepare("SELECT * FROM zip WHERE zip_code =:zip1");
$stmt->bindValue(':zip1', $_POST[zipcode], PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if($rows = "") {
echo "<p><strong>There was a database error attempting to retrieve your ZIP Code.</strong></p>\n";
}
if(number of rows == 0) {
echo "<p><strong>No database match for provided ZIP Code.</strong> Please enter a new ZIP Code.</p>\n";
}
You're interested only in whether there are records containing a particular value. It makes no sense to select everything and count the records in PHP. It's a waste of resources. Imagine what happens if there's a million records.
Solution you're after is to simply ask your database about the COUNT of rows containing a particular value. Your code should be quite simple:
$stmt = $conn->prepare("SELECT COUNT(*) AS num_rows FROM zip WHERE zip_code = :zip");
$stmt->bindValue(':zip', $_POST['zipcode'], PDO::PARAM_INT);
$stmt->execute();
$count = (int)$stmt->fetchColumn();
if($count)
{
echo "Success";
}
else
{
echo "Bummer";
}
Notes:
if successful, the above query will always return 1 row with 1 column, named num_rows which will be 0 for no matching records or an integer larger than 0 if there are records. If you use MySQL native driver with PHP, PHP will correctly represent this value as integer internally. I deliberately put typecasting in, you can remove it (the (int) part) if you have MySQL ND.
if something goes wrong during query execution, an exception will be thrown. The snippet doesn't cover that. You correctly set PDO in exception mode, and along with using bindValue instead of bindParam, this implies you did your research right and you're using PDO correctly which means that error handling should be implemented easily by you in this particular case.

PDO query is not working

I am trying to run a simple SELECT query. here is the query
$sql1=$conn->prepare("SELECT q.quoteid, q.customername, q.customersurname, q.timestamp, o.name
FROM quotes as q, occasions as o
WHERE q.occasionid=o.occasionid
AND companyid=1
AND q.day=:day
AND q.month=:month
AND q.year=:year
AND staffid='-1'
AND (q.complete != 'W' OR q.complete != 'Y')
AND q.online=0");
$sql1->execute($exearray);
/* here $exearray contain following value */
Array ( [:day] => 24 [:month] => 1 [:year] => 2014 )
Its not even showing any error.
If I pass static value 1 in month it is showing data.
I run this query directly on DB its working.
So I think there is no error in query.
I am running this query locally on MAMP.
have you tried to parse your month's data to string before passing to the pdo???
$exearray = array(':day'=>24, ':month'=>(string)1, ':year'=>2014);
once i faced this situation and i did this and it worked for me.
i always have this problem while i trying to use LIMIT command in mysql. i just parse my value to string or pass it through statically.
and it doesn't relevant to your MAMP. i have this problem on LAMP and WAMP too.
apparently it's a common problem which it's in PDO libraries.
and for the record don't forget to use intval() while you pass your month's variable directly to your query.
You need to fetch your result, execute only returns a boolean (true or false) whether query execution succeeded or not.
Example:
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();
/* Fetch all of the remaining rows in the result set */
print("Fetch all of the remaining rows in the result set:\n");
$result = $sth->fetchAll();
print_r($result);
from: http://php.net/manual/en/pdostatement.fetchall.php
Perhaps doing it the "long-way" with the parameters, and/or changing the query to use a join would help.
Also, the try/catch on PDOException might provide more information.
Lastly, note the $cmd->fetch(PDO::FETCH_ASSOC) invoked for iterating through the recordset.
try {
$db = new PDO("mysql:host=localhost;charset=utf8", "root", "root");
$cmd = $db->prepare("
SELECT q.quoteid, q.customername, q.customersurname,
q.timestamp, o.name
FROM quotes q
LEFT JOIN occasions o on q.occasionid = o.occasionid
WHERE companyid=1
AND q.day = :day
AND q.month = :month
AND q.year = :year
AND staffid = '-1'
AND (q.complete != 'W' OR q.complete != 'Y')
AND q.online = 0
");
$cmd->bindParam(':day', 24, PDO::PARAM_INT);
$cmd->bindParam(':month', 1, PDO::PARAM_INT);
$cmd->bindParam(':year', 2014, PDO::PARAM_INT);
if ($cmd->execute()) {
while ($row = $cmd->fetch(PDO::FETCH_ASSOC)) {
echo $row['quoteid']."|".$row['customername']."|".$row['name']."<br/>";
}
} else {
echo "$cmd->execute() returned false.";
}
} catch (PDOException $e) { echo $e->getMessage(); return; }
In table month column type was Varchar.
I change that to integer and now it is working.
p.s. I have tried using (string) before variable and even double quotes and single quotes on variable value but it didn't work.
Thank you everyone. :)

MYSQL result not returning correctly

So I have a piece of code that will check if you have followed a user or not. And basically let you follow them if you haven't. So here it is
if($_SESSION['loggedIn'] == true){
$result = $con->prepare("SELECT * FROM followers WHERE follow_from = :username AND follow_to = :post_id");
$result->bindParam(':username', $username);
$result->bindParam(':post_id', $follower);
$result->execute();
$reprint = $result->fetchAll(PDO::FETCH_ASSOC);
}
print_r($reprint);
if($reprint < 1){
$stmt = $con->prepare("INSERT INTO followers (follow_from, follow_to) VALUES (:ff, :ft)");
$stmt->bindValue(':ff', $follower, PDO::PARAM_STR);
$stmt->bindValue(':ft', $username, PDO::PARAM_STR);
$stmt->execute();
}
else{
echo 'Error';
exit();
}
//Display follower
$stmt1 = $con->prepare("SELECT COUNT(*) AS count FROM followers WHERE follow_to = :username");
$stmt1->bindValue(':username', $username, PDO::PARAM_STR);
$stmt1->execute();
$likes = $stmt1->fetchAll(PDO::FETCH_ASSOC);
print_r($likes);
So when I run it once. I get the else statement echoed. My question is why does this happen? In the database I have no record, so I'd expect it to go in once. I get no errors at all. loggedIn is true. And variables are being passed through successfully.
Any ideas?
You're misusing the result you get from fetchAll(). It's an associative array, not a scalar value. It could, as you've probably guessed, be empty.
But, more significantly than that, your code has a potential race condition. What happens if two different sessions are trying to set this same followers row? (Admittedly, in a small system that is unlikely, but in a large system it might happen).
What you actually do is just the INSERT operation. If your followers row has a unique key on the (follow_from,follow_to) columns, then, if that row is already there you'll get a 'Duplicate entry' error on the INSERT. Otherwise it will just happen. You can just ignore the 'Duplicate entry' error, because all you want is for that row to make it into that table.
So your code would go like this:
$stmt = $con->prepare("INSERT
INTO followers (follow_from, follow_to)
VALUES (:ff, :ft)");
$stmt->bindValue(':ff', $follower, PDO::PARAM_STR);
$stmt->bindValue(':ft', $username, PDO::PARAM_STR);
$result = $stmt->execute();
if ($result) {
/* this follow pair was successfully added */
} else {
/* MySQL may return the error 'Duplicate entry' */
if (false == stripos($stmt->errorCode,'Duplicate')){
echo 'Something failed in the insert: ' . '$stmt->errorCode';
}
else {
/* this follow pair was already in your table */
}
}
Pro tip: Don't use SELECT * in software; it can mess up query optimization; it often sends more data than you need from the server to your program, and it makes your program less resilient if your change your table definitions.
Pro tip: If you must count rows matching a particular WHERE statement, use COUNT() rather than fetching the rows and counting them in the client. What if you get a million rows?
You'd want to use count($reprint) other that a direct comparison. $reprint is an array, not a number
if(count($reprint) < 1)
{
$stmt = $con->prepare("INSERT INTO followers (follow_from, follow_to) VALUES (:ff, :ft)");
$stmt->bindValue(':ff', $follower, PDO::PARAM_STR);
$stmt->bindValue(':ft', $username, PDO::PARAM_STR);
$stmt->execute();
}
else
{
echo 'Error';
exit();
}
PDOStatement::fetchAll
PDOStatement::fetchAll — Returns an array containing all of the result set rows
If you check the size of the array then you would actually know if something happened.
Using proper error handling can tell you if something's failing deep down:
try
{
...
}
catch (PDOException $e)
{
echo $e->getMessage();
}
You will need to enable PDO error-displaying:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
If checking the size of the array doesn't do it and you get no errors then it's simply some logic error.
Most likely the logic error is that
$reprint = $result->fetchAll(PDO::FETCH_ASSOC);
doesn't get executed (wrapping the error handling around that should tell you why), so
$reprint = $result->fetchAll(PDO::FETCH_ASSOC);
isn't given a proper value, meaning you'll always hit the else statement.
Edit
Your original problem was that "So when I run it once. I get the else statement echoed. [...] In the database I have no record" but now you're saying "It adds the record, but doesn't limit it to me one".
Can you be more clear about the actual, current, problem?

PDO::exec() blocking further query from working

I'm trying to implement pagination using PHP. I found that calling exec to the connected database prevents the further query calls from working.
The piece of code at hand:
<?php
// Pagination logic
//Here we count the number of results
$query = "SELECT COUNT(*) as num FROM gig";
$total_pages = $db->exec($query);
$total_pages = $total_pages[num];
?>
After it if I try to use a query such as:
<?php>
foreach ($db->query("SELECT sname, start, venue FROM gig WHERE start = '0000-00-00 00:00:00'") as $a) {
$row="<tr><td>$a[sname]</td><td>To be announced</td><td>$a[venue]</td></tr>\n";
print $row;
}
?>
it returns
Warning: Invalid argument supplied for foreach()
As soon as the first code block is removed, the query works fine. When I check the value of $total_pages, it's 0, so something must be going wrong along the way. As far as I know, I use it in the same way as the query(which works on its own), so is there any reason why it doesn't work?
The PDO is initialized in the following way:
try {
$db = new PDO("mysql:dbname=$db_name;host=$db_server", $db_user, $db_pw);
} catch (PDOException $e) {
die('Connection failed: ' . $e->getMessage());
}
session_start();
From Manual
PDO::exec() does not return results from a SELECT statement. For a
SELECT statement that you only need to issue once during your program,
consider issuing PDO::query(). For a statement that you need to issue
multiple times, prepare a PDOStatement object with PDO::prepare() and
issue the statement with PDOStatement::execute().
Used a function of the STATEMENT object had after using querying to count the rows instead of exec:
$dbq = $db->query("SELECT * FROM gig");
$rows = $dbq->rowCount();
About the latter code block not working because of the exec failing - it seems to just be the way php queries work, if one fails, all fail. The foreach() error is for the object it's provided is not an array, for it failed.

MySQL PDO Count Rows - Can I make this more efficient?

So, I've been learning PDO. So far, I am not at all impressed, honestly, due to the large amount of code needed to do small tasks. However, I am willing to convert nonetheless if I can get my code to be efficient and reusable.
My question is this: can I make this code any more efficient? By efficient, I mean both A) take up less lines, and B) run faster. I am worried that I am going about this all wrong. However, due to the lack of a num_rows() function, I can't think of a better way.
try
{
$sth = $dbh->prepare("SELECT * FROM table_name");
$sth->execute();
if (count($result = $sth->fetchAll()))
{
foreach ($result as $value)
{
// Rows returned! Loop through them.
}
}
else
{
// No rows returned!
}
}
catch (PDOException $e)
{
// Exception!
}
Is this written properly?
As far as my research has shown, no. There is no way to rewrite this code more concisely or logically--the way it stands is entirely optimized. :) It's easy to use, so that's definitely not a bad thing!
Use PDO::query() to issue a SELECT COUNT(*) statement with the same predicates as your intended SELECT statement
Then, Use PDOStatement::fetchColumn() to retrieve the number of rows that will be returned
$sql = "SELECT COUNT(*) FROM table_name";
if ($res = $conn->query($sql))
{
/* Check the number of rows that match the SELECT statement */
$res->fetchColumn(); //This will give you the number of rows selected//
}
Make a general function that does that, and all you need to do is send a select count based on your needs. You can make in more general by dividing the $select to more variables.
function countRows($select)
{
if ($res = $conn->query($select))
{
/* Check the number of rows that match the SELECT statement */
return $res->fetchColumn(); //This will give you the number of rows selected//
}
}
No, you need to use PDO's rowCount method.
try
{
$sth = $dbh->prepare("SELECT * FROM table_name");
$sth->execute();
if ($sth->rowCount() > 0)
{
while ($result = $sth->fetch())
{
// Rows returned! Loop through them.
}
}
else
{
// No rows returned!
}
}
catch (PDOException $e)
{
// Exception!
}

Categories