I am using this php pdo wrapper.This is my database class .
class Db
{
private static $_pdoObject = null;
protected static $_fetchMode = PDO::FETCH_ASSOC;
protected static $_connectionStr = null;
protected static $_driverOptions = array();
private static $_username = null;
private static $_password = null;
public static function setConnectionInfo($schema, $username = null, $password = null, $database = 'mysql', $hostname = 'localhost')
{
if($database == 'mysql') {
self::$_connectionStr = "mysql:dbname=$schema;host=$hostname";
self::$_username = $username;
self::$_password = $password;
} else if($database == 'sqlite'){
// For sqlite, $schema is the file path
self::$_connectionStr = "sqlite:$schema";
}
// Making the connection blank
// Will connect with provided info on next query execution
self::$_pdoObject = null;
}
public static function getResult($sql, $params = array())
{
$statement = self::_query($sql, $params);
return $statement->fetchAll(self::$_fetchMode);
}
private static function _query($sql, $params = array())
{
if(self::$_pdoObject == null) {
self::_connect();
}
$statement = self::$_pdoObject->prepare($sql, self::$_driverOptions);
$arrayjson1=array(
'success' => false,
'message'=>'database error '
);
$msg= formjson(array(),array(),$arrayjson1);
if (! $statement) {
$errorInfo = self::$_pdoObject->errorInfo();
//~ print_r($errorInfo);
//~ echo $msg;exit;
throw new PDOException("Database error [{$errorInfo[0]}]: {$errorInfo[2]}, driver error code is $errorInfo[1]");
}
$paramsConverted = (is_array($params) ? ($params) : (array ($params )));
if ((! $statement->execute($paramsConverted)) || ($statement->errorCode() != '00000')) {
$errorInfo = $statement->errorInfo();
//~ print_r($errorInfo);
throw new PDOException("Database error [{$errorInfo[0]}]: {$errorInfo[2]}, driver error code is $errorInfo[1]");
//~ echo $msg;exit;
}
return $statement;
}
}
I am calling this query for getting all the users
$sql="select userid,concat_ws(' ',firstname,lastname) as name $fields
from users where 1=1 $condition order by updatedon $limit";
$row=Db::getResult($sql,$query);
I want that by
Input
passing
No. of record per page
2.Page No.
So that it
output
come should be the records of that page only by record per page .
How can i achieve this in pdo.
Please help.Thanks
read the following article. That will help you understand the criteria you are interested in.
paging
Related
When I want to update my articles table from MySQL database I get the following error
PDOStatement::execute() expects parameter 1 to be array, bool given in /Users/Iceson/Sites/blog jean/app/Database.php on line 49
Here the update code from my managementpost.php
if(isset($_POST['update'])) {
$id = $_POST['id'];
$titre = $_POST['titre'];
$contenu = $_POST['contenu'];
App\App::getDb()->prepare("UPDATE articles SET titre ='$titre',
contenu ='$contenu' WHERE id='id'",true);
}
Here is the my database class from my database.php, the error is located on the line $req->execute($attributes); in the function prepare
<?php
namespace App;
use \PDO;
class Database {
private $db_name;
private $db_user;
private $db_pass;
private $db_host;
private $pdo;
public function __construct($db_name, $db_user = 'root', $db_pass = 'root', $db_host = 'localhost') {
$this->db_name = $db_name;
$this->db_user = $db_user;
$this->db_pass = $db_pass;
$this->db_host = $db_host;
}
private function getPDO() {
if ($this->pdo === null) {
$pdo = new PDO('mysql:host=localhost;dbname=blogdejean;charset=utf8', 'root', 'root');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo = $pdo;
}
return $this->pdo;
}
public function query($statement, $class_name = null, $one = false) {
$req = $this->getPDO()->query($statement);
if($class_name === null) {
$req->setFetchMode(PDO::FETCH_OBJ);
} else {
$req->setFetchMode(PDO::FETCH_CLASS, $class_name);
}
if($one) {
$datas = $req->fetch();
} else {
$datas = $req->fetchALL();
}
return $datas;
}
public function prepare($statement, $attributes, $class_name = null, $one = false) {
$req = $this->getPDO()->prepare($statement);
$req->execute($attributes);
if($class_name === null) {
$req->setFetchMode(PDO::FETCH_OBJ);
} else {
$req->setFetchMode(PDO::FETCH_CLASS, $class_name);
}
if($one) {
$datas = $req->fetch();
} else {
$datas = $req->fetchALL();
}
return $datas;
}
}
You are using your database class wrong: Instead of sending a statement with parameters you can bind, you inject the values in the sql statement making your query vulnerable to sql injection.
And where you need to send an array of values to bind, you send a boolean.
So you need to replace this:
App\App::getDb()->prepare("UPDATE articles SET titre ='$titre', contenu ='$contenu' WHERE id='id'",true);
with:
App\App::getDb()->prepare(
"UPDATE articles SET titre = ?, contenu = ? WHERE id = ?",
[
$_POST['titre'],
$_POST['contenu'],
$_POST['id'],
]
);
You should probably also re-think why you are extending PDO like that; fetching all rows does not make sense on an update statement for example.
thanks y'all now i have a general error "General error in /Users/Iceson/Sites/blog jean/app/Database.php:58" it's the $datas = $req->fetchALL(); i think i messed up my database class everything was working until the update part, i don't know what's wrong
public function prepare($statement, $attributes, $class_name = null, $one = false) {
$req = $this->getPDO()->prepare($statement);
$req->execute($attributes);
if($class_name === null) {
$req->setFetchMode(PDO::FETCH_OBJ);
} else {
$req->setFetchMode(PDO::FETCH_CLASS, $class_name);
}
if($one) {
$datas = $req->fetch();
} else {
$datas = $req->fetchALL();
}
return $datas;
}
You prepare method expects a array as the second argument ($attributes), but you passed it true.
App\App::getDb()->prepare("UPDATE articles SET titre ='$titre', contenu ='$contenu' WHERE id='id'",true);
It should be something like this.
App\App::getDb()->prepare("UPDATE articles SET titre = :titre, contenu = :contenu WHERE id= :id",[':titre' => $titre, ':contenu' => $contenu, ':id' => $id ]);
I have been adapting an older abstraction layer to use PDO but I am running into user x has more than 'max_user_connections' active connections SQLSTATE[HY000] [1203] errors when looping through large sets. I have been reading on http://php.net/manual/en/pdo.connections.php but all of my attempts to unset the $dbh from within the loops result in errors from having ended the connection.
Base class looks like
class DB {
public $pdo;
private $host = DB_HOST;
private $user = DB_USER;
private $pass = DB_PASS;
private $dbname = DB_NAME;
public function __construct()
{
$this->connect();
}
private function connect()
{
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
try {
$this->pdo = new PDO("mysql:host=$this->host;dbname=$this->dbname;charset=utf8;", $this->user, $this->pass, $options);
} catch(PDOException $e) {
echo $e->getMessage();
}
}
public function __sleep()
{
return array('dsn', 'username', 'password');
}
public function __wakeup()
{
$this->connect();
}
public function __destruct()
{
$this->connection = null;
$this->pdo = null;
unset($this->pdo);
}
// CRUD methods follow including
function retrieve($where, $groupBy='', $order_by='') {
$query = "SELECT * FROM `$this->table` $where $groupBy $order_by";
$q = $this->pdo->prepare($query);
$q->execute();
$result = $q->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE,get_class($this));
// was $result = $q->fetchAll(PDO::FETCH_CLASS,get_class($this));
$this->query_log($query);
$q = null;
if ($result == 'NULL') {
return false;
} else {
return $result;
}
} // retrieve()
And an example that has the errors would be
if (in_array($_GET['type'], $types)) {
$type = $_GET['type'];
$rsObj = new ReservedSlug;
if ($type == 'artist') {
$obj = new CalendarArtist;
$slugfield = 'urlSlug';
$namefield = 'name';
} else if ($type == 'event') {
$obj = new CalendarEvent;
$slugfield = 'urlSlug';
$namefield = 'name';
} else if ($type == 'location') {
$obj = new Location;
$slugfield = 'UrlSlug';
$namefield = 'LocationName1';
}
$needslug = $obj->retrieve("TRIM(`$namefield`) != '' AND (`$slugfield` = '' OR `$slugfield` IS NULL) LIMIT 0,400");
if ($needslug) {
foreach ($needslug as $ns) {
$testslug = slugify($ns->$namefield);
list($reserved) = $rsObj->retrieve("`slug` = '$testslug' AND `type` = '$type'");
if (!$reserved) {
list($test) = $obj->retrieve("`$slugfield` = '$testslug'");
if ($test) {
for ($i = 2; $i < 26; $i++) {
list($test) = $obj->retrieve("`$slugfield` = '$testslug-$i'");
if (!$test) {
$slug = $testslug . '-' . $i;
}
}
} else { // not found in table
$slug = $testslug;
}
} else { // was reserved
$slug = false;
}
echo $ns->$namefield . " gets $slug<p>";
} // foreach needslug
} // if needslug
} // type found in array
So I need to understand how to not create new connections when an active connection is available and how to properly __destruct() these child objects. Where am I going wrong?
I fetch some results from an sql statement I did using PDO and whenever I put it on an array it goes like this:
initialize Object ( [conn:protected] => PDO Object ( ) [container:protected] => Array ( [0] => 1,Philippine Tax,2 ) )
Whenever I FOREACH the returned array, it gives an error that it can't display an object. Here is my code:
<?php
class initialize{
protected $conn = NULL;
protected $container = array();
function __construct(){
$this->conn = $this->connect();
$ed_fetch = $this->conn->prepare("SELECT * FROM table");
if ($ed_fetch->execute()){
while ($row = $ed_fetch->fetch( )){
array_push($this->container, $row[0] . ',' . $row[1] . ',' . $row[2]);
}
}
return $this->container;
}
protected function connect(){
$this->conn = new PDO("mysql:host=localhost;dbname=db", 'root');
if (!$this->conn){
echo "Error, could not connect to the database, contact the administrator";
}
else{
return $this->conn;
}
}
}
?>
My display:
$new = new initialize();
print_r($new);
Try something like this instead. The reason you are getting what you are is because you are trying to get info on the object, essentially a mapping of the object. If you are trying to return an array, you need to return it through a method, not so much through the __construct as a return though.
class Initialize
{
protected $conn = NULL;
protected $container = array();
protected $creds;
protected $username;
protected $password;
public function __construct($creds = "mysql:host=localhost;dbname=db", $username = 'root', $password = '')
{
$this->creds = $creds;
$this->username = $username;
$this->password = $password;
$this->conn = $this->connect();
}
public function Fetch($sql)
{
$ed_fetch = $this->conn->prepare($sql);
$ed_fetch->execute();
if ($ed_fetch->rowCount() > 0){
while ($row = $ed_fetch->fetch()){
$this->container[] = $row[0].','.$row[1].','.$row[2];
}
}
return $this->container;
}
protected function connect()
{
try {
$this->conn = new PDO($this->creds,$this->username,$this->password);
} catch (PDOException $e) {
echo "Error, could not connect to the database, contact the administrator<br/>"; //. $e->getMessage() .
die();
}
}
}
$query = new Initialize();
$array = $query->Fetch("SELECT * FROM table");
print_r($array);
Basically what I'm doing is a users class, which executes a MySQL query in the constructor to retrieve all the users data and store it, like so:
public function __construct($data, $type = 'id')
{
$this->details = Beam::$db->row("SELECT * FROM users WHERE $type = :param", ['param' => $data]);
if(!empty($this->details)) $this->exists = true;
}
This is row() method:
public function row($query, $params = null, $fetchmode = PDO::FETCH_ASSOC)
{
$this->init($query, $params);
return $this->statementQuery->fetch($fetchmode);
}
And init(), where the parameters are bound and the query is executed:
public function init($query, $parameters = '')
{
try {
$this->statementQuery = $this->pdo->prepare($query);
if(!empty($parameters))
{
foreach($parameters as $key => $value)
{
$this->bind($key, $value);
}
}
if(!empty($this->parameters))
{
foreach($this->parameters as $key => &$value)
{
$this->statementQuery->bindParam($key, $value);
}
}
$this->success = $this->statementQuery->execute();
}
catch(PDOException $e)
{
throw new SystemException($e->getMessage() . ' in query: ' . $query, (int) $e->getCode());
}
$this->parameters = array();
}
It should work, I've tested everything multiple times, and debugged using dies() everywhere, but it seems as if I instantiate the class more than one time, the error occurs. It's called multiple times in all my code. Is there something I'm missing?
The error:
SQLSTATE[HY093]: Invalid parameter number: parameter was not defined in query: SELECT * FROM users WHERE id = :param
I've also tried debugging printing all the parameters set in PDO by ::debugDumpParams(), and all the parameters are okay, I even var_dump the $this->statementQuery->fetch($fetchmode) from the row() method and it returns everything as it should be...
PS: I bind the array ['param' => $data] afterwards, using this method:
public function bind($param, $value)
{
$this->parameters[':' . $param] = $value;
}
Some examples of where I call the class from:
Login method. Called when the user does login. It fails.
public static function login($user, $password)
{
$user = new User($user, Beam::$con->auth['type']);
if($user->exists == true)
{
$user_ip = $_SERVER['REMOTE_ADDR'];
$user_browser = $_SERVER['HTTP_USER_AGENT'];
$user_id = $user->details["id"];
$username = $user->details["username"];
$user_mail = $user->details["mail"];
$user_password = $user->details["password"];
if(self::verify($password, $user_password))
{
$_SESSION['user_id'] = $user_id;
$_SESSION['username'] = $username;
$_SESSION['user_mail'] = $user_mail;
$_SESSION['user_checksum'] = hash('sha512', $user_password . $user_ip . $user_browser);
Beam::$db->bind("l", time());
Beam::$db->bind("u", $user_id);
Beam::$db->query("UPDATE user_info SET login_timestamp = :l WHERE user_id = :u");
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
This one checks if the user is logged in. It's called almost in every file for authenticated users only.
public static function status()
{
if(isset($_SESSION["user_id"], $_SESSION["username"], $_SESSION["user_checksum"]))
{
$user = new User($_SESSION["user_id"], "id");
if($user->exists)
{
$user_id = $_SESSION['user_id'];
$user_checksum = $_SESSION['user_checksum'];
$username = $_SESSION['username'];
$user_ip = $_SERVER['REMOTE_ADDR'];
$user_browser = $_SERVER['HTTP_USER_AGENT'];
$user_password = $user->details["password"];
switch($user_checksum)
{
default:
$checksum_verify = hash('sha512', $user_password . $user_ip . $user_browser);
break;
case "facebook":
$checksum_verify = "facebook";
break;
}
if($checksum_verify == $user_checksum)
{
return true;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
You need to use the same name for the parameter that you used in the query. In this case you used ":param" so that's what you need to use when you pass in the array of parameters.
change
['param' => $data]
to
[':param' => $data]
and it should work.
so i have been trying to debug this issue myself for a few days now and i can't seem to figure out why i'm not getting the results I expect.
My code is rather complex and for a DB connection to be establish it spans across 3 Classes and one config file.
but basically my end usage ends up being
$this->db('test')->query('SELECT * FROM test1');
this establishes a connection to my database by the alias of test the query returns results so i'm good so far.
now my issue is when i try to make a new PDO object.
$this->db('test2')->query('SELECT * FROM test2');
this returns nothing because there is not table called test2 in my test1 object.
but if I do this
$this->db('test2')->query('SELECT * FROM test1');
now this returns the same results from the first PDO object.
I have traced and tracked down every line of code to make sure that the correct parameters are being passed to my database class and that each connection is properly established to the corresponding databases.
now my question is, can you have more than one datbase pdo connection? if so is there a special flag that needs to be set in the PDO options? are my connections being cached somewhere and causing this confusion?
this is my PDO declaration in each new class object stored in my array of connections
try
{
$this->_con = new PDO(
"mysql:host=" . $host . ";
port=" . $port . ";
dbname=" . $name, $user, $pass
);
$this->_con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
// TODO: push all $e methods to the developer debugger
echo "Database Error: ". $e->getMessage();
}
edit my code that uses the connection
step 1: a call to the parent class
public function __call($name, $params)
{
$class = $name . '_system_helper';
$hash = md5($class . $params);
if (class_exists($class))
{
if (!array_key_exists($hash, $this->_sys_helper))
{
if (method_exists($class, 'init'))
{
$this->_sys_helper[$hash] = call_user_func_array(array($class, 'init'), $params);
} else {
$this->_sys_helper[$hash] = call_user_func_array($class, $params);
}
}
return $this->_sys_helper[$hash];
}
return null;
}
step 2: called from the parent class
class DB_System_Helper extends Jinxup
{
private $_con = null;
public function __construct($end = null)
{
$mode = null;
$host = null;
$name = null;
$user = null;
$pass = null;
$port = null;
if (isset($this->config['database']['mode']))
{
$mode = $this->config['database']['mode'] == 'production' ? 'production' : 'development';
if (count($this->config['database'][$mode]) > 1)
{
foreach ($this->config['database'][$mode] as $key => $database)
{
if ($database['#attr']['alias'] == $end)
{
$host = $this->config['database'][$mode][$key]['host'];
$name = $this->config['database'][$mode][$key]['name'];
$user = $this->config['database'][$mode][$key]['user'];
$pass = $this->config['database'][$mode][$key]['pass'];
$port = $this->config['database'][$mode][$key]['port'];
}
}
} else {
$host = $this->config['database'][$mode]['host'];
$name = $this->config['database'][$mode]['name'];
$user = $this->config['database'][$mode]['user'];
$pass = $this->config['database'][$mode]['pass'];
$port = $this->config['database'][$mode]['port'];
}
$this->_con = new PDO_Database_Helper($host, $name, $user, $pass, $port);
} else {
echo 'No database mode specified';
}
}
public function __call($name, $param)
{
return call_user_func_array(array($this->_con, $name), $param);
}
}
step 3: called from DB_System_Helper
class PDO_Database_Helper extends Jinxup
{
private $_con = null;
private $_id = 0;
public function __construct($host, $name, $user, $pass, $port = 3306)
{
try
{
$this->_con = new PDO(
"mysql:host=" . $host . ";
port=" . $port . ";
dbname=" . $name, $user, $pass
);
$this->_con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
// TODO: push all $e methods to the developer debugger
echo "Database Error: ". $e->getMessage();
}
}
[...]
}
Are you sure that the hashing you're doing is enough to "namespace" each connection in the $this->_sys_helper array?
I suspect the problem lies in the first stage.
public function __call($name, $params)
{
$class = $name . '_system_helper';
$hash = md5($class . $params);
if (class_exists($class))
{
if (!array_key_exists($hash, $this->_sys_helper))
{
if (method_exists($class, 'init'))
{
$this->_sys_helper[$hash] = call_user_func_array(array($class, 'init'), $params);
} else {
$this->_sys_helper[$hash] = call_user_func_array($class, $params);
}
}
>>>>>>>>>>>>>> are you sure this is not returning the wrong
>>>>>>>>>>>>>> connection because of how the hashing is working?
return $this->_sys_helper[$hash];
}
return null;
}