My MySQL randomly assigns a second port to the requested address like this:
[2002] Cannot assign requested address (trying to connect via tcp://127.0.0.1:3306:3306)
This behavior is triggered on my localhost and on my servers as well, so I figured it might be my code. I'm connecting via a self-written class, which is using constants only to connect (which are correct, no second ports assigned within these constants), so I'm pretty clueless why this behavior is triggered sometimes and where the second port comes from. The execution of the script terminates when this error occurs.
I added the class to this post, if someone wants to browse through.
Any advise is welcome to fix or circumnavigate this.
Thanks in advance!
class mysql{
protected $query = false;
protected $lastquery = false;
protected $result = false;
protected $row = false;
protected $args = array('');
protected static $mysqli = null;
public function __construct(\mysqli $mysqli = null){
self::$mysqli = $mysqli;
$this->establishAutoConnection();
}
// Tries to establish connection, if none is set.
protected function establishAutoConnection(){
IF(empty(self::$mysqli)):
SWITCH($_SERVER['SERVER_NAME']):
case 'localhost':
self::$mysqli = new mysqli(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWD, MYSQL_DATABASE);
break;
case 'AN IP.IP.IP':
$this->connectToSlave();
break;
default:
self::$mysqli = new mysqli(MYSQL_HOST_SERVER, MYSQL_USER_SERVER, MYSQL_PASSWD_SERVER, MYSQL_DATABASE_SERVER);
ENDSWITCH;
ENDIF;
}
public function connectToSlave(){
self::$mysqli = new mysqli(SLAVE_HOST_SERVER, SLAVE_USER_SERVER, SLAVE_PASSWD_SERVER, SLAVE_DATABASE_SERVER);
}
public function connectToMaster(){
self::$mysqli = new mysqli(MASTER_HOST_SERVER, MASTER_USER_SERVER, MASTER_PASSWD_SERVER, MASTER_DATABASE_SERVER);
}
// Sets the PDO arguments, which need to be replaced by '?'
public function setArgs(&$data, $type = false){
$type = $type ?: $this->getTypeString($data);
$this->args[0] .= $type;
$this->args[] = &$data;
return $this;
}
// Reset function needs to be called in order to make a new query.
public function reset(){
$this->args = array('');
$this->row = false;
$this->result = false;
return $this;
}
// Loops through the found results.
public function loopThroughResults(){
return ($this->row = $this->result->fetch_assoc())
? true
: false;
}
// Returns the row unformatted. If no result is found an emtpy array is returned.
public function getRow(){
$this->row = $this->row ?: $this->result->fetch_assoc();
return $this->row ?: array();
}
// Returns the first result of the first row.
public function getSingleResult(){
FOREACH($this->getRow() as $assoc => $value):
return $value ?: false;
ENDFOREACH;
return false;
}
// Returns the result by rowname
public function getByName($name){
return isset($this->row[$name])
? $this->row[$name]
: false;
}
// If a new query is made, while the former query has not been resetted, a warning is stored or an error is thrown.
protected function isResetted(){
IF($this->result):
$this->warning("PDO has not been resetted from query: ". $this->lastquery ." // new query: ". $this->query);
ENDIF;
}
// Executes the prepared query.
public function query($sql){
$this->query = $sql;
$this->isResetted();
$this->lastquery = $sql;
IF($prep = self::$mysqli->prepare($this->query)):
IF(count($this->args) > 1):
call_user_func_array(array($prep, 'bind_param'), $this->args);
ENDIF;
$prep->execute();
$this->result = $prep->get_result();
$prep->close();
ELSE:
$this->error("Query $sql failed to prepare.");
ENDIF;
}
// Automatically generates the string of types for the submitted params if not set. ("ssisdss") etc.
protected function getTypeString($string){
SWITCH(gettype($string)):
case 'string':
return 's';
case 'double':
return 'd';
case 'boolean':
case 'integer':
return 'i';
case 'array':
$this->error('Unserialized array submitted to PDO.');
break;
default:
$this->error('Unknown param type submitted to PDO. ' . print_r($string) . ' type: ' . gettype($string));
break;
ENDSWITCH;
}
protected function error($msg){
IF(!new error($msg)):
trigger_error($msg);
ENDIF;
}
protected function warning($msg){
IF(!new warning($msg)):
trigger_error($msg);
ENDIF;
}
}
Did you added the port number in your definition? So e.g.
MYSQL_HOST = 127.0.0.1:3306
MYSQL_HOST_SERVER = 127.0.0.1:3306
mysqli will use his default port settings on your server definition. So if you add the port number here, the result will be the same as your request error:
MYSQL_HOST = 127.0.0.1:3306:3306
MYSQL_HOST_SERVER = 127.0.0.1:3306:3306
Related
I'm wanting to create a new instance of my Class and assign it's attributes the values that are returned. The reason for this is I'm creating a series of methods inheriting from the calling class, as opposed to using static methods which I already had working.
Example of what I'm using currently:
public static function findById($id) {
$id = self::escapeParam($id);
$idVal = is_int($id) ? "i" : "s";
$sql = "SELECT * FROM ".static::$db_table." WHERE id = ? LIMIT 1";
return static::findByQuery($sql,$idVal,$id);
}
public static function findByQuery($sql,$bindChar = '',$bindVal = '') {
try {
$callingClass = get_called_class();
$object = new $callingClass;
$statement = Database::$connection->prepare($sql);
if(!empty($bindChar)) :
$statement->bind_param($bindChar, $bindVal);
endif;
if($statement->execute()) :
$result = $statement->get_result();
$object = $result->fetch_object();
endif;
$statement->close();
if(!empty($object)) :
return $object;
endif;
} catch(Exception $e) {
}
}
What I tried was writing an instantiation method that creates a new instance of my class, and then assign each attribute of the object the value it returns from an array from a tutorial I did. However, the tutorial was fairly outdated and didn't use any new syntax or binding, so I was trying to rework this.
Example from the tutorial below:
public static function find_by_id($id) {
global $database;
$the_result_array = static::find_by_query("SELECT * FROM " . static::$db_table . " WHERE id = $id LIMIT 1");
return !empty($the_result_array) ? array_shift($the_result_array) : false;
}
public static function find_by_query($sql) {
global $database;
$result_set = $database->query($sql);
$the_object_array = array();
while($row = mysqli_fetch_array($result_set)) {
$the_object_array[] = static::instantation($row);
}
return $the_object_array;
}
public static function instantation($the_record){
$calling_class = get_called_class();
$the_object = new $calling_class;
foreach ($the_record as $the_attribute => $value) {
if($the_object->has_the_attribute($the_attribute)) {
$the_object->$the_attribute = $value;
}
}
return $the_object;
}
private function has_the_attribute($the_attribute) {
return property_exists($this, $the_attribute);
}
What I was trying to do from the tutorial, was to return my result as an array using a while, and then assigning a variable by passing the built array into the static::instantation() method, but it doesn't seem to ever be working correctly, as any public functions I create in my calling class (Admin for example) aren't called after as they don't exist due to the Class not being instantiated.
mysqli_result::fetch_object() accepts the class name as the first argument. You can pass the class name as an argument to that method and get the instance of the model. I am not sure why you have that much code but consider my example which I wrote based on your own code:
<?php
class Model
{
public static function findByQuery(string $sql, ?string $bindChar = null, ?string $bindVal = null): ?static
{
$statement = Database::$connection->prepare($sql);
if ($bindChar) :
$statement->bind_param($bindChar, $bindVal);
endif;
$statement->execute();
$result = $statement->get_result();
return $result->fetch_object(static::class);
}
}
class User extends Model
{
private $id;
}
class Database
{
public static mysqli $connection;
}
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
Database::$connection = new mysqli('localhost', 'user', 'password', 'test');
$user = User::findByQuery('SELECT ? as id', 's', 'Dharman');
var_dump($user);
The output from that example is:
object(User)#4 (1) {
["id":"User":private]=>
string(7) "Dharman"
}
As you can see, the code created an instance of the class using late-static binding and it also assigned the value to a private property, which you can't do otherwise.
P.S. My example is a little bit tidier. I added parameter typing and removed a lot of unnecessary code. In particular, I remove empty try-catch which is a terrible practice.
I have now got this working, although I feel this is probably not the best way of doing it.
I'm primarily front end so please comment if there are improvements or best practices.
public static function findByQuery($sql,$bindChar = '',$bindVal = '') {
try {
$statement = Database::$connection->prepare($sql);
if(!empty($bindChar)) :
$statement->bind_param("$bindChar", $bindVal);
endif;
if($statement->execute()) :
$result = $statement->get_result();
$output = $result->fetch_object();
endif;
$statement->close();
if(!empty($output)) :
$class = get_called_class();
$object = new $class;
foreach(get_object_vars($output) as $key => $value) :
$object->$key = $value;
endforeach;
endif;
if(!empty($object)) :
return $object;
endif;
} catch(Exception $e) {
}
}
My initial thoughts were declaring an object and then I thought that the PHP fetch_object call would have just assigned my object it's properties after initiating the Class but that wasn't the case.
So what I've done is that if the statement is successful and a results object is created, I then get the object properties and values with the get_object_vars() command, and then loop through these as a key value pair, assigning each attribute it's returned value.
I can confirm this works as I can now run $admin->remove() from my removal script, as opposed to what I was having to do before which was Admin::remove($id);
I'm building a simple CRUD app as a learning exercise in Angularjs and PHP. I have a shell page, mysql backend, a PHP API that handles the SQL requests, and I'm using Angularjs to handle the flow of data between the shell page and the API. I'm working off an API modeled here:
http://angularcode.com/demo-of-a-simple-crud-restful-php-service-used-with-angularjs-and-mysql/
I've tested every component of this app so far and everything works cleanly except the API. All I've done to modify the original was change the syntax to PDO and I adjusted the response function because the existing one didn't work.
The abstract class:
<?php
class REST {
public $_allow = array();
public $_content_type = "application/json";
public $_request = array();
private $_method = "";
private $_code = 200;
public function __construct(){
$this->inputs();
}
public function get_referer(){
return $_SERVER['HTTP_REFERER'];
}
/*public function response($data,$status){
$this->_code = ($status)?$status:200;
$this->set_headers();
echo $data;
exit;
}*/
public function response($status, $status_message, $data){
header("HTTP/1.1 $status $status_message");
$response['status'] = $status;
$response['status_message'] = $status_message;
$response['data'] = $data;
$json_response = json_encode($response);
}
private function get_status_message(){
$status = array(
200 => 'OK',
201 => 'Created',
204 => 'No Content',
404 => 'Not Found',
406 => 'Not Acceptable');
return ($status[$this->_code])?$status[$this->_code]:$status[500];
}
public function get_request_method(){
return $_SERVER['REQUEST_METHOD'];
}
private function inputs(){
switch($this->get_request_method()){
case "POST":
$this->_request = $this->cleanInputs($_POST);
break;
case "GET":
case "DELETE":
$this->_request = $this->cleanInputs($_GET);
break;
case "PUT":
parse_str(file_get_contents("php://input"),$this->_request);
$this->_request = $this->cleanInputs($this->_request);
break;
default:
$this->response('',406);
break;
}
}
private function cleanInputs($data){
$clean_input = array();
if(is_array($data)){
foreach($data as $k => $v){
$clean_input[$k] = $this->cleanInputs($v);
}
}else{
if(get_magic_quotes_gpc()){
$data = trim(stripslashes($data));
}
$data = strip_tags($data);
$clean_input = trim($data);
}
return $clean_input;
}
private function set_headers(){
header("HTTP/1.1 ".$this->_code." ".$this->get_status_message());
header("Content-Type:".$this->_content_type);
}
}
?>
And the API itself:
<?php
require_once("Rest.inc.php");
class API extends REST {
public $data = "";
private $db = NULL;
private $conn = NULL;
public function __construct(){
parent::__construct();
$this->dbConnect();
}
/*
* Connect to Database
*/
private function dbConnect(){
$this->conn = null;
$servername="myServer";
$dbname="mySQL";
$username="myUN";
$password="myPW";
try{
$this->conn = new PDO("mysql:host=$servername;Database=$dbname",$username, $password);
}catch(PDOException $e){
echo "Failed:" . $e->getMessage();
}
return $this->conn;
}
/*
* Dynmically call the method based on the query string
*/
public function processApi(){
//$func = strtolower(trim(str_replace("/","",$_REQUEST['x']))); //<<--NEED TO FIX THIS. x determines which function to call
$func = 'quote';
if((int)method_exists($this,$func) > 0){
$this->$func();
}else{
$this->response(404,'','');
}
}
private function quote(){
if($this->get_request_method() != "GET"){
$this->response(406, '', '');
}
$id = (int)$this->_request['id'];
if($id > 0){
try{
$sql = "SELECT * FROM mysql.Quotes WHERE ID =:ID";
$query = $this->conn->prepare($sql);
$query->bindParam(":ID", $id);
$query->execute();
$result = $query->fetchAll(PDO::FETCH_ASSOC);
}catch(PDOException $e){
echo "Failed:" . $e->getMessage();
}
echo $this->response(200,"Success",$result);
}
}
// Initiate Library
$api = new API;
$api->processApi();
?>
One issue I'm aware of is that the commented portion in processAPI() does not work. It's supposed to grab the initial part of the URL and determine which function to run based on based on that, but my server keeps throwing an error. My workaround for the time being is just to hard-code $func = 'quote';
More importantly, though, the API returns an empty object whenever it runs. It connects to the DB and executes without errors, and it does return an object as designed -- there just isn't anything inside it. If I pull out the core components -- the DB connection, the SQL request, and the response function -- and run them on their own, they correctly pull the data and pass it on to the shell. So something in the REST class or the API must be fouling it up, but I'm not handy enough in PHP yet to figure out where it's going wrong. I'd appreciate any feedback.
I am trying to fetch query results so i can use the data from mysql as variables on my page
here in the given code i have hardcoded the hotel value as 105 but i am trying to get the value from an other page as get .
$ratedID =$_GET['ratedhotel'];
Here the body of my page is embedded under while.but the page is always empty.and this is what i have at the moment.
$hotel=$database->query('SELECT * FROM rate WHERE HotelID=:hotel ');
$database->bind(':hotel', '105');
$hotel->setFetchMode(PDO::FETCH_ASSOC);
while($r = $hotel->fetch())
Below Is what i had before.
//$query = $db->query("SELECT * from rate WHERE HotelId='$ratedhotelID'");
//while($hotel = mysql_fetch_row($query, MYSQL_ASSOC))
I have some defined functions which I got as a library to use.
<?php
class Database{
private $host=DB_HOST;
private $user=DB_USER;
private $pass=DB_PASS;
private $dbname=DB_NAME;
private $stmt;
private $dbh;
private $error;
public function __construct()
{
// Set DSN
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
public function query($query){
$this->stmt = $this->dbh->prepare($query);
}
public function bind($param, $value, $type = null){
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
public function execute(){
return $this->stmt->execute();
}
public function resultset(){
$this->execute();
return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function single(){
$this->execute();
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
public function rowCount(){
return $this->stmt->rowCount();
}
}
I am not sure and am new to PDO .Any help will be much appreciated.
Jai
UPDATE
I made Changes to php and the code is like below:
$database= new Database();
$database->query('SELECT * from rated where HotelID =:hotel');
$database->bind(':hotel', $HotelID);
//echo $database->resultset();
$rows=array();
$rows= $database->resultset(PDO::FETCH_ASSOC);
//while($rows= $database->resultset());
//while($hotel = $q->fetchAll(PDO::FETCH_ASSOC));
{
echo "<pre>";
print_r($rows);
echo "</pre>";
echo "<div>'.$rows[LowRate].'<div>";
};
?>
So based on the above i can see the array on my page so the query works.
But I want to use the variables in my html like.
<p class="price-display-large page-price-text">'.$rows[LowRate].''.rows[PropertyCurrency].'</p>
But this does not work.
Just replace the harcoded value '105' with a reference to $ratedId.
$database->bind(':hotel', $ratedId);
I don't understand why that wouldn't work for you. Include the bind type, if you want something other than what the library function is going to assign.
$database->bind(':hotel', $ratedId, PDO::PARAM_INT);
(It's likely I entirely misunderstood the question you were asking.)
FOLLOWUP
I expect rows is a multidimensional array, since it looks like a "fetch all" operation has been done. Each row will be an array, but those are all going to be contained in another array.
To see what's in the array, you could do a:
var_dump($rows);
To get the LowRate value from the first row, I think you'd need to refer to it like this:
$rows[0]['Lowrate']
(I think it's zero based, if not, it will be a [1]. The var_dump will show you what it looks like.)
Just because you got an array back, that doesn't mean there's rows in it, it could be an empty set. An resultset with zero rows is a valid resultset, so you really want to check if the row you want is in there or not.
The normative pattern would be to loop through the array of rows, and handle each row individually. For example, using a foreach loop.
foreach($rows as $row) {
echo $row['LowRate'];
}
I'm using MySQL(i)-community-5.3 if not mistaken. After finally getting the hang of PDO, I can now conclude that the infected sectore is that which processes binding, all other functions are fine (that I know of). Below I will present a function which works and also doesn't work (the sequence without anything to do with binding works flawlessly.
Function you() is as followes:
public function you($row) {
if(isset($_COOKIE["SK"])) {
$usr = $this->baseXencode($_SESSION["username"]);
$q = "SELECT $row FROM SN_users WHERE username=:USR";
$this->netCore->q($q);
$this->netCore->bind(":USR", $usr);
$result = $this->netCore->single();
$result = $result[$row];
} else {
$q = "SELECT $row FROM SN_users WHERE username='".$this->baseXencode("Anonymous")."' AND password='".$this->baseXencode("Anonymous")."'";
$result = $this->netCore->q($q);
$result = $this->netCore->single();
$result = $result[$row];
}
return $result;
}
}
(As you can see, when pre-allocating the username/password combo for Anonymous users, the function executes perfectly whereas binding within the if() section does not, returning the value 1.
Below is my binding function bind() (if you may require any other code, I will edit this post further~^^):
EDIT:
Below is the netCore class:
class netCore {
private $boot;
private $dbHost = "";
private $dbNAME = "";
private $dbPASS = "";
private $dbUSR = "";
private $err;
private $state;
public function __construct() {
$bootloadr = "mysql:host=".$this->dbHost.";dbname=".$this->dbNAME.";charset=UTF8";
$opt = array(PDO::ATTR_PERSISTENT => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
try {
$this->boot = new PDO($bootloadr, $this->dbUSR, $this->dbPASS, $opt);
} catch(PDOException $e) {
$this->err = "<b>Lebensborn® netCore™ Error:</b> An exception has been raised during Network-to-Database procedures.<br /><b>Message:</b> ".$e->getMessage().".";
}
}
public function bind($param, $value, $type = NULL) {
if(is_null($type)) {
switch(true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->state->bindParam($param, $value, $type);
}
public function debug() {
return $this->state->debugDumpParams();
}
public function exe() {
return $this->state->execute();
}
public function count() {
$this->exe();
return $this->state->fetchColumn();
}
public function q($q) {
$this->state = $this->boot->prepare($q);
}
public function set() {
$this->exe();
return $this->state->fetchAll(PDO::FETCH_ASSOC);
}
public function single() {
$this->exe();
return $this->state->fetch(PDO::FETCH_ASSOC);
}
public function transBegin() {
return $this->boot->beginTransaction();
}
public function transCancel() {
return $this->boot->rollBack();
}
public function transEnd() {
return $this->boot->commit();
}
}
I am developing a project in which two portions of webpage frequently change and fetch recent data. I have some confusion about whether to use mysql_connect or mysql_pconnect? I have one config file that is being included in every page. There is one database connection object which I use for queries. Even when approximately 70 users are online it shows 20,000 connections on my server. Please suggest me the best way to keep a single connection alive from a single user, so there should be 70 connections when there are 70 users online. Currently I'm not using mysql_close method to close connection. Is this the reason it shows these many connections? Your advice will really be appreciated.
A common pattern used in this case is the singleton pattern, here's some rough code.
class DB_Instance
{
private static $db;
public static function getDB()
{
if (!self::$db)
self::$db = new Database();
return self::$db;
}
}
function getSomething()
{
$conn = DB_Instance::getDB();
.
.
.
}
Some examples/references
http://tutorialpedia.org/tutorials/Singleton+pattern+in+PHP.html
http://www.ricocheting.com/static/code/php/mysql-v3/Database.singleton.phps
http://netlinxinc.com/netlinx-blog/53-php/7-applying-the-singleton-pattern-to-database-connections-in-php.html
Here you have my implementation maybe it is useful for you
<?php
class Utils_Sql{
private $count = 0;
private static $sqlObj = null;
/**
* #return Utils_Sql
*/
public static function getSql(){
if(self::$sqlObj===null){self::$sqlObj = new Utils_Sql();}
return self::$sqlObj;
}
private $db;
private function __construct(){
$this->db = mysql_connect(MYSQL_SERVER,DB_LOGIN,DB_PASS);
if($this->db === false){
Utils_Logging_Logger::getLogger()->log(
array("Unable to connect to DB on Mysql_Server:".MYSQL_SERVER." with login:".DB_LOGIN." and pass:".DB_PASS."!")
,Utils_Logging_Logger::TYPE_ERROR
);
}else{
if (!mysql_select_db ( DB_NAME , $this->db )) {
$sql = "CREATE DATABASE " . DB_NAME;
$this->qry($sql);
if (!mysql_select_db ( DB_NAME , $this->db )) {
Utils_Logging_Logger::getLogger()->log(
array("DB: ".DB_NAME." not found"),
Utils_Logging_Logger::TYPE_ERROR
);
}
}
}
mysql_set_charset ('utf8',$this->getConnection());
}
public function getConnection(){return $this->db;}
public function qry($sql,$errType,$errMsg=""){
$this->count++;
// Utils_Logging_Logger::getLogger()->log("<br>$sql<br>",Utils_Logging_Logger::TYPE_LOG);
$ret = mysql_query($sql,$this->getConnection());
if(mysql_error($this->getConnection())){
//Error
$msgs = array(
"mysql_error: (".mysql_error($this->getConnection()).")",
"qry: \"$sql\""
);
if($errMsg!==""){$msgs[]="$errMsg";}
Utils_Logging_Logger::getLogger()->log($msgs,$errType);
}
return $ret;
}
public function getData($sql,$errType=Utils_Logging_Logger::TYPE_ERROR){
$r = $this->qry($sql,$errType);
if($r === false){
Utils_Logging_Logger::getLogger()->log("No Sql Resource, Illegal Query!",$errType);
return false;
}
$ret = array();
while(($data = mysql_fetch_assoc($r))!==false){
$ret[] = $data;
}
if(count($ret)===1){return $ret[0];}
else if(count($ret)>1){return $ret;}
else{
$msgs = array(
"No resulset found.",
"qry: \"$sql\""
);
Utils_Logging_Logger::getLogger()->log($msgs,$errType|Utils_Logging_Logger::TYPE_WARNING);
return false;
}
}
public function getInsertId($sql,$errType=Utils_Logging_Logger::TYPE_ERROR){
$this->qry($sql,$errType);
$ret = mysql_insert_id($this->getConnection());
if(!is_numeric($ret)){Utils_Logging_Logger::getLogger()->log("mysql_insert_id is not numeric!",$errType);}
return $ret;
}
public function getDbName(){return DB_NAME;}
public function __destruct(){
// Utils_Logging_Logger::getLogger()->log("Querys count: '$this->count'",Utils_Logging_Logger::TYPE_LOG);
}
}
Interstellar_Coder is correct, you want to use a singleton/factory solution for your db connection handling. We use here at work and it serves us well.
While Interstallar_Coder's solution is valid, I wrote up a more flexible solution in response to another post.
Destroy db connections:
public function __destruct()
{
foreach (self::$dbos as $key => $dbo) {
self::$dbos[$key] = null;
}
}
More info about PDO connection management.