PDO search fails with multiple numbers - php

I'm trying to search a database using either a name OR a reference number (in the format ABC/X/012345/XX).
The name searches appear perfectly, as do reference number searches if I look for ABC or XX.
But if I search for the full reference number, no matches are found. The problem also happens with a partial reference number search containing more than one number (e.g. ABC/X/01 or even just 01).
I don't get an error message and the 'Sorry, your search returned no results' message isn't displayed, which would seem to suggest it's finding the correct entries, just not displaying them.
Can anyone spot where I'm going wrong? Thanks!
$search = $_POST['search'];
$search_term = "%".$search."%";
try {
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$STH = $DBH->prepare('SELECT user_id, name FROM users WHERE name LIKE :search_term OR ref_number LIKE :search_term');
$STH->bindParam(':search_term', $search_term, PDO::PARAM_STR);
$STH->execute();
$STH->setFetchMode(PDO::FETCH_ASSOC);
if ($STH->fetchColumn() > 0) {
while($row = $STH->fetch()) {
echo "<a href='viewprofile.php?user_id=".$row['user_id']."'>".$row['name']."</a><br/>";
}
} else {
echo '<p>Sorry, your search returned no results.</p>';
}
}
catch(PDOException $e) {
echo $e->getMessage();
}

PDOStatement::fetchColumn($index = 0) fetches a whole row and returns the $indexth column's value. If you want to test how many rows your query returns, use PDOStatement::rowCount()

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.

PHP SIMPLE DOM PDO select

I have in the database a list of links from which I want to take some data.
All the script is working, except the part when I'm taking the link from the DB and paste it in Simple DOM function.
"
include ('utile/db.php');
include_once('utile/simple_html_dom.php');
$dbh = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8;", $username, $password);
$sth = $dbh->query("SELECT link FROM pilots where year = '2007' and Contry ='CZ' and zboruri <> '101' limit 3 ");
foreach ($sth as $url) {
functie ($url['link']);
}
function functie($lin){
$linkul=file_get_html("$lin");
// pages number
$paging = $linkul->find('div[class*=paging]',0);
echo $paging;
$numar=-4;
foreach($paging->find('a') as $element=>$item){$numar++;}
echo $numar;
}
"
I receive the following error:
Fatal error: Call to a member function find() on null in C:\xampp\htdocs\para\teste.php on line 269
If I change the link manually it will work.
I think it is something related how I extract the link from DB and insert it the function.
Thank you
The issue with fetchALL in foreach.
The line changed:
foreach($sth->fetchAll() as $url){
The final code that is working:
include ('utile/db.php');
include_once('utile/simple_html_dom.php');
$dbh = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8;", $username, $password);
$sth = $dbh->query("SELECT link FROM pilots where zboruri > '101' limit 3");
foreach($sth->fetchAll() as $url){
functie ($url['link']);
}
function functie($lin){
var_dump($lin);
$linkul=file_get_html("$lin");
$paging = $linkul->find('div[class*=paging]',0);// pages number
echo $paging;
$numar=-4;
foreach($paging->find('a') as $element=>$item){$numar++;}
echo $numar;
}
Thank you for advices.
When I use PDO I use prepared statements, so the syntax on getting the result of the query is a little different... but I think that you need to fetch a row from your $sth since it would be a record set. Here's a snippit of what I do
$dbconn = new PDO('mysql:host='.$hostname.';port='.$dbPort.';dbname='.$dbName.';charset=utf8', $dbuser, $dbpass,array(PDO::MYSQL_ATTR_FOUND_ROWS => true));
$dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$result=$dbconn->prepare($query);
$result->execute($arr);
if(!$result){
// do your error handling, result is either false
// for error or contains a recordset
$errorMessage=$dbconn->errorInfo();
}
$result->setFetchMode(PDO::FETCH_ASSOC);
while($row=$result->fetch()){
// do stuff here, $row is an associative array w/ the
//keys being the column titles in your db table
print_r($row);
}

PHP Count array index and convert integer to string

I got an array taken from an mysqli query, this array contain a list of tasks. I must to count how many tasks is in the array ( so only the number of row ) and put in a icon badge as a human readable number.
try {
$db = new PDO("mysql:host=127.0.0.1;dbname=c9", "andreaem_dev", "");
//echo "Connected to database<br/>"; // check for connection
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$sql = "SELECT ID FROM data_tasks WHERE data_tasks . user = 'admin'"; //I'm selecting ID so only one element on the row is count
$result = $db->query($sql);
foreach ($result as $row) {
$row = $result->fetch(PDO::FETCH_NUM);
echo $row[0];
}
$db = null; // close the database connection
}
catch(PDOException $e) {
echo $e->getMessage();
}
With this code i get a int(2) response, the array contains 5 element and i don't know where it takes '2', even i must to convert it in a number.
Thanks in advice for help!
*sigh*
You need to use count() function in mysql. this is how databases intended to work: they count your data for you. You don't need to count by hand. You don't need to select id. You don't need to loop over results. You don't need to convert number to string. You just have to ask database to count and then get the result.
$db = new PDO("mysql:host=127.0.0.1;dbname=c9", "andreaem_dev", "");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT count(*) FROM data_tasks WHERE user = 'admin'";
$count = $db->query($sql)->fetchColumn();

PHP MySQL query not returning all results

My following SQL query in PHP does not work fully. The result only contains the first row. The query works totally fine inside PHPMyadmin, which returns me all the results.
$select = "SELECT a.setID, a.setName, a.setPrimaryLanguage, a.setSecondaryLanguage
FROM Person_Set ps, Album a
WHERE ps.Person_username = :username
AND ps.Set_setID = a.setID";
try {
$stmt = $dbh->prepare($select, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$stmt->bindValue(":username", $username, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetch();
echo json_encode($result);
unset($stmt);
} catch (Exception $e) {
echo 'Exception : ' . $e->getMessage() . "\n";
}
Besides, if I change the selection criteria to search for rows containing certain string, the result is empty (returned 'false'). Query below:
$select = "SELECT a.setID, a.setName, a.setPrimaryLanguage, a.setSecondaryLanguage
FROM Album a, Set_Card s
WHERE a.setName LIKE '%:searchText%'
AND a.setID = s.Set_setID
GROUP BY a.setID";
I have been trying different ways to connect to MySQL and get the results, like
$results = $mysqli->query($query);
instead of using PDO. However, the results are still the same. Could anyone help to point out where my mistakes are? Thank you very much!
PDOStatement::fetch — Fetches the next row from a result set
So when you just do a fetch it fetches the first row, unless you do it using a loop which changes the cursor to the next record.
You may get all the records using fetchAll method
http://php.net/manual/en/pdostatement.fetch.php
http://php.net/manual/en/pdostatement.fetchall.php
PDOStatement::fetch fetches a single row and moves pointer to the next row. You will either use $results = $stmt->fetchAll() to retrieve all results or a loop like this:
while ($result = $stmt->fetch()) {
echo json_encode($result);
}
Hi you are using fetch() function which fetch only one row instead use this code,
$select = "SELECT a.setID, a.setName, a.setPrimaryLanguage, a.setSecondaryLanguage
FROM Person_Set ps, Album a
WHERE ps.Person_username = :username
AND ps.Set_setID = a.setID";
try {
$stmt = $dbh->prepare($select, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$stmt->bindValue(":username", $username, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchall();
echo json_encode($result);
unset($stmt);
} catch (Exception $e) {
echo 'Exception : ' . $e->getMessage() . "\n";
}

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?

Categories