I'm using an internal switch to determine the sort order of my results and have just discovered that you can't use PDO to bind certain params (like selecting a table or specifying a sort order) in this way.
So I'm now trying to return my results without binding using ->query like this (ignoring the sort part for now) :
$results = $db->query("SELECT * from tracks WHERE online = 1", PDO::FETCH_ASSOC);
But when I print_r($results) I'm just getting the PDO object statement back :
PDOStatement Object
(
[queryString] => SELECT * from tracks WHERE online = 1
)
What am I doing wrong here?
Here is my PDO connection :
protected static function getDB()
{
static $db = null;
if ($db === null) {
$dbhost = getenv('DB_HOST');
$dbuser = getenv('DB_USER');
$dbpass = getenv('DB_PASS');
$dbname = getenv('DB_NAME');
try {
$db = new PDO("mysql:host=$dbhost;dbname=$dbname;charset=utf8mb4",
$dbuser, $dbpass);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
}
}
return $db;
}
the statement needs to be executed ...
$stmt = $db->query("SELECT * from tracks WHERE online = 1");
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
passing it as second argument should also work:
$stmt = $db->query("SELECT * from tracks WHERE online = 1", PDO::FETCH_ASSOC);
$data = $stmt->fetchAll();
or as one-liner:
$data = $db->query("SELECT * from tracks WHERE online = 1")->fetchAll(PDO::FETCH_ASSOC);
there's also:
$stmt->setFetchMode(PDO::FETCH_ASSOC);
PDO::query manual shows you how to work with results, returned by query method:
$results = $db->query("SELECT * from tracks WHERE online = 1", PDO::FETCH_ASSOC);
foreach ($results as $row) {
print $row;
}
Related
Function getUsers_Test() can retrieve data with the limit of 10 rows only while my getUsers_Orig() cannot retrieve any records **my record in the database is almost 50 rows*. No error, no warning. (PHP version 5.5.12)
function getUsers_Test(){
$sql = "SELECT TOP 10 a.user_name, a.user_level, a.user_status, b.* FROM user_access a, user_details b WHERE a.emp_code = b.emp_code ORDER BY a.id DESC";
try{
$data = array();
$db = null;
$db = connectDB();
$stmt = $db->prepare($sql);
$stmt->execute();
$data = $stmt->fetchAll();
}catch(PDOException $e){
$data['message'] = "Error: " . $e;
}
echo json_encode($data);
}
function getUsers_Orig(){
$sql = "SELECT a.user_name, a.user_level, a.user_status, b.* FROM user_access a, user_details b WHERE a.emp_code = b.emp_code ORDER BY a.id DESC";
try{
$data = array();
$db = null;
$db = connectDB();
$stmt = $db->prepare($sql);
$stmt->execute();
$data = $stmt->fetchAll();
}catch(PDOException $e){
$data['message'] = "Error: " . $e;
}
echo json_encode($data);
}
function connectDB() {
$dbuser = "myusername";
$dbpass = "mypassword";
$dbh = new PDO('odbc:databaseName', $dbuser, $dbpass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbh;
}
You could try catching a general exception instead of the PDOException
try
{
// ...
} catch (\Exception $e) {
// ...
}
The size of data is not a problem here, the data I was fetching has a special character (A‘ for Ñ). I use to add charset UTF-8 in my connection but still, I wasn't able to fetch it.
This problem occurs when I perform Generate Script and extract data from MSSQL instead of Backup and Restore. So when I execute the script from the Generate Script feature of MSSQL, the character changed and I didn't notice it.
Here's the relevant piece of my PHP code:
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//get values from AJAX
$whereCategory = isset($_GET['cat_code'])? "{$_GET['cat_code']}" : '';
$sortvalue = isset($_GET['sortvalue'])? "{$_GET['sortvalue']}" : '';
$sortorder = isset($_GET['sortorder'])? "{$_GET['sortorder']}" : '';
$sql = "select * from {$table} where cat_code = ':cat_code' order by ':sortvalue' ':sortorder';";
$stmt2 = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY) );
$stmt2->execute(array(':cat_code' => $whereCategory,':sortvalue' => $sortvalue, ':sortorder' => $sortorder));
$result = $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
header('Content-type: application/json');
echo json_encode($result);
If I var_dump the variables $where_category,$sortorder, and $sortvalue, they are all what I expect and the correct data that would need to be passed in the query. I've tried the query directly without PDO just substituting in the correct variables and I get back what I want, but apparently I'm not sending the variables correctly with my PDO methods (such as they are).
I'm getting no errors back, but no data returned either.
Any suggestions?
First off, named placeholders doesn't need to be quoted, so ditch those.
Secondly, you cannot bind identifiers (table/columns/DESC/ASC) You could only whitelist those.
Third, don't mix ->query() and ->execute(). Use ->execute() alone:
header('Content-type: application/json');
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//get values from AJAX
if(isset($_GET['cat_code'], $_GET['sortvalue'], $_GET['sortorder'])) {
$whereCategory = $_GET['cat_code'];
$sortvalue = $_GET['sortvalue'];
$sortorder = $_GET['sortorder'];
// super simple filtering
$default_tables = array('table1', 'table2', 'table3');
$default_columns = array('column1', 'column2', 'column3');
in_array(needle, haystack)
if(
in_array($table, $default_tables) &&
in_array($sortvalue, $default_columns) &&
in_array($sortorder, array('ASC', 'DESC'))
) {
// good to go
$sql = "SELECT * FROM $table where cat_code = :cat_code ORDER BY $sortvalue $sortorder";
$stmt2 = $dbh->prepare($sql);
$stmt2->execute(array(':cat_code' => $whereCategory));
echo json_encode($stmt2->fetchAll(PDO::FETCH_ASSOC));
} else {
// did not satisfy condition
}
}
Sidenote: Those default tables and columns are just examples, you'll need to populate and correspond it into yours. You could create your own method/function which creates a map with tables with their corresponding columns if you really want to be sure of it.
Change this -
$result = $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
to this -
$result = $stmt2->fetchAll(PDO::FETCH_ASSOC);
You're trying to run the query again when all you need to do is grab the results.
The query you are running is against a prepared statement which is incorrect, removing the query and assigning the result from the execute statement will work. There's also quite a few other problems in your php. Also using the input directly from the user such as the table (which appears to be undefined in this code snippet), sort order and sort value leaves you open to sql injection.
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//get values from AJAX
$whereCategory = isset($_GET['cat_code'])? $_GET['cat_code'] : '';
$sortvalue = isset($_GET['sortvalue'])? $_GET['sortvalue'] : '';
$sortorder = isset($_GET['sortorder'])? $_GET['sortorder'] : '';
/** you cannot use prepared statements for doing the order by */
$sql = "select * from $table where cat_code = :cat_code order by $sortvalue $sortorder;";
$stmt2 = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY) );
$query = $stmt2->execute(['cat_code' => $whereCategory]);
/** below line isn't needed because above on deals with it */
//$dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
$result = $query->fetchAll();
header('Content-type: application/json');
echo json_encode($result);
try without quotes:
$sql = "select * from {$table} where cat_code = :cat_code order by :sortvalue :sortorder;";
Use Like this
$result = $stmt2->fetchAll(PDO::FETCH_ASSOC);
I am trying to query out a result, it works in SQL query, but I'm trying to get the result using PHP
SELECT prs_amtdb FROM `prs` WHERE prs_amtcrck = 0
Using mysqli
Note: Make sure you bind your value. mysqli does not automatically
secure your query
$connection= mysqli_connect($host, $user, $password, $database);
$query="SELECT prs_amtdb FROM prs WHERE prs_amtcrck = 0";
$result= mysqli_query($connection, $query);//$connection is your database
//connection
//fetch the result
while($row= mysqli_fetch_array($result)){
echo $row['column_name'].'<br/>';
}
Using PDO:
$query = $db->query("SELECT `prs_amtdb` FROM prs WHERE `prs_amtcrck` = 0");
$results = $query->fetchAll();
foreach($results as $result) {
echo $result;
}
http://php.net/manual/en/pdo.query.php
If you have user input that you're using in your query you should always use prepared statements eg:
$query = $db->prepare("SELECT `prs_amtdb` FROM prs WHERE `prs_amtcrck` = :atmcrck");
$query->bindParam(':atmcrck', 0); // 0 will be the user input
$query->execute();
$results = $query->fetchAll();
foreach($results as $result) {
echo $result;
}
Make sure you have a database connection setup in PDO:
try {
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
} catch (PDOException $e) {
die($e->getMessage());
}
http://php.net/manual/en/pdo.connections.php
i'm building an website using php and html, im used to receiving data from a database, aka Dynamic Website, i've build an CMS for my own use.
Im trying to "simplify" the receiving process using php and functions.
My Functions.php looks like this:
function get_db($row){
$dsn = "mysql:host=".$GLOBALS["db_host"].";dbname=".$GLOBALS["db_name"];
$dsn = $GLOBALS["dsn"];
try {
$pdo = new PDO($dsn, $GLOBALS["db_user"], $GLOBALS["db_pasw"]);
$stmt = $pdo->prepare("SELECT * FROM lp_sessions");
$stmt->execute();
$row = $stmt->fetchAll();
foreach ($row as $row) {
echo $row['session_id'] . ", ";
}
}
catch(PDOException $e) {
die("Could not connect to the database\n");
}
}
Where i will get the rows content like this: $row['row'];
I'm trying to call it like this:
the snippet below is from the index.php
echo get_db($row['session_id']); // Line 22
just to show whats in all the rows.
When i run that code snippet i get the error:
Notice: Undefined variable: row in C:\wamp\www\Wordpress ish\index.php
on line 22
I'm also using PDO just so you would know :)
Any help is much appreciated!
Regards
Stian
EDIT: Updated functions.php
function get_db(){
$dsn = "mysql:host=".$GLOBALS["db_host"].";dbname=".$GLOBALS["db_name"];
$dsn = $GLOBALS["dsn"];
try {
$pdo = new PDO($dsn, $GLOBALS["db_user"], $GLOBALS["db_pasw"]);
$stmt = $pdo->prepare("SELECT * FROM lp_sessions");
$stmt->execute();
$rows = $stmt->fetchAll();
foreach ($rows as $row) {
echo $row['session_id'] . ", ";
}
}
catch(PDOException $e) {
die("Could not connect to the database\n");
}
}
Instead of echoing the values from the DB, the function should return them as a string.
function get_db(){
$dsn = "mysql:host=".$GLOBALS["db_host"].";dbname=".$GLOBALS["db_name"];
$dsn = $GLOBALS["dsn"];
$result = '';
try {
$pdo = new PDO($dsn, $GLOBALS["db_user"], $GLOBALS["db_pasw"]);
$stmt = $pdo->prepare("SELECT * FROM lp_sessions");
$stmt->execute();
$rows = $stmt->fetchAll();
foreach ($rows as $row) {
$result .= $row['session_id'] . ", ";
}
}
catch(PDOException $e) {
die("Could not connect to the database\n");
}
return $result;
}
Then call it as:
echo get_db();
Another option would be for the function to return the session IDs as an array:
function get_db(){
$dsn = "mysql:host=".$GLOBALS["db_host"].";dbname=".$GLOBALS["db_name"];
$dsn = $GLOBALS["dsn"];
$result = array();
try {
$pdo = new PDO($dsn, $GLOBALS["db_user"], $GLOBALS["db_pasw"]);
$stmt = $pdo->prepare("SELECT * FROM lp_sessions");
$stmt->execute();
$rows = $stmt->fetchAll();
foreach ($rows as $row) {
$result[] = $row['session_id'];
}
}
catch(PDOException $e) {
die("Could not connect to the database\n");
}
return $result;
}
Then you would use it as:
$sessions = get_db(); // $sessions is an array
and the caller can then make use of the values in the array, perhaps using them as the key in some other calls instead of just printing them.
As antoox said, but a complete changeset; change row to rows in two places:
$rows = $stmt->fetchAll();
foreach ($rows as $row) {
echo $row['session_id'] . ", ";
}
Putting this at the start of the script after <?php line will output interesting warnings:
error_reporting(E_ALL|E_NOTICE);
To output only one row, suppose the database table has a field named id and you want to fetch row with id=1234:
$stmt = $pdo->prepare("SELECT * FROM lp_sessions WHERE id=?");
$stmt->bindValue(1, "1234", PDO::PARAM_STR);
I chose PDO::PARAM_STR because it will work with both strings and integers.
here is the code before implementing the function,
try {
$conn = new PDO('mysql:host=localhost;dbname=dbname', 'usr', 'pass');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare('SELECT * FROM posts WHERE status= :published ORDER BY id DESC LIMIT 5');
$stmt->execute(array(':published' => 'published'));
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
$contents = $result['content'];
$title = $result['title'];
....
this works fine. Then i moved db connecting commands to separate php file(functions.php). and created this function,
function run_db($sqlcom,$exe){
$conn = new PDO('mysql:host=localhost;dbname=dbname', 'usr', 'pass');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare($sqlcom);
$stmt->execute($exe);
$data_db = $stmt->fetch(PDO::FETCH_ASSOC) ;
return $data_db;
}
Then i changed first mentioned code like this,
try {
$data_db=run_db('SELECT * FROM posts WHERE status= :published ORDER BY id DESC LIMIT 5',array(':published' => 'published'));
while ($result = $data_db) {
$contents = $result['content'];
$title = $result['title'];
Then all i got was one post repeating infinitely. Can anyone tell me how to correct this?
Change the function to this:
function run_db($sqlcom,$exe){
$conn = new PDO('mysql:host=localhost;dbname=dbname', 'usr', 'pass');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare($sqlcom);
$stmt->execute($exe);
return $stmt;
}
and the call to that function to:
try {
$stmt = run_db('SELECT * FROM posts WHERE status= :published ORDER BY id DESC LIMIT 5',array(':published' => 'published'));
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
$contents = $result['content'];
$title = $result['title'];
EDIT: Better solution is the one that jeroen advices - to return all the fetched objects at once:
function run_db($sqlcom,$exe){
$conn = new PDO('mysql:host=localhost;dbname=dbname', 'usr', 'pass');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare($sqlcom);
$stmt->execute($exe);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
Then calling this way:
try {
$data = run_db('SELECT * FROM posts WHERE status= :published ORDER BY id DESC LIMIT 5',array(':published' => 'published'));
foreach($data as $result) {
$contents = $result['content'];
$title = $result['title'];
EDIT 2: Anyway - wrapping such a logic into one function is not very good idea. now You are limited with executing of only SELECT queries and the resulting array containing always only record's associative array. What if You would like to (for any reason) retrieve the array of objects, or even only one single value? What if You would like to execute INSERT, UPDATE, DELETE queries???
If You for sure want to go this way, then I'd suppose creating a class with functions like this:
class MyPDO {
private $connection;
static $instance;
function __construct() {
$this->connection = new PDO('mysql:host=localhost;dbname=dbname', 'usr', 'pass');
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
static function getInstance() {
return self::$instance ? : self::$instance = new MyPDO;
}
// retrieves array of associative arrays
function getAssoc($sqlcom, $exe) {
$stmt = $this->connection->prepare($sqlcom);
$stmt->execute($exe);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// retrieves array of objects
function getObj($sqlcom, $exe) {
$stmt = $conn->prepare($sqlcom);
$stmt->execute($exe);
return $stmt->fetchAll(PDO::FETCH_OBJ);
}
// retireves one single value, like for SELECT 1 FROM table WHERE column = true
function getOne($sqlcom, $exe) {
$stmt = $conn->prepare($sqlcom);
$stmt->execute($exe);
return $stmt->fetchColumn();
}
// just executes the query, for INSERT, UPDATE, DELETE, CREATE ...
function exec($sqlcom, $exe){
$stmt = $conn->prepare($sqlcom);
return $stmt->execute($exe);
}
}
Then You can call it this way:
try {
$pdo = MyPDO::getInstance();
foreach($pdo->getAssoc('MySQL QUERY'), array($param, $param)) as $result) {
print_r($result);
}
} catch(\Exception $e) {
// ...
}
Just return the statement:
function run_db($sqlcom,$exe){
static $conn;
if ($conn == NULL)
{
$conn = new PDO('mysql:host=localhost;dbname=dbname', 'usr', 'pass');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
$stmt = $conn->prepare($sqlcom);
$stmt->execute($exe);
return $stmt;
}
try {
$stmt=run_db('SELECT * FROM posts WHERE status= :published ORDER BY id DESC LIMIT 5',array(':published' => 'published'));
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
$contents = $result['content'];
$title = $result['title'];
And you could also set the default fecth mode on the connection.
An alternative to the correct answers that return $stmt from the function, would be to fetch all rows in the function and use a foreach in your main code:
In function:
...
$data_db = $stmt->fetchAll(PDO::FETCH_ASSOC) ;
return $data_db;
Outside of function:
$data_db=run_db('SELECT * FROM posts WHERE status= :published ORDER BY id DESC LIMIT 5',array(':published' => 'published'));
foreach ($data_db as $result) {
$contents = $result['content'];
$title = $result['title'];
...
There are two essential problems with your code.
It connects every time it runs a query.
It returns data in only one format, while PDO can return results in dozens different formats.
Accepted answer makes it wrong, as it is just trying to reinvent PDO features, but very dirty way, with a lot of duplicated code and still failing to make it as good as with vanilla PDO.
As it said in xdazz's answer, you have to return the statement. And then use PDO's native fetch mode to get the result in desired format, using method chaining.
Also, you shouldn't add try to your code.