How to Use Pdo Connection in Other Classes

How to use PDO connection in other classes?

  • your current class is rather useless. It would make sense to create a database wrapper if it adds some extra functionality to PDO. But given its current code, better to use vanilla PDO instead.
  • Either way, create a single $db instance from either vanilla PDO or your database class.
  • pass it as a constructor parameter into every class that needs a database connection

database.php:

<?php
$host = '127.0.0.1';
$db = 'test';
$user = 'root';
$pass = '';
$charset = 'utf8';

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$opt = [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new \PDO($dsn, $user, $pass, $opt);

user.php

<?php
class User {
/* Properties */
private $conn;

/* Get database access */
public function __construct(\PDO $pdo) {
$this->conn = $pdo;
}

/* List all users */
public function getUsers() {
return $this->conn->query("SELECT username, usermail FROM user")->fetchAll();
}
}

app.php

include 'database.php';
$user = new User($pdo);
$list = $user->getUsers();

foreach($list as $test) {
echo $test["username"],"\n";
}

output:

username_foo
username_bar
username_baz

Check out my (The only proper) PDO tutorial for more PDO details.

How to use the PDO connection work in the class

First, Connect() is a member function, while Query($sql) is a static function. I would suggest to define both the same way, either as member or as static.

Next $conn needs to be accessible from both methods, so make it a class variable instead a local variable in Connect().

Here is a version without static functions/variables:

<?php
class DBConnection{

private $conn;

public function __construct(){
}
public function Connect(){
try {
$this->conn = new PDO('mysql:host=localhost;dbname=hqe', 'root', '');
$this->conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$this->conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

} catch (Exception $e) {
echo 'ERROR: ' . $e->getMessage();
}
}

public function Query($sql){
return $this->conn->prepare($sql);
}
}

As you can see, the member variable is accessed using $this. Further you need an object of the class to call Query(). Something like:

$c = new DBConnection();
$c->Query("Select id, first_name, last_name from tbl_user");

Here is a version where all is defined as static:

<?php
class DBConnection{

private static $conn;

public function __construct(){
}
public static function Connect(){
try {
self::$conn = new PDO('mysql:host=localhost;dbname=hqe', 'root', '');
self::$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
self::$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

} catch (Exception $e) {
echo 'ERROR: ' . $e->getMessage();
}
}

static public function Query($sql){
return self::$conn->prepare($sql);
}
}

As you can see, the static variable is accessed using self::.

How to use $PDO variable in another class?

class MyDb{
public $pdo;
private static $instance;

public function __construct(PDO $pdo){
$this->pdo = $pdo;
}

public static function getInstance()
{
if (!isset(self::$instance))
{
$object = __CLASS__;
self::$instance = new $object;
}
return self::$instance;
}

}

$query = MyDb::getInstance()->pdo->query('SELECT * FROM ...');

PHP PDO-MYSQL : How to use database connection across different classes

Solution 1

Replace class account_info { with class account_info extends connection {

Replace

$con = new connection();
$info = new account_info();

with

$info = new account_info();

and it should work.

Solution 2 (suggested)

I highly suggest you to solve your problem with dependency injection in this case.
Just replace your account class with:

class account_info {

private $con;

public function __construct(connection $con) {
$this->con = $con->con;
}

public function getAccountInfo(){

$acc_info = $this->con->prepare("SELECT * FROM account_info");
$acc_info->execute();

$results = $acc_info->fetchAll(PDO::FETCH_OBJ);

foreach ($results as $key) {
$results->owner_firstname;
}
}

}

and use it in index.php like this:

include_once 'classes/connection.class.php';
include_once 'classes/accountinfo.class.php';

$con = new connection();
$info = new account_info($con);
$info->getAccountInfo();

Explanation

As a general good rule: always specify the scope keyword for functions (public, protected or private).

The first solution is called inheritance and what we basically did was extending the account class with the connection class in order to inherit all the methods and properties from the connection class and easily use them. In this case you have to watch out for naming conflicts. I suggest you to take a look at the class inheritance in the PHP manual.

The second solution is called dependency injection and it is a wildly encouraged design pattern that makes your classes accept other classes in their constructor in order to explicitly define the class dependency tree (in this case account depend from connection and without the connection we can't make account work).

Another, of thousands of possible solution, would be the one that someone posted below which is a design pattern called Singleton. However that patter has been reevaluated recently as anti-pattern and should not be used.

PHP A Good way to pass the PDO Object into other Main classes

In general, you'd create your database object outside of this class and then inject it as a parameter. This is called Dependency Injection and is a Good Thing™.

Then you'd use that parameter within your class-specific methods. So your employee class would look something like this:

class Employee
{
protected $db;

public function __construct(PDO $db)
{
$this->db = $db;
}

public function find($id)
{
// or whatever your query looks like
$stmt = $this->db->query('SELECT * FROM EMPLOYEE WHERE id = :id');
// $row = ...
return $row;
}

public function getAll()
{
$stmt = $this->db->query('SELECT * FROM EMPLOYEE');
// whatever
}
}

And then to use that class, you'd instantiate a database object, and then pass that to the Employee:

$db = new PDO();
$employee = new Employee($db);
$steve = $employee->find(1);

You should not do this:

class Employee
{
public $db;

public function __construct(PDO $db)
{
$this->db = $db;
}
}
$db = new PDO();
$employee = new Employee($db);
$steve = $employee->db->query('...');

Or this:

class Employee extends PDO
{
// ...
}
$employee = new Employee($db);
$employee->query('...');

PDO database connection can not be used in other classes, but others can?

In the return statement of getConnection method you should write the class variable without $:

return $this->db;

Also, you must do the queries on the PDO connection instead of your database handler class, so $database = databaseHandler::getInstance(); should be

$database = databaseHandler::getInstance()->getConnection();

or you can simply use the __call magic method to keep your code as it is right now:

public function __call($method, $args)
{
return call_user_func_array(array($this->db, $method), $args);
}

Also, to clarify how to use this class, you should call it inside every method you need the database to be used, not only once on the top of your file, because defining it there it will not be available inside your methods/functions unless you don't use the global statement to import the variable. However usage of the global variable is not encouraged and it is considered as a bad practice. An example on how to use the database would be:

public function doSomething()
{
$db = databaseHandler::getInstance()->getConnection();
$db->prepare(....);
}

public function doSomethingElse()
{
$db = databaseHandler::getInstance()->getConnection();
$db->prepare(....);
}

If you know there are many methods inside your class that uses the database then you can define it as a class variable and set the db instance in the constructor.

PHP - How to access pdo object from other (multiple) classes

You dont want any of these to extend the database class because that will essentially make them all singletons of which you can only have one instance... you Want to make them USE the database class instead. So you would put you most abstract db methods on the Database and then methods that create queries for specific things would be on the User or what have you. This means your Database actually wraps PDO and is what all other classes work with for db operations. The Main or Base class may not even be needed unless you are trying to implement active record or something.

class Database {
static protected $instance;

/**
* @var PDO
*/
protected $connection;

protected function __construct($dsn, $user, $pass, $attrs = array()) {
// create pdo instance and assign to $this->pdo
}

public static function getInstance() {
if(!self::$instance) {
// get the arguments to the constructor from configuration somewhere
self::$instance = new self($dsn, $user, $pass);
}

return self::$instance;
}

// proxy calls to non-existant methods on this class to PDO instance
public function __call($method, $args) {
$callable = array($this->pdo, $method);
if(is_callable($callable)) {
return call_user_func_array($callable, $args);
}
}
}

class Main {
protected $db;

public function __construct() {
$this->db = Database::getInstance();
}
}

class User extends Main{

public function __construct() {
parent::__construct();
}

public function findById($id) {
$qry = $this->db->prepare('SELECT * FROM users WHERE userID = :userID');
$qry->execute(array(':userID' => $id));
$results = $qry->fetchAll(PDO::FETCH_ASSOC);

return $results
}
}

PHP PDO - what is the proper usage for multiple connecting classes?

Not everyone likes singleton style class, but that is one solution. Have an application object/class that you include in every page.

The nice part with this, is that it only connects if/when you use the connection, not all pages may require a db connection

class App {

private static $PDO_INSTANCE;

public static function getPdoInstance() {
if (!self::$PDO_INSTANCE) {
self::$PDO_INSTANCE= // TODO build pdo connection
}

return self::$PDO_INSTANCE;
}

}

Then to use it

$pdo = App::getPdoInstance();
// do db logic here

Addition to original answer

I try to keep all my database access in one set of classes, a common name for that would be the "data access layer" or "data repository".

Those classes are the only ones that needs to know about the pdo connection.

for example

class calendar_page {

function index() {
$dal_calendar = new DalCalendar();
$events = $dal_calendar->getEvents();
// render html using data
}
}


class DataAccessLayer {

private $pdo;

function __construct() {
$this>pdo = App::getPdoInstance();
}

class DalCalendar extends DataAccessLayer {

function getEvents() {
$this->pdo-> // query for events
return $events;
}

}

Another way you an pass the connection around is by using Dependency injection, you would have to google more info on that, it's not something i can give you a quick example of.



Related Topics



Leave a reply



Submit