here is my code
pdo.php
class Connection {
public function __construct() {
$this->connect ($db);
}
private function connect($db) {
try {
if (! $db){
$this->db = new PDO ( 'mysql:host=localhost;dbname=Shopping;charset=utf8', 'xxxx', 'xxxxx' );
echo 'Connected';
return $this->db;
}
catch ( PDOException $conError ) {
echo 'failed to connect DB' . $conError->getMessage ();
}
}
}
product.php
class ProductInsert extends Connection { //here my function is called multiple times
function __construct() {
parent::__construct($db);
}
public function prdInsert(.....)
{ ........}
here my problem is database connection is opened multiple time. when ever i am calling the productInsert() then database connection is opened how i can prevent this
Do not extend your application class from database class.
This is your main problem.
They are too different classes having nothing in common.
So you have to just use your db object as a property.
Connection class is also useless at the moment, as it's just a leaky disguise for the PDO.
So, just create raw PDO object and then pass it in the constructor of product
class ProductInsert
{
function __construct(PDO $db)
{
$this->db = $db;
}
public function prdInsert(.....)
}
And for goodness sake, learn to indent your code.
class Connection {
public function __construct($db) {
return $this->connect($db);
}
private function connect($db) {
try {
if (! $db){
$db = new PDO ( 'mysql:host=localhost;dbname=Shopping;charset=utf8', 'xxxx', 'xxxxx' );
echo 'new connection';
}
return $db;
}
catch ( PDOException $conError ) {
echo 'failed to connect DB' . $conError->getMessage ();
}
}
}
here is the solution
pdo.php
class Connection {
// Declare instance
private static $instance = NULL;
// the constructor is set to private so so nobody can create a new instance using new
private function __construct() {
// maybe set the db name here later
}
// Return DB instance or create intitial connection #return object (PDO) #access public
public static function getInstance() {
if (! self::$instance) {
self::$instance = new PDO ( 'mysql:host=localhost;dbname=Shopping;charset=utf8', 'root', 'vss0ftech' );
self::$instance->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
echo 'connected';
} else
echo 'connection is already existed';
return self::$instance;
}
// Like the constructor, we make __clone private so nobody can clone the instance
PRIVATE FUNCTION __CLONE() {
}
}
product.php
here we can call the method as like this
class ProductInsert {
public function prdInsert(.....) {
$result_By_Vendor_And_Title = Connection::getInstance ()->query ( "select * from........)
}
}
Related
i have two classes in my project.
Db.php :
<?php
namespace app\core;
use \PDO;
class Db
{
private $dsn = 'mysql:host=localhost;dbname=test';
private $user = 'root';
private $password = '6ReA4';
private $options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
];
private static $PDO = null;
private function __construct()
{
try {
self::$PDO = new \PDO($this->dsn,$this->user,$this->password, $this->options);
} catch (\PDOexception $e) {
/* Exception of datebase connection (error message in future) */
echo "Date base connection error ".$e->getMessage();
}
}
private function __clone() {}
private function __wakeup () {}
public static function conDb()
{
if (is_null(self::$PDO)) {
return new self();
} else { return self::$PDO; }
}
}
and Model.php
<?php
namespace app\core;
class Model
{
private $db;
private $db2;
public function __construct()
{
$this->db2 = Db::conDb();
$this->db = Db::conDb();
if ($this->db == $this->db2) {
echo "Singleton works";
} else { echo "Fail"; }
}
public function getById()
{
}
public function getAll()
{
}
}
private $db;
private $db2;
public function __construct()
{
$this->db2 = Db::conDb();
$this->db = Db::conDb();
if ($this->db == $this->db2) {
echo "Singleton works";
} else { echo "Fail"; }
}
public function getById()
{
}
public function getAll()
{
}
}
I'm trying to realize singleton pattern but method conDb() during the Model object creation returns an empty object a second time instead of the same one. Please help me to understand what is the problem and how can i solve this? What am i doing wrong?
The issue resides in the Db class definition. The first time you called conDb it returned a new Db object that then assigned the static variable a PDO object.
The second time you call that method you get back a PDO object which made the if guard evaluate to false, since a Db object and PDO object are different. In case you call it more than 2 times the objects returned thereafter would be PDO objects and tested for true.
Below a suggested change to the Db class.
class Db
{
private $dsn = 'mysql:host=localhost;dbname=test';
private $user = 'root';
private $password = '6ReA4';
private $options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
];
private static $PDO = null;
private function __clone()
{
}
private function __wakeup()
{
}
public static function conDb()
{
// This is always null the first call
if (is_null(self::$PDO)) {
// Here you returned a new Db object.
// return new self(); // <- old line.
try {
self::$PDO = new \PDO($this->dsn, $this->user, $this->password, $this->options);
} catch (\PDOexception $e) {
"Date base connection error " . $e->getMessage();
}
}
// Here you returned a PDO object in an else, this can just be the variable after the PDO object is created.
return self::$PDO;
}
}
In the construction of the Model, the if would evaluate to false testing a Db object vs a PDO object.
public function __construct()
{
$this->db2 = Db::conDb();
$this->db = Db::conDb();
if ($this->db == $this->db2) {
echo "Singleton works";
} else {
echo "Fail";
}
}
I have a try catch block that connects via PDO to a database. I would like to be able to reference it in all my functions without having to pass it as a parameter. How would I do this? The mentioned code is:
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e) {
echo $e->getmessage();
die();
}
EDIT:
I created a singleton class (attempt below) that executes the try catch block upon _construct
final class database {
private static $instance = NULL;
private function __construct() {
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo $e->getmessage();
die();
}
}
public static function getInstance() {
static $instance = null;
if (self::$instance === NULL) {
$instance = new database();
}
return $instance;
}
}
Declare it as a static attribute of a singleten class. Than you can access it with
$pdo = Singleton::instance()->getConnection();
Alternatively I can suggest taking a look at MArtin Fowler's relational database mapping pattern. It goes a step further, than centralizing ony the connection itself.
Alternatively Doctirne project has a complete implementation of that: www.doctrine-project.org
final class database {
private static $instance = NULL;
private $pdo; //added private variable for pdo
private function __construct() {
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo $e->getmessage();
die();
}
$this->pdo = $database; //saved the connection into the new variable
}
public static function getInstance() {
static $instance = null;
if (self::$instance === NULL) {
$instance = new database();
}
return $instance;
}
//added a function to get the connection itself
function getConnection(){
return $this->pdo;
}
}
So now you use it:
$pdo = database::getInstance()->getConnection();
Hey guys I'm doing this wrong again I'm sure, but I'm trying to instantiate a PDO database
handler from my class Database from the file class.database.php inside my class AdminSession
from class.admin.php, somethings a bit screwy with my dependancy injection, and it is not
allowing me to use PDO's methods corretly; like fetch(), prepare() etcetra.
the class.database.php file
class Database
{
public $db; // handle of the db connection
private static $dsn="mysql:host=server2.com;dbname=database";
private static $user="user";
private static $pass="pass";
private static $instance;
public function __construct ()
{
$this->db = new PDO(self::$dsn,self::$user,self::$pass,$self::$opts);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
switch($_SERVER['ENVIRONMENT']) {
case 'staging':
self::$dsn="mysql:host=server1.com;dbname=database";
self::$user="user";
self::$pass="pass";
break;
default:
self::$dsn="mysql:host=server2.com;dbname=database";
self::$user="user";
self::$pass="pass";
}
}
public static function getInstance()
{
if(!isset(self::$instance))
{
$object= __CLASS__;
self::$instance=new $object;
}
return self::$instance;
}
}
and here's the topmost of my class.admin.php, and a method that is throwing an error.
right now the errors I'm getting
PHP Fatal error: Call to undefined method line 230
If I use $this->db-prepare($sql)
or
PHP Fatal error: Call to a member function prepare() on a non-object line 230
If I use $db-prepare($sql)
require('library/class.database.php');
class AdminSession {
static $abs_path;
public function __construct(Database $db) {
session_start();
self::$abs_path = dirname(dirname(__FILE__));
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->post = $_POST; // filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
if(get_magic_quotes_gpc ()) {
//get rid of magic quotes and slashes if present
array_walk_recursive($this->post, array($this, 'stripslash_gpc'));
}
}
$this->get = $_GET; // filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
array_walk_recursive($this->get, array($this, 'urldecode'));
}
// other methods
private function checkDB($username, $password) {
$sql = "SELECT * FROM users WHERE username=:username";
try {
$db = Database::getInstance();
$stmt = $db->prepare($sql);
$stmt->bindParam("username", $username);
$stmt->execute();
$user = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
if($user) {
//general return
if(is_object($user[0]) && md5($user[0]->password) == $password) {
return true;
} else {
return false;
}
} else {
return false;
}
} catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
}
You can't put logic into your class definition. Instead, determine the value of these variables within the constructor. The switch will work in a method, but not when defining members.
Edit: I actually feel silly for missing this. The connection was made before the switch statement. I don't know that it'll fix the second set of issues ... but it'll behave properly for the original question now.
class Database
{
public $db; // handle of the db connection
private static $opts = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
private static $dsn="mysql:host=server2.com;dbname=database";
private static $user="user";
private static $pass="pass";
private static $instance;
public function __construct ()
{
switch($_SERVER['ENVIRONMENT']) {
case 'staging':
self::$dsn="mysql:host=server1.com;dbname=database";
self::$user="user";
self::$pass="pass";
break;
default:
self::$dsn="mysql:host=server2.com;dbname=database";
self::$user="user";
self::$pass="pass";
}
$this->db = new PDO(self::$dsn,self::$user,self::$pass,$self::$opts);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public static function getInstance()
{
if(!isset(self::$instance))
{
$object= __CLASS__;
self::$instance=new $object;
}
return self::$instance;
}
}
Can anybody please guide me with a sample code to establish a database connection in php using singleton class.
class DatabaseSingleton
{
// [Singleton]
private static $instance = null;
public static function getInstance()
{
if (!self::$instance)
{
self::$instance = new self();
}
return self::$instance;
}
private function __clone(){}
// [/Singleton]
private $connection = null;
private function __construct()
{
$this->connection = mysql_connect('localhost','root','admin');
if ($this->connection)
{
mysql_select_db('my_database');
}
}
//
// crud operations go here.
//
}
$db = DatabaseSingleton::getInstance();
$db->SomeCRUDOperation();
Something like that perhaps? Very basic, but should give you a starting point.
That's how a singleton-pattern looks like:
<?php
class SingletonClass
{
static private $instance = null;
static public function getInstance()
{
if (null === self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
private function __construct(){}
private function __clone(){}
}
$singletonClass = SingletonClass::getInstance();
Now you can put random functions and parameters in there that handle your DB-stuff. I hope that answers your question.
See the manual for an example on how to implement the Singleton pattern: http://www.php.net/manual/en/language.oop5.patterns.php
Then just establish the database connection in your class constructor.
I use something like this:
class DBConn
{
static private $_db = null; // The same PDO will persist from one call to the next
private function __construct() {} // disallow calling the class via new DBConn
private function __clone() {} // disallow cloning the class
/**
* Establishes a PDO connection if one doesn't exist,
* or simply returns the already existing connection.
* #return PDO A working PDO connection
*/
static public function getConnection()
{
if (self::$_db == null) { // No PDO exists yet, so make one and send it back.
try {
self::$_db = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PASS);
} catch (PDOException $e) {
// Use next line for debugging only, remove or comment out before going live.
// echo 'PDO says: ' . $e->getMessage() . '<br />';
// This is all the end user should see if the connection fails.
die('<h1>Sorry. The Database connection is temporarily unavailable.</h1>');
} // end PDO connection try/catch
return self::$_db;
} else { // There is already a PDO, so just send it back.
return self::$_db;
} // end PDO exists if/else
} // end function getConnection
} // end class DBConn
/**
* And you can use it as such in a class
* */
class Post {
public function __construct(){
$this->db = DBConn::getConnection();
}
public function getPosts()
{
try {
/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM posts";
foreach ($this->_dbh->query($sql) as $row) {
var_dump($row);
}
/*** close the database connection ***/
$this->_dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
}
}
}
I am using something like below
class Database
{
private $_connection;
private static $_instance; //The single instance
private $_host = "HOST";
private $_username = "USERNAME";
private $_password = "PASSWORd";
private $_database = "DATABASE";
public static function getInstance() {
if(!self::$_instance) { // If no instance then make one
self::$_instance = new self();
}
return self::$_instance;
}
private function __construct() {
$this->_connection = new mysqli($this->_host, $this->_username,
$this->_password, $this->_database);
// Error handling
if(mysqli_connect_error()) {
trigger_error("Failed to conencto to MySQL: " . mysqli_connect_error(),
E_USER_ERROR);
}
}
// Magic method clone is for prevent duplication of connection
private function __clone() { }
public function getConnection() {
return $this->_connection;
}
}
$db = Database::getInstance();
$mysqli = $db->getConnection();
$sql_query = "SELECT foo FROM etc";
$result = $mysqli->query($sql_query);
In my project I have a database class that I use to handle all the MySQL stuff. It connects to a database, runs queries, catches errors and closes the connection.
Now I need to create a members area on my site, and I was going to build a users class that would handle registration, logging in, password/username changes/resets and logging out. In this users class I need to use MySQL for obvious reasons... which is what my database class was made for.
But I'm confused as to how I would use my database class in my users class. Would I want to create a new database object for my user class and then have it close whenever a method in that class is finished? Or do I somehow make a 'global' database class that can be used throughout my entire script (if this is the case I need help with that, no idea what to do there.)
Thanks for any feedback you can give me.
Simple, 3 step process.
1/ Create a database object.
2/ Give it to your user class constructor.
3/ Use it in the user methods.
Little example.
File Database.class.php :
<?php
class Database{
public function __construct(){
// Connects to database for example.
}
public function query($sqlQuery){
// Send a query to the database
}
[...]
}
In User.class.php :
<?php
class User{
private $_db;
public function __construct(Database $db){
$this->_db = $db;
}
public function deleteUser(){
$this->_db->query('DELETE FROM Users WHERE name = "Bobby"');
}
}
Now, in userManager.php for example :
<?php
$db = new Database();
$user = new User($db);
// Say bye to Bobby :
$user->deleteUser();
If you want the current trendy name of this old technique, google "Dependency Injection". The Singleton pattern in php will fade away soon.
As he said, put all your functions in the database class and use the database object to access those functions from your user class. This should be the best method in your case.
Eg:
global $database;
userclassvar = $database->doSomething();
What I like to do is make the database class with the Singleton pattern in mind. That way, if you already have a database object, it just retrieves it, otherwise creates a new one. For example:
Database.class.php
class Db
{
protected static $_link;
private function __construct()
{
// access your database here, establish link
}
public static function getLink()
{
if(self::_link === null) {
new Db();
}
return self::_link;
}
// etc.
}
User.class.php
class User
{
protected $_link; // This will be the database object
...
public function __construct()
{
$this->_link = Db::getLink();
}
}
And now you can use User's $_link property to do the database functions, like $this->_link->query(...). You don't necessarily have to put the Db::getLink() in the constructor if your class doesn't have to interact with the database that much.
Since you are using the database as an object, why not just add methods to the object that your "users class" can employ to take care of the things it needs to do. The users class can contain a pointer to the database class. The database class will protect your database, and assure that the users class is using it appropriately.
Here is a solution using PDO.
<?php
class Database {
private static $dbh;
public static function connect() {
$host = "mysql:dbname=YOUR_DB_NAME;host=YOUR_DB_SERVER";
$username = "YOUR_USERNAME";
$password = "YOUR_PASSWORD";
try {
self::$dbh = new PDO( $host, $username, $password );
self::$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
self::$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
self::$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
} catch( PDOException $e ){
$error_message = $e->getMessage();
exit();
}
return self::$dbh;
}
}
class MYObject {
public static $dbh = null;
public function __construct(PDO $db = null) {
if($db === null){
$this->dbh = Database::connect();
} else {
$this->dbh = $db;
}
}
}
class User extends myObject {
public function __construct($id = null, PDO $db = null) {
if($db === null){
parent::__construct();
} else {
parent::__construct($db);
}
if($id !== null){
return $this->select($id);
}
}
public function select($id) {
$retVal =false;
try {
$stmt = $this->dbh->prepare("SELECT...");
$stmt->execute();
if( $stmt->rowCount()==1 ){
$row = $stmt->fetchAll(PDO::FETCH_ASSOC);
$retVal =json_encode($row);
}
} catch (PDOException $e ) {
$error_message = $e->getMessage();
exit();
}
return $retVal;
}
}
?>
I think the better aproach would be to create the database class that instatiate right away on its own on a database.php and then include it on user.php. then every time you create a function that needs a database, you globalise the database object.
Check this.
databse.php
<?php
require_once ('includes/config.php');
class MysqlDb{
public $connection;
private $last_query;
private $magic_quotes_active;
private $real_escape_string_exists;
public function __construct() {
$this->open_connection();
$this->magic_quotes_active = get_magic_quotes_gpc();
$this->real_escape_string_exists = function_exists( "mysql_real_escape_string" );
}
public function open_connection() {
$this->connection = mysql_connect(DBHOST,DBUSER,DBPASS);
if(!$this->connection){
die("Could not Connect ".mysql_error());
}else{
$db = mysql_select_db(DB, $this->connection);
}
}
public function close_connection(){
if(isset($this->connection)){
mysql_close($this->connection);
unset($this->connection);
}
}
public function query($sql){
$this->last_query = $sql;
$results = mysql_query($sql, $this->connection);
$this->comfirm_query($results);
return $results;
}
private function comfirm_query($results){
if(!$results){
$output = "Query Failed " .mysql_error()."<br />";
$output .= "Last Query: " . $this->last_query;
die($output);
}
}
public function escape_value($value){
if( $this->real_escape_string_exists ) {
if($this->magic_quotes_active ) { $value = stripslashes( $value ); }
$value = mysql_real_escape_string( $value );
} else {
if( !$this->magic_quotes_active ) { $value = addslashes( $value ); }
}
return $value;
}
public function fetch_array($results){
return mysql_fetch_array($results);
}
public function num_row($results){
return mysql_num_rows($results);
}
public function insert_id(){
return mysql_insert_id($this->connection);
}
public function affected_row(){
return mysql_affected_rows();
}
}
$database = new MysqlDb();
?>
here is the user.php
<?php
require_once ('includes/database.php');
class User {
public $id;
public $fName;
public $lName;
Public $userName;
public $password;
public $email;
public $acess;
public static function find_all(){
global $database;
return self::find_by_sql("SELECT * FROM users");
}
public static function find_by_id($id=0){
global $database;
$results_array = self::find_by_sql("SELECT * FROM users where id={$id}");
return !empty($results_array)? array_shift($results_array) : false;
}
public static function find_by_sql($sql){
global $database;
$results = $database -> query($sql);
$object_array = array();
while($row = $database -> fetch_array($results)){
$object_array[] = self::instantiate($row);
}
return $object_array;
}
public static function instantiate($row){
$user = new self;
foreach($row as $attribute => $value){
if($user -> has_attribute($attribute)){
$user -> $attribute = $value;
}
}
return $user;
}
private function has_attribute($attribute){
$object_vars = get_object_vars($this);
return array_key_exists($attribute, $object_vars);
}
}
?>