I came across an ancient PHP project where there's a modified QuickDB class(I had to strip it as it was too big for StackOverflow).
It'll work just fine if there's just one instance of QuickDB, but if you add another, it'll get real bad as the second instance overwrites the previous connection.
I'm struggling to find an elegant solution, could anyone give me a hint?
<?php
if (!function_exists("mysql_connect")) {
/* warning: fatal error "cannot redeclare" if a function was disabled in php.ini with disable_functions:
disable_functions =mysql_connect,mysql_pconnect,mysql_select_db,mysql_ping,mysql_query,mysql_fetch_assoc,mysql_num_rows,mysql_fetch_array,mysql_error,mysql_insert_id,mysql_close,mysql_real_escape_string,mysql_data_seek,mysql_result
*/
global $mysqli_connection;
function mysql_connect($host, $username, $password) {
global $mysqli_connection;
$mysqli_connection = mysqli_connect($host, $username, $password);
return $mysqli_connection;
}
function mysql_pconnect($host, $username, $password) {
return mysqli_connect("p:" . $host, $username, $password);
}
function mysql_num_fields($result) {
return mysqli_num_fields($result);
}
function mysql_field_name($result, $i) {
return mysqli_fetch_field_direct($result, $i)->name;
}
function mysql_fetch_object($result) {
return mysqli_fetch_object($result);
}
function mysql_select_db($db, $dbconnect = false) {
global $mysqli_connection;
if (!$dbconnect) {
$dbconnect = $mysqli_connection;
}
return mysqli_select_db($dbconnect, $db);
}
function mysql_ping($dbconnect = false) {
global $mysqli_connection;
if (!$dbconnect) {
$dbconnect = $mysqli_connection;
}
return mysqli_ping($dbconnect);
}
function mysql_query($stmt) {
global $mysqli_connection;
return mysqli_query($mysqli_connection, $stmt);
}
function mysql_fetch_assoc($erg) {
return mysqli_fetch_assoc($erg);
}
function mysql_num_rows($e) {
return mysqli_num_rows($e);
}
function mysql_affected_rows($e = NULL) {
return mysqli_affected_rows($e);
}
function mysql_fetch_array($e) {
return mysqli_fetch_array($e);
}
function mysql_error() {
global $mysqli_connection;
return mysqli_error($mysqli_connection);
}
function mysql_errorno() {
global $mysqli_connection;
return mysqli_errorno($mysqli_connection);
}
function mysql_insert_id() {
global $mysqli_connection;
return mysqli_insert_id($mysqli_connection);
}
function mysql_close() {
return true;
}
function mysql_fetch_row($erg) {
return mysqli_fetch_row($erg);
}
function mysql_errno() {
global $mysqli_connection;
return mysqli_errno($mysqli_connection);
}
function mysql_real_escape_string($s) {
global $mysqli_connection;
return mysqli_real_escape_string($mysqli_connection, $s);
}
function mysql_data_seek($re, $row) {
return mysqli_data_seek($re, $row);
}
function mysql_result($res, $row = 0, $col = 0) {
$numrows = mysqli_num_rows($res);
if ($numrows && $row <= ($numrows - 1) && $row >= 0) {
mysqli_data_seek($res, $row);
$resrow = (is_numeric($col)) ? mysqli_fetch_row($res) : mysqli_fetch_assoc($res);
if (isset($resrow[$col])) {
return $resrow[$col];
}
}
return false;
}
function mysql_set_charset($connection, $charset) {
return mysqli_set_charset($connection, $charset);
}
}
if (!function_exists('ereg_replace')) {
function ereg_replace($p1, $p2, $p3) {
return preg_replace("/".$p1.'/', $p2, $p3);
}
}
class QuickDB
{
private $con = null; // for db connection
private $row = null; // for fetched row
private $rows = null; // for number of rows fetched
private $affected = null; // for number of rows affected
private $insert_id = null; // for last inserted id
private $query = null; // for the last run query
public $show_errors = null; // for knowing whether to display errors
private $emsg = null; // for mysql error description
private $eno = null; // for mysql error number
// Intialize the class with connection to db
/**
* #param $host
* #param $user
* #param $password
* #param $db
* #param bool $persistent
* #param bool $show_errors
* #param bool $new_link
*/
public function __construct($host, $user, $password, $db, $persistent = false, $show_errors = false, $new_link = false)
{
if ($show_errors == true) {
$this->show_errors = true;
}
if ($persistent == true) {
$this->con = #mysql_pconnect($host, $user, $password, $new_link);
mysql_set_charset($this->con, "utf8"); // předefinování defaultu 8.6.2017
} else {
$this->con = #mysql_connect($host, $user, $password, $new_link);
mysql_set_charset($this->con, "utf8"); // předefinování defaultu 8.6.2017
}
if ($this->con) {
$result = mysql_select_db($db, $this->con) or die("Could Not Select The Database !!");
return $result;
} else {
die("Could Not Establish The Connection !!");
}
}
// Close the connection to database
/**
*
*/
public function __destruct()
{
$this->close();
}
// Close the connection to database
/**
* #return bool
*/
public function close()
{
//$result = #mysql_close($this->con); // orig
$result = #mysql_close($this->con);
return $result;
}
}
Related
This has nothing to do with Frameworks because it is an external project, I am currently developing to learn, some things about database management or how databases behave...
I need help with some php and PDO... Previously I dev this script:
<?php
class DataBaseManager
{
public function GetData($query, $user, $pass)
{
try {
$db_result = [];
$conn = new PDO("mysql:host=localhost;dbname=test", $user, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->exec("set names utf8");
reset($query);
$db_name = key($query);
$conn->exec('USE ' . $db_name);
$db_result['r'] = $conn->query($query[$db_name], PDO::FETCH_ASSOC);
$count = $db_result['r']->rowCount();
$db_result['c'] = $count;
if (0 == $count) {
$db_result['r'] = null;
} elseif (1 == $count) {
$db_result['r'] = $db_result['r']->fetch();
}
return $db_result;
} catch (PDOException $e) {
echo $e->getMessage();
return false;
}
}
public function DeleteData($query, $user, $pass)
{
try {
$conn = new PDO("mysql:host=localhost;dbname=test", $user, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->beginTransaction();
$conn->exec("set names utf8");
foreach ($query as $db_name => $query_arr) {
$conn->exec('USE ' . $db_name);
foreach ($query_arr as $key => $query_string) {
$conn->exec($query_string);
++$ct;
}
}
$conn->commit();
$conn = null;
return '<b>' . $ct . ' Records Deleted Successfully.</b>';
} catch (PDOException $e) {
$conn->rollback();
echo $e->getMessage();
return false;
}
}
public function SetData($query, $user, $pass)
{
try {
$db_result = [];
$conn = new PDO("mysql:host=localhost;dbname=test", $user, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->beginTransaction();
$conn->exec("set names utf8");
$count = ['u' => 0, 'i' => 0];
foreach ($query as $db_name => $query_arr) {
$conn->exec('USE ' . $db_name);
foreach ($query_arr as $key => $query_string) {
$cq = $conn->exec($query_string);
if (strpos($query_string, 'UPDATE') !== false) {
$count['u'] += $cq;
}
if (strpos($query_string, 'INSERT') !== false) {
$count['i'] += $cq;
}
}
}
$conn->commit();
$db_result['r'] = true;
$db_result['t'] = 'Updates: ' . $count['u'] . ', Inserts: ' . $count['i'];
return $db_result;
} catch (PDOException $e) {
$conn->rollback();
echo $e->getMessage();
return false;
}
}
}
I would like to be able to insert data by volumes in multiple tables in a single commit...
The idea of doing it that way is because if something fails I want it to be automatically rolled back in all table instances...
So I have a data structure in an array with the following content in my new class:
$dbquery =[
'test'=>[
'0' =>[
0 => 'INSERT INTO table_name_1(column1,column2) VALUES (?,?)', //mean it is the query
1 =>[value11,value12], // mean it is a row
2 =>[value21,value22], // mean it is a row
],
'1' =>[
0 => 'INSERT INTO table_name_2(column1,column2,column3,column4) VALUES (?,?,?,?)', //mean it is the query
1 =>[value11,value12,value13,value14], // mean it is a row
2 =>[value21,value22,value23,value24], // mean it is a row
],
],
];
but i have my first try with bindValue, this is my new class mentioned:
<?php
class DataBase
{
private static ?DataBase $instance = null;
public static function getInstance(): DataBase
{
if (!self::$instance instanceof self) {
self::$instance = new self();
}
return self::$instance;
}
private array $config;
public function __construct()
{
$this->config = ['DB_HOST'=>'test','DB_NAME'=>'test','DB_USER'=>'test','DB_PASSWORD'=>''];
$this->setConnection(new PDO("mysql:host=" . $this->config['DB_HOST'] . ";dbname=" . $this->config['DB_NAME'], $this->config['DB_USER'], $this->config['DB_PASSWORD']));
}
private PDO $connection;
/**
* #return PDO
*/
private function getConnection(): PDO
{
return $this->connection;
}
/**
* #param PDO $connection
*/
private function setConnection(PDO $connection): void
{
$this->connection = $connection;
}
public function changeConnectionServer(string $host, string $db_name, string $user, string $password): void
{
$this->setConnection(new PDO("mysql:host=" . $host . ";dbname=" . $db_name, $user, $password));
}
private array $query;
public function setDataBaseTarget(string $db_name)
{
if (empty($this->query)) {
$this->query = [];
}
$this->query[$db_name] = [];
}
public function buildQuery(string $query)
{
if (empty($this->query)) {
$this->query = [];
$this->query[$this->config['DB_NAME']] = [];
}
$target = array_key_last($this->query);
$this->query[$target][] = [$query];
}
public function addQueryData($data)
{
$target = array_key_last($this->query);
$key = array_key_last($this->query[$target]);
$this->query[$target][$key][] = $data;
}
private function getQuery(): array
{
return $this->query;
}
/**
* #throws Exception
*/
public function setData(): array
{
try {
$time = -microtime(true);
$con = $this->getConnection();
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->beginTransaction();
$con->exec("set names utf8;");
foreach ($this->getQuery() as $db_name => $query_arr) {
$con->exec('USE `' . $db_name . '`;');
$ct = 0;
// on this section have proble with code and logic .... i dont know what i need to dev to insert the data
foreach ($query_arr as $query_structure) {
foreach ($query_structure as $key => $raw) {
if ($key === 0) {
$ct++;
$stmt[$ct] = $con->prepare($raw);
} else {
if (is_array($raw)) {
$c = 0;
foreach ($raw as $value) {
$c++;
$stmt[$ct]->bindValue($c, $value, $this->getParamType($value));
}
}
}
}
$stmt[$ct]->execute();
}
//end section
}
//$con->commit();
return true;
} catch (PDOException $e) {
$con->rollback();
echo $e->getMessage();
return false;
}
}
private function getParamType($value)
{
if (is_int($value)) {
return PDO::PARAM_INT;
} elseif (is_bool($value)) {
return PDO::PARAM_BOOL;
} elseif (is_null($value)) {
return PDO::PARAM_NULL;
} elseif (is_string($value)) {
return PDO::PARAM_STR;
} else {
return false;
}
}
}
$db_handler = DataBase::getInstance();
$db_handler->buildQuery("INSERT INTO `client_list`(`email`,`mobile`) VALUES ('?','?');");
$db_handler->addQueryData(['mail1#test.com', '35634634636546']);
$db_handler->addQueryData(['mail2#test.com', '35634634636546']);
$db_handler->addQueryData(['mail3#test.com', '35634634636546']);
$db_handler->setData();
I can't figure out, develop the part that allows me to package everything in a single transaction... what I have is a stm[] ...
Can someone help me with this development?
I can't make heads or tails of all the things your class is doing, but here's a generalized version according to the bits that seem obvious:
public function runMultipleQueries() {
$dbh = $this->getConnection();
// ... setup stuff
$dbh->beginTransaction();
try {
foreach($this->queries as $query) {
$stmt->prepare($query->queryString);
$param_id = 1;
foreach($query->params as $param) {
$stmt->bindValue($param_id++, $param);
}
$stmt->execute();
}
} catch( \Exception $e ) {
$dbh->rollback();
throw $e;
// IMO if you cannot fully/meaningfully recover, just re-throw and let it kill execution or be caught elsewhere where it can be
// otherwise you're likely having to maintain a stack of if(foo() == false) { ... } wrappers
}
$dbh->commit();
}
Additionally, singleton DB classes have the drawbacks of both being limiting if you ever need a second DB handle, as well as boiling down to being global state, and subject to the same "spooky action at a distance" problems.
Consider using dependency inversion and feeding class dependencies in via constructor arguments, method dependencies via method arguments, etc. Eg:
interface MyWrapperInterface {
function setQueries(array $queries);
function runQueries();
}
class MyDbWrapper implements MyWrapperInterface {
protected $dbh;
public function __construct(\PDO $dbh) {
$this->dbh = $dbh;
}
public function setQueries(array $queries) { /* ... */ }
public function runQueries() { /* ... */ }
}
class MyOtherThing {
protected $db;
public function __construct( MyWrapperInterface $db ) {
$this->db = $db;
}
// ...
}
$wrapper1 = new MyDbWrapper(new PDO($connstr1, $options));
$wrapper2 = new MyDbWrapper(new PDO($connstr2, $options));
$thing1 = new MyOtherThing($wrapper1);
$thing2 = new MyOtherThing($wrapper2);
$thing1_2 = new MyOtherThing($wrapper1);
// etc
Is it possible to get different output when you run the exact same query from PHP vs. PHPMyAdmin? When I run
$sql = "SELECT IF(PersonA=200, PersonB, PersonA) AS Person
FROM People
WHERE PersonA=200 OR PersonB=200;";
I get the correct output from PHPMyAdmin but a different (incorrect) result from my PHP code above. The following is my SQL class I use.
<?php
class SQLQueryExecutor {
private $queryString;
private $conn;
private $db;
private $host;
private $username;
private $password;
public function __construct($queryString, $db, $host, $username, $password) {
$this->queryString = $queryString;
$this->conn = NULL;
$this->db = $db;
$this->host = $host;
$this->username = $username;
$this->password = $password;
}
// make connection to mysql database
public function makeConnection() {
$this->conn = new mysqli($this->host, $this->username, $this->password, $this->db);
if ($this->conn->connect_error) {
die("Connection failed: " . $this->conn->connect_error);
}
}
// execute query
public function executeQuery() {
if ($this->conn != NULL)
{
$result = mysqli_query($this->conn, $this->queryString);
$rows = Array();
if ($result !== False) // resource returned?
{
while($row=mysqli_fetch_assoc($result))
{
$rows= $row;
}
return $rows;
}
}
return NULL;
}
// close sql connection
public function closeConnection() {
mysql_close($this->conn);
}
} // class
?>
I call this class as follows...
$user = $_GET['User_ID'];
$sql = "
SELECT IF(PersonA=$user, PersonB, PersonA) AS Person
FROM People
WHERE PersonA=$user OR PersonB=$user;";
$newSQLQueryExecutor = new SQLQueryExecutor($sql, "blah","blah", "blah", "blah");
$newSQLQueryExecutor->makeConnection();
$rows = $newSQLQueryExecutor->executeQuery();
$friends = Array("friends" => $rows);
$newSQLQueryExecutor->closeConnection();
print_r($friends);
The PHPMyAdmin prints all the correct rows but the PHP only prints the very last row.
Here is your issue, a mistake in the executeQuery() method
public function executeQuery() {
if ($this->conn != NULL) {
$result = mysqli_query($this->conn, $this->queryString);
$rows = Array();
if ($result !== False) { // resource returned?
while($row=mysqli_fetch_assoc($result)) {
$rows[] = $row;
// amended ^^
}
return $rows;
}
}
return NULL;
}
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?
We've just updated PHP on our server, for the most part everything is fine, but the mssql_ functions aren't supported any more unfortunately. I've tried to update our previous class:
$connection['server'] = 'server, port';
$connection['user'] = 'user';
$connection['pass'] = 'pass';
$connection['db'] = 'db';
class mssqlClass {
function connect($dbhost = NULL){
global $connection;
if(! ISSET ($dbconnect)){
$dbconnect = mssql_Connect($connection['server'], $connection['user'], $connection['pass'], true);
}
if(! $dbconnect){
return 'Failed to Connect to Host';
}else{
$select = mssql_select_db($connection['db'], $dbconnect);
if(! $select){
return 'Failed to select Database';
}else{
return $dbconnect;
}
}
}
function getData ($query){
$this->data_array = array();
$result = mssql_query($query);
while ($row = mssql_fetch_assoc($result)) {
$this->data_array[] = $row;
}
$m = $this->data_array;
return $m;
}
function query($query){
$result = mssql_query($query) or die("Query didn't work");
}
}
To be compliant with sqlsrv_, and whilst I can connect to the database without any issues, it won't return any data!:
class mssqlClass {
function connect($database = 'Db') {
$mssql_server = 'server';
$mssql_data = array("UID" => 'uid',
"PWD" => 'pwd',
"Database" => $database);
if(! ISSET ($dbconnect)){
$dbconnect = sqlsrv_connect($mssql_server, $mssql_data);
}
if(! $dbconnect){
return 'Failed to connect to host';
}
}
function getData ($query) {
$result = sqlsrv_query($db->connect, $query);
while ($row = sqlsrv_fetch_array($result)) {
$this->data_array[] = $row;
}
$m = $this->data_array;
return $m;
}
function query($query) {
$result = sqlsrv_query($query) or die("Query didn't work.");
}
}
ps. Example usage is as follows:
$db = new mssqlClass();
$conn = $db->connect('DATABASE');
$query = "SELECT * FROM Table";
$result= $db->getData($query);
So sorry for the horrible amount of code - I can edit it down to just the getData function if that's easier? Thank you!!
I've made some changes in your class:
<?php
class mssqlClass {
protected $connection = null;
public function connect($database = 'Db') {
// we don't need to connect twice
if ( $this->connection ) {
return;
}
// data for making connection
$mssql_server = 'gc-hr01';
$mssql_data = array("UID" => 'uid',
"PWD" => 'pwd',
"Database" => $database);
// try to connect
$this->connection = sqlsrv_connect($mssql_server, $mssql_data);
if(! $dbconnect){
return 'Failed to connect to host';
}
}
public function getData ($query) {
// reset results; is this really needed as object's variable? Can't it be just local function's variable??
$this->data_array = array();
$result = $this->query($this->connection, $query);
while ($row = sqlsrv_fetch_array($result)) {
$this->data_array[] = $row;
}
return $this->data_array;
}
public function query($query) {
$result = sqlsrv_query($query) or die("Query didn't work..");
}
}
The code looks fine. The only thing which could be your problem is that sqlsrv_fetch_array needs maybe a second parameter e.g.:
sqlsrv_fetch_array( $result, SQLSRV_FETCH_ASSOC)
Because the default is that it returns two arrays with different formats. And if you may acess attributes by name it will return nothing but not fail.
Something like this. Because you actually call the sqlsrv_query method with the return value of the following method. And in the original version you missed to return the connection resource.
function connect($database = 'Db') {
$mssql_server = 'gc-hr01';
$mssql_data = array("UID" => 'uid',
"PWD" => 'pwd',
"Database" => $database);
$dbconnect = sqlsrv_connect($mssql_server, $mssql_data);
if(! $dbconnect){
return 'Failed to connect to host';
}
return $dbconnect;
}
in advance
function getData ($query) {
$result = sqlsrv_query($db->connect(), $query);
while ($row = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
$this->data_array[] = $row;
}
$m = $this->data_array;
return $m;
}
function query($query) {
$result = sqlsrv_query($query) or die("Query didn't work.");
}
I found this page while trying to find a quick short-cut to someone else's wrapper class for sqlsrv commands. Since this wasn't really complete, I have compiled my own quickly. Please don't think this is production code, you should test and test again, but it might help someone out of a jam quickly.
class db {
protected $connection = null;
private $debug = true;
private $stmt = null;
private $insertid = null;
private $affectedrows = null;
public function db($host = '.',$database,$username,$password) {
// we don't need to connect twice
if ( $this->connection ) {
return;
}
sqlsrv_configure('WarningsReturnAsErrors', 0);
// data for making connection
$sqlsvr_details = array( 'UID' => $username,
'PWD' => $password,
'Database' => $database,
'CharacterSet' => 'UTF-8'
);
// try to connect
$this->connection = sqlsrv_connect($host, $sqlsvr_details);
if($this->connection == false){
$this->debug('Failed to connect to host: '.$this->errors(),true);
return false;
}else{
return true;
}
}
public function query($query) {
return new resultset($query,$this->connection,$this->debug);
}
private function debug ($message,$hard = false){
if ($this->debug){
if ($hard){
die($message);
}else{
echo $message;
}
}
return true;
}
public function delete($query){
return $this->update($query);
}
public function update($query){
//Not happy with this
$this->affectedrows = null;
$this->insertid = null;
$this->stmt = sqlsrv_query($this->connection, $query);
if (!$this->stmt){
$this->debug('SQL Query Failed: '.$query.' '.$this->errors(),true);
return false;
}else{
$this->affectedrows = #sqlsrv_rows_affected($this->stmt);
return $this;
}
}
public function insert($query){
//Not happy with this
$this->affectedrows = null;
$this->insertid = null;
$this->stmt = sqlsrv_query($this->connection, $query);
if (!$this->stmt){
$this->debug('SQL Query Failed: '.$query.' '.$this->errors(),true);
return false;
}else{
//Get the last insert ID and store it on here
$this->insertid = $this->query('select ##IDENTITY as insert_id')->asObject()->insert_id;
return $this;
}
}
public function insert_id(){
return $this->insertid;
}
public function affected_rows(){
return $this->affectedrows;
}
private function errors(){
return print_r( sqlsrv_errors(SQLSRV_ERR_ERRORS), true);
}
}
class resultset implements Countable,Iterator {
private $result = null;
private $connection = null;
private $debug = false;
private $internal_pointer = 0;
private $data = array();
public function resultset($query,$link,$debug = false){
$this->connection = $link;
$this->debug = $debug;
$this->result = sqlsrv_query($this->connection, $query, array(), array('Scrollable' => SQLSRV_CURSOR_STATIC));
if ($this->result == false){
$this->debug('Query Failed: '.$query.' '.$this->errors(),true);
return false;
}else{
return $this;
}
}
public function asObject($step = true){
$object = sqlsrv_fetch_object($this->result,NULL,NULL,SQLSRV_SCROLL_ABSOLUTE,$this->internal_pointer);
if (! $object){
return false;
}else{
if ($step) $this->internal_pointer++;
return $object;
}
}
public function num_rows() {
return sqlsrv_num_rows($this->result);
}
public function free(){
$this->internal_pointer = 0;
if (is_resource($this->result)){
sqlsrv_free_stmt($this->result);
}
}
public function __destory(){
$this->free();
}
//Countable Function
public function count(){
return $this->num_rows();
}
//Iteration Functions
public function rewind(){
$this->internal_pointer = 0;
}
public function current(){
return $this->asObject(false);
}
public function key(){
return $this->internal_pointer;
}
public function next(){
$this->internal_pointer++;
}
public function valid(){
return $this->internal_pointer <= $this->num_rows();
}
//============================================
private function debug ($message,$hard = false){
if ($this->debug){
if ($hard){
die($message);
}else{
echo $message;
}
}
return true;
}
private function errors(){
return print_r( sqlsrv_errors(SQLSRV_ERR_ERRORS), true);
}
}
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 ;-)