Looping through query results with fetch(PDO::FETCH_ASSOC) - php

I have moved away from mysqli_query() due to server requirements on a new project. However, I am having issues with updating some of my queries.
Connection file
<?php
define('DB_HOST', 'localhost');
define('DB_NAME', 'nj2kfa3j_sublift');
define('DB_USER', 'nj2kfa3j_web');
define('DB_PASS', 'prum9wR4');
define('DB_CHAR', 'utf8');
class DB
{
protected static $instance = null;
protected function __construct() {}
protected function __clone() {}
public static function instance()
{
if (self::$instance === null)
{
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => FALSE,
);
$dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHAR;
self::$instance = new PDO($dsn, DB_USER, DB_PASS, $opt);
}
return self::$instance;
}
public static function __callStatic($method, $args)
{
return call_user_func_array(array(self::instance(), $method), $args);
}
public static function run($sql, $args = [])
{
if (!$args)
{
return self::instance()->query($sql);
}
$stmt = self::instance()->prepare($sql);
$stmt->execute($args);
return $stmt;
}
}
?>
Problem Query Statement:
$stmt = DB::run("SELECT * FROM admin WHERE username='$manager' AND password='$password' LIMIT 1");
$existCount = $stmt->fetchColumn();
if ($existCount == 1){
$id;
$full_name;
var_dump($stmt);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$id = $row["id"];
$full_name = $row["full_name"];
echo 'test';
}
}
I have done other queries in more or less the same way and they're working, like this:
$stmt = DB::run("SELECT * FROM categories");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
What is going on here? In the query above the var_dump() is returning:
object(PDOStatement)#2 (1) { ["queryString"]=> string(81) "SELECT * FROM admin WHERE username='********' AND password='********' LIMIT 1" }
But it is not entering the while loop and hitting the echo 'test';

Please use prepared statements. Your function is designed to accept prepared statements. Also, don't store your password as plain text; use password_hash() and password_verify().
You can fetch your results as an array with fetchall() and then count the array elements.
<?php
$params = [$manager,$password];
$sql = "SELECT * FROM admin WHERE username= ? AND password= ? LIMIT 1";
$stmt = DB::run($sql,$params);
$results = $stmt->fetchall(PDO::FETCH_ASSOC); // Returns an array
if (count($results) > 0){
$id;
$full_name;
foreach($results as $key=>$row){
$id = $row["id"];
$full_name = $row["full_name"];
echo 'test';
}
}
?>

As discussed in the comments, I was looking for an alternative to mysqli_num_rows() and found rowCount().
The following now works for me:
$stmt = DB::run("SELECT * FROM admin WHERE username='$manager' AND password='$password' LIMIT 1");
$existCount = $stmt->rowCount();
if ($existCount == 1){

Related

PHP MySQLI OOP not work

I want to ask help for my MySQLI OOP. My MySQLI Class look like this:
Class DB {
Private $connection;
Public Function __construct($host = "localhost", $user = "root", $password = "", $db = "social_network") {
$this->host = $host;
$this->db = $db;
$this->user = $user;
$this->password = $password;
$this->connection = #new mysqli($this->host, $this->user, $this->password);
$this->connection->set_charset("UTF-8");
if($this->connection->connect_errno > 0){
die('Tietokantapalvelimeen ei saada yhteyttä [' . $this->connection->connect_error . ']');
} else {
if(!$this->connection->select_db($db)) {
die('Tietokantaan ei saada yhteyttä: ' . $this->connection->error);
}
return $this->connection;
}
}
Public Function connect() {
if(!$this->connection){
return $this->connection;
}
return true;
}
Public Function disconnect() {
if($this->connection){
$this->connection->kill($this->connection->thread_id);
$this->connection->close();
}
return true;
}
Public Function query($sql) {
return $this->connection->query($sql);
}
Public Function result($sql) {
$query = $this->connection->query($sql);
if($query){
$result = array();
$i = 0;
while($row = $query->fetch_object()){
$result[$i] = $row;
$i++;
}
return $result;
} else {
return print $this->connection->error;
}
}
Public Function escape_string($sql) {
return $this->connection->real_escape_string($sql);
}
Public Function __destruct() {
$this->disconnect();
}
}
Example result:
$DB = new DB($_CONFIG['host'], $_CONFIG['user'], $_CONFIG['password'], $_CONFIG['db']);
$row = $DB->result("SELECT username, password FROM users WHERE username = T0niiiiii LIMIT 1");
print $row['username'];
I get error "Unknown column 'T0niiiiii' in 'where clause' ".
So what is wrong? How i fix that? Or anyone know ready MySQLI OOP?
If you don't wrap the value with apostrophes, MYSQL will 'think' you're referencing a column.
This should be your code:
$DB->result("SELECT username, password FROM users WHERE username = 'T0niiiiii' LIMIT 1");
You didn't even need to ask in here, the error message says it all.
And about retrieving the row, you could do this:
$query = $DB->query("SELECT username, password FROM users WHERE username = 'T0niiiiii' LIMIT 1");
foreach ($query->result() as $row)
{
echo $row->username;
echo $row->password; //Never echo the password, this is just for testing :P
}

PDO query class

I'm tinkering with a class that 'should' allow me to easily execute a fetchall query and display the results within a foreach statement. I assume all is working correctly as I have no errors. As for the foreach - this must be the problem? How would I foreach the results gained from the $connect->query()? I'm new to using any database OOP framework in my functions so I could be along the wrong lines completely.
<?
error_reporting(1);
class dbconnect {
private $host;
private $database;
private $username;
private $password;
private $pdo;
private $error;
public function __construct() {
$this->host = "localhost"; // Host
$this->database = "images"; // Database Name
$this->username = "*"; // Username
$this->password = "*"; // Password
$options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
);
try {
$this->pdo = new PDO("mysql:host={$this->host};dbname={$this->dbname};charset=utf8", $this->username, $this->password, $options);
}
catch(PDOException $e) {
$this->error = $e->getMessage();
}
}
public function query($query) {
try {
$stmt = $this->pdo->prepare($query);
$stmt->execute();
} catch(PDOException $ex) {
die("Failed to run query: " . $ex->getMessage());
}
$rows = $stmt->fetchAll();
return $rows;
}
}
$connect = new dbconnect;
$rows = $connect->query("select * from photos");
foreach($rows as $row):
print $row['id'];
endforeach;
?>
The $rows variable you're declaring inside query is not accessible to the outside, it is local to that function. Most likely, you simply want to return those results to the caller:
$rows = $stmt->fetchAll();
return $rows; // return value from function...
and have the caller capture that return value in its own variable:
$rows = $connect->query("select * from images"); // ... is received by caller
foreach($rows as $row):
Also check out dougjore's answer, you're mixing $this->stmt and $stmt inside your query method.
Pretty sure you aren't ever actually executing the query:
$this->stmt = $this->pdo->prepare($query);
$stmt->execute();
I believe (I could be wrong, I'm rather new to PDO myself and I haven't built a class for it), that you need to say $this->stmt->execute();
You could do
//PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set
$this->stmt = $this->pdo->prepare($query);
$this->stmt->execute();
while ($result = $this->stmt->fetch(PDO::FETCH_ASSOC))
{
//do something with the result
}
Have a look here for more options to fetch PDO query results:
http://php.net/manual/en/pdostatement.fetch.php
$connect = new dbconnect;
$sql="select * from photos";
$stmt=$connect->pdo->prepare($sql);
$stmt->execute();
$result=$stmt->fetch(PDO::FETCH_ASSOC);
foreach($result as $key => $value) {
echo $key . "-" . $value . "<br/>";
}

How To Return mysqli_fetch_assoc in While Loop As Variable in PHP Function?

I have this PHP function :
function userParent($Username)
{
global $con;
$Result = mysqli_query($con, "SELECT Username FROM Family WHERE Parent = '$Username' LIMIT 10");
$row = mysqli_fetch_assoc($Result);
return $row;
}
that function should give me 10 rows in array, but why I just have a value in array? I tried to test that codes outside function bracket and try to add WHILE loop like this :
while ($row = mysqli_fetch_assoc($Result)){
print_r($row);
}
and it works. I got my 10 rows in array format. but it prints the result to the screen. how to make it as variable so it can be returned in function?
thanks.
UPDATE : according to Phil's answer, now here's my complete code :
<?php
function userParent(mysqli $con, $username) {
$stmt = $con->prepare('SELECT Username FROM Family WHERE Parent = ? LIMIT 10');
$stmt->bind_param('s', $username);
$stmt->execute();
$res = $stmt->get_result();
return $res->fetch_all(MYSQLI_ASSOC);
}
$DbServer = 'localhost';
$DbUser = 'username';
$DbPassword = 'password';
$DbName = 'dbname';
$mysqli = new mysqli($DbServer, $DbUser, $DbPassword, $DbName);
$arrayParent = userParent($mysqli, 'root');
print_r($arrayParent);
?>
but I got this error message :
Fatal error: Call to undefined method mysqli_stmt::get_result() in /home/myhome/public_html/test.php on line 6
Use return:
function userParent(mysqli &$dbms, $username){
// You need to "escape" strings, which you would use in direct queries.
// OR BETTER: use mysqli prepared statements with parameter binding.
$username = mysqli_real_escape_string($dbms, $username);
$result = mysqli_query($dbms, "SELECT Username FROM Family WHERE Parent = '$username' LIMIT 10");
// Create temporary array for resultset:
$buffer = array();
// Fetch data to temporary buffer:
while ($row = mysqli_fetch_assoc($result)){
$buffer[] = $row;
}
// Free result set:
$result->free();
// Return buffer to global scope:
return $buffer;
}
$users = userParent($con, 'John');
var_dump($users);
Try mysqli_result::fetch_all instead
function userParent(mysqli $con, $username) {
$stmt = $con->prepare('SELECT Username FROM Family WHERE Parent = ? LIMIT 10');
if ($stmt === false) {
throw new Exception($con->error, $con->errno);
}
$stmt->bind_param('s', $username);
$stmt->execute();
$res = $stmt->get_result();
return $res->fetch_all(MYSQLI_ASSOC);
}
Then call it like this
$parents = userParent($mysqli, 'some username');
Read these in case you're not aware of prepared statements and parameter binding
http://www.php.net/manual/en/mysqli.prepare.php
http://www.php.net/manual/en/mysqli-stmt.bind-param.php
Update
Apparently (undocumented), the mysqli_stmt::get_result() method is only available when using the mysqlnd driver. If you cannot use this driver, try this alternative
function userParent(mysqli $con, $username) {
$stmt = $con->prepare('SELECT Username FROM Family WHERE Parent = ? LIMIT 10');
if ($stmt === false) {
throw new Exception($con->error, $con->errno);
}
$stmt->bind_param('s', $username);
$stmt->execute();
$parent = null;
$parents = array();
$stmt->bind_result($parent);
while($stmt->fetch()) {
$parents[] = $parent;
}
return $parents;
}

Converting MySQL connector to PDO

After taking some advice from people on here in a previous thread, I'm trying to convert my MySQL to PDO, but am running into some issues.
Here is my original MySQL connection class:
class DbConnector {
public static function getInstance() {
static $instance = null;
if ($instance === null) {
$instance = new DbConnector();
}
return $instance;
}
protected $theQuery;
private $link;
function DbConnector() {
$host = 'localhost';
$db = '';
$user = '';
$pass = '';
// connect to the db
$this->link = mysql_connect($host, $user, $pass);
mysql_select_db($db);
register_shutdown_function(array(&$this, 'close'));
}
public function find($query) {
$ret = mysql_query($query, $this->link);
if (mysql_num_rows($ret) == 0)
return array();
$retArray = array();
while ($row = mysql_fetch_array($ret))
$retArray[] = $row;
return $retArray;
}
public function insert($query) {
$ret = mysql_query($query, $this->link);
if (mysql_affected_rows() < 1)
return false;
return true;
}
public function query($query) {
$this->theQuery = $query;
return mysql_query($query, $this->link);
}
public function fetchArray($result) {
return mysql_fetch_array($result);
}
public function close() {
mysql_close($this->link);
}
public function exists($query) {
$ret = mysql_query($query, $this->link);
if (mysql_num_rows($ret) == 0)
return false;
}
public function last_id($query) {
return mysql_insert_id($query);
}
}
Here is the function that I'm writing:
function getRandomSubmission() {
global $db;
if(!empty($_GET['id'])){
$submission_id = $_GET['id'];
$query = $db->find("
SELECT
*
FROM
`submissions`
WHERE id = '{$submission_id}'
LIMIT 1
");
}
else {
$query = $db->find("
SELECT
*
FROM
`submissions`
ORDER BY RAND()
LIMIT 1
");
}
if($query) {
return $query[0];
}
else {
$query = $db->find("
SELECT
*
FROM
`submissions`
ORDER BY RAND()
LIMIT 1
");
}
}
Here is the PDO connector:
$host = 'localhost';
$username = '';
$pass = '';
$db = '';
try {
$dbh = new PDO("mysql:host=$host;dbname=$db", $username, $pass);
} catch (PDOException $e) {
echo $e->getMessage();
}
Here is what I've tried to convert it to, but it's just plain wrong. I think I need to be returning a PDO associative array in the 2nd if statement, but am not sure.
function getRandomSubmission() {
global $dbh;
if(!empty($_GET['id'])){
$submission_id = $_GET['id'];
$stmt = $dbh->prepare('
SELECT
*
FROM
`submissions`
WHERE
`id` = ?
LIMIT 1
');
$stmt->bindParam(1, $submission_id, PDO::PARAM_INT);
$stmt->execute();
}
else {
$stmt = $dbh->prepare('
SELECT
*
FROM
`submissions`
ORDER BY RAND()
LIMIT 1
');
$stmt->execute();
}
if($stmt) {
return $stmt[0];
}
else {
$stmt = $dbh->prepare('
SELECT
*
FROM
`submissions`
ORDER BY RAND()
LIMIT 1
');
$stmt->execute();
}
}
The original one works as intended, however (I realize I left the connection details blank).
You need to call fetch method of the PDOStatement object:
return $stmt->fetch()
Read about the fetch style, really you don't need FETCH_BOTH ;-)

What is the simplest way to return a ROW as well as loop through the ROWS with PDO?

If I am doing an old query to return a row I would do something like this:
$sql = 'SELECT id FROM table WHERE email="' . mysql_real_escape_string($email) . '" LIMIT 1';
$res = mysql_query($sql);
$row = mysql_fetch_array($res);
echo $row['id'];
How do I do that with a Prepared Statement? I can get this far...
$stmt = $dbh->prepare("SELECT id FROM table WHERE email = ? LIMIT 1");
if ($stmt->execute(array($_POST['email']))) {
// what goes in here to pull out this one row?
}
Secondly, if I have multiple rows I would do it like this:
$sql = 'SELECT id FROM table WHERE email="' . mysql_real_escape_string($email) . '" ';
$res = mysql_query($sql);
while($row = mysql_fetch_array($res)) {
echo $row['id'];
}
Likewise, with PDO I get to a similar place...
$stmt = $dbh->prepare("SELECT id FROM table WHERE email = ? ");
if ($stmt->execute(array($_POST['email']))) {
// what goes in here to loop through the rows??
//
// something like this...?
//
while ($row = $stmt->fetch()) {
echo $row['id'];
}
}
Assuming you're connected to the DB and $dbh is your PDO object.
<?php
$email = 'myEmail#somesite.com';
$stmt = $dbh->prepare("SELECT `id` FROM `table` WHERE `email` = ?");
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->bindParam(1, $email, PDO::PARAM_STR);
$stmt->execute();
/* One row. */
$result = $stmt->fetch();
if ($result !== FALSE) {
$stmt->closeCursor();
echo $result['id'];
}
/* Multiple rows. */
$result = $stmt->fetchAll();
if ($result !== FALSE) {
foreach ($result as $row) {
echo $row['id'];
}
}
?>
Here is what I use:
For more info on PDO see: http://php.net/manual/en/book.pdo.php
How to use:
//create connection
$connection = new Connection($settings,true);
$conn = $connection->conn;
//query
$sql = "SELECT StateName as State, StateAbbr as Abb FROM State";
$values = array(":Abbr" => "AL");
$query = new Query($conn);
$testArr = $query->getArrayFromQuery($sql, $values);
CONNECTION: (Connection.php)
class Connection
{
public $conn = null;
/**
* Creates PDO Database Connection
*
* #param array $params Connection Data (host,database,username,password)
* #param bool $useErrorReporting True to Show Errors (optional)
* #sets Database Connection
* #access public
*/
public function __construct($params,$useErrorReporting=false)
{
try
{
$host = "";
$database = "";
$username = "";
$password = "";
if(isset($params) && is_array($params))
{
$host = $params['database_connection']['host'];
$database = $params['database_connection']['database'];
$username = $params['database_connection']['username'];
$password = $params['database_connection']['password'];
$dsn = 'mysql:dbname='.$database.';host='.$host;
$dbh = new PDO($dsn, $username, $password, array(PDO::ATTR_PERSISTENT => true));
//display errors if true
if($useErrorReporting)
{
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
}
else
{
$dbh = null;
}
}
catch (PDOException $e)
{
throw new Exception('Connection Failed: '.$e->getMessage());
}
$this->conn = $dbh;
}
QUERY: Query.php
Class Query
{
private $conn = null;
/**
* sets query properties
*
* #param object $conn pdo connection object
* #return void
* #access public
*/
public function __construct($conn)
{
$this->conn = $conn;
}
/**
* getArrayFromQuery
* gets array from given query
*
* #param string $sql sql statement
* #param array $values array values to replace (":value" => 2)
* #return array
* #access public
*/
public function getArrayFromQuery($sql, $values)
{
$retValue = array();
$conn = $this->conn;
$statement = "";
try
{
//prepare sql statement
$statement = $conn->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
//add values
if(isset($values) && is_array($values))
{
$statement->execute($values);
}
//set return array to result array
$retValue = $statement->fetchAll();
}
catch (PDOException $e)
{
throw new Exception("PDO Query Error: ".$e->getMessage());
}
catch(Exception $e)
{
throw new Exception("Process Query Error: ". $e->getMessage());
}
return $retValue;
}
}

Categories