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

I'm kinda new to PDO with MYSQL, here are my two files:
I have a connection class that I use to connect to the database:
class connection{
private $host = 'localhost';
private $dbname = 'devac';
private $username = 'root';
private $password ='';
public $con = '';
function __construct(){
$this->connect();
}
function connect(){
try{
$this->con = new PDO("mysql:host=$this->host;dbname=$this->dbname",$this->username, $this->password);
$this->con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo 'We\'re sorry but there was an error while trying to connect to the database';
file_put_contents('connection.errors.txt', $e->getMessage().PHP_EOL,FILE_APPEND);
}
}
}
I have an account_info class that i use to query the data from the database:
class account_info{
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;
}
}
}
I include both these files in my index.php page:
include_once 'classes/connection.class.php';
include_once 'classes/accountinfo.class.php';
$con = new connection();
$info = new account_info();
$info->getAccountInfo();
I just cant get it to work I'm not getting any output, I think it has something to do with the scope, but I don't know the correct why to fix it as I'm new to this PDO and OOP stuff.
Thanks in advance.

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.

A common method is to use a singleton pattern in your database class.
Something like this:
class connection {
private static $hInstance;
public static function getInstance() {
if (!(self::$hInstance instanceof self)) {
self::$hInstance = new self();
}
return self::$hInstance;
}
/* your code */
}
Then, you can simply use
$database = connection::getInstance();
$database->con->prepare(....)
etc

Related

How many SQL-connections they are recommended in a project PHP ? What is the ideal number of SQL-connections?

I work now on a project for learning i'm a beginner, i use singelton pattern to make sure, that there is just one PDO connection to the Data Base.
I made var_dump() for all possible connections to the Mysql and I founded that there were 10 objects of pdo.
how can i found, from where come all this objects?
Are 10 objects of PDO normal?
I wanted to use just one for all the project.
my singelton
<?php
namespace App\Database;
use PDO;
use PDOException;
class DataBase
{
private static $instance;
private PDO $pdo;
private function __construct()
{
try {
$db= parse_ini_file("..//..//..//config.ini");
#$db= parse_ini_file("..//..//config.ini");
$type = $db['type'];
$host = $db['host'];
$name = $db['name'];
$user = $db['user'];
$password = $db['password'];
$this->pdo = new PDO($type . ':host=' . $host . ';dbname=' . $name, $user, $password);
}
catch (PDOException $e) {
echo "there is an error";
die();
}
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
return $this->pdo;
}
private function __clone() {}
public static function getInstance()
{
if (!static::$instance) {
static::$instance = new DataBase();
}
return static::$instance;
}
public function getPdo(): PDO
{
return $this->pdo;
}
}
?>
then I made a connection of the pdo like this in another place, where I need to use pdo init.
function makePdo(){
$db= DataBase::getInstance();
$pdo= $db->getPdo();
var_dump($pdo);
return $pdo;
}
Thank you
10 connections are not normal, you should have only one to one DB. Use singleton pattern for database connection:
https://gist.github.com/jonashansen229/4534794
https://phpenthusiast.com/blog/the-singleton-design-pattern-in-php
In this case, you will have one connection and always will get it instead of creating duplicates.
No it should be only one object, the best way to implment it, is to create a separate config file to store your DBMS credentials as associative array, like mysql db_name, host .. etc.
Then create a config class to get those values by creating a static get method.
and finally use this get method inside your db constructor to get the credentials.
I'm pretty sure If you do that you'll get only one instance of PDO object.

One connection for ALL ,OOP PHP

struggling to grip the varying levels of variables in OOP PHP. I want to have one connection file which can be accessed from all classes and functions through out my project. I include 'config.php' but the $mysql variable cannot be found. Any help greatly appreciated;
I have a file
config.php
public $mysqli = new mysqli('localhost', 'usernameEG', 'passwordEG', 'databaseEG');
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
and a few class files
class.User.php
<?php
class User {
private $mysqli = null;
function __construct(){
//=========
//include config.php here?
}
function myProfile($Id){
$stmt = $this->mysqli->prepare("SELECT First_Name, Last_Name, Email, DateJoined FROM members WHERE Id = ? ");
$stmt->bind_param('i',$Id);
$stmt->execute();
$stmt->bind_result($fname,$lname,$email,$date);
$stmt->store_result();
$stmt->fetch();
echo "<p>User#: ".$Id."</p>";
echo "<p>First Name: ".$fname."</p>";
echo "<p>Last Name: ".$lname."</p>";
echo "<p>Email: ".$email."</p>";
echo "<p>Date Joined: ".$date."</p>";
$stmt->close();
}
function example(){
EXAMPLE CODE HERE WILL ALSO NEED TO BE ABLE TO USE SAME CONNECTION
}
}
So rather than a singleton approach as hinted at in the other answer. Let me offer you a dependency injection approach. For a lot of experienced developers, dependency injection is a preferred approach, as it allows the class receiving the dependency to have looser coupling to the dependency (for example, you don't need to even know the name of the class for instantiating the dependency like you would with a singleton approach). You just need to know that the dependency being passed meets some interface requirement (i.e. it implements some interface or is a certain type of class).
So that would look more like this:
class User {
protected $mysqli = null;
// other properties
public function __construct(mysqli $mysqli) {
$this->mysqli = $mysqli;
// other constructor operations
}
// other methods
}
So what is happening here? Here you enforce the requirement to pass an object of type mysqli when instantiating this class. This could be a mysqli object or perhaps even your own custom class which extends mysqli, the User class doesn't care, so long as all mysqli class methods are implemented
Usage could be like
require('/path/to/db_config.php'); // an include which creates a mysqli object or provides a factory for one, or whatever
$user = new User($mysqli);
$user->foo(); // do something
Interestingly enough, you might at times see use of singelton pattern along with dependency injection. So say you had a mysqli_singleton_factory class with singleton functionality to provide you the single instantiated mysqli object. The usage might look like this:
require('/path/to/db_config.php'); // an include which provides a singleton
$user = new User(mysqli_singleton_factory::get_instance());
$user->foo(); // do something
$other_class = new other_class_requiring_mysqli(mysqli_singleton_factory::get_instance());
$other_class->bar(); // do something
Here you have both guaranteed that you only have one instantiated mysqli object during script execution AND you have decoupled your User class from having to do any instantiation of the object itself.
For reference, a singleton pattern may look like this:
class mysqli_singleton_factory {
protected static $mysqli = null;
protected function __construct() {
// assume DB connection setting have been pre-defined as constants somewhere
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
// make sure connection worked
if($mysqli->connect_error) {
throw new Exception(__METHOD__ . ' at line ' . __LINE__ . ' failed with: ' . $mysqli->connect_error);
}
self::mysqli = $mysqli;
}
public static function get_instance() {
if (false === self::mysqli instanceof mysqli) {
self::__construct();
}
return self::mysqli;
}
}
I've done this a number of times previously and I have found that it is easy to implement "singleton-like" class to serve as a database connector which then can be referenced by any object in the application.
config.php
Config.php is where the credentials are set and the database class is actually constructed.
$dbHost = 'localhost';
$dbUser = 'someUser';
$dbPass = 'somePass';
$dbSchema = 'someSchema';
Database::$db = new MySQLi($dbHost, $dbUser, $dbPass, $dbSchema);
classes.php
classes.php is where my classes are defined, which is kept separate from the rest of the code.
class Database {
public static $db;
}
class User {
...
function example()
{
$stmt = Database::$db->prepare('SELECT TRUE');
...
}
}
index.php
index.php is the entry point for the app, and is used to handle the request and exhibit the desired behavior using the supplied classes.
require_once('classes.php');
require_once('config.php');
/* Application Goes Here */
This ensures that all objects in my project use the same connection, I only have to invoke it once and I don't have to mess about with scope too much.

How do I use multiple classes in PHP

I'm very new to oop in php, so far i'm using multiple classes that I made in one php file, such as:
class Style {
//stuff
}
class User {
//other stuff
}
And many more, yet i'm having an issue on how to connect to mysql within these classes, if I use $db = new Mysqli(); how will I be able to make queries from inside classes? what if i'm trying to make my own connector class like so:
class Connection extends mysqli {
public function __construct($host, $user, $pass, $db) {
parent::__construct($host, $user, $pass, $db);
if (mysqli_connect_error()) {
die('Connect Error (' . mysqli_connect_errno() . ') '
. mysqli_connect_error());
}
}
}
How can I be able to make queries from within different classes? Or what's a better way of using oop in php correctly? with multiple classes to organize different parts of code?
Any help or tips will be appreciated, thanks. What about using PDO? does that make everything easier?
class Style {
public function __construct($conn) {
$this->conn = $conn;
//use $this->conn in the class
}
}
$db = new Mysqli();
$style = new Style($db);
I think the first example is the preferred method, however you could create a simple registry class and use that to store a $db object etc.
If possible I would probably use PDO but that doesn't solve this issue.
Since you are extending the mysqli class you will have access to the functions as you would if you instantiated that class by itself (so long as those functions aren't private). Some folks though (including myself) will instantiate the DB connection in their own custom class with a database connection, then inject that class into classes that need it.
class MyDatabase {
private $this->dbi;
public function __construct() {}
public function connectDB($host, $user, $pass, $db)) {
//You can do this in the constructor too, doesn't have to be its own function
$this->dbi = new mysqli($host, $user, $pass, $db);
}
public function getDBI() {
return $this->dbi;
}
}
You can add all the functions you want to your own class (or an extended class), you can also have any class that needs a database extend your DB class. But that isn't really preferred (each class will have a different db class/connection). The easiest is probably to import your DB connection into your class. Either through the constructor or another function;
class MyClass {
private $this->database;
public function __construct($db) {
$this->database = $db->getDBI();
}
public function query($q) {
//Of course, clean your data first, and best practices use prepared statements
$result = $this->database->query($q);
return $result;
}
}
Then make your database connection and inject it into your class.
$db = new MyDatabase();
$db->connectDB('localhost', 'username', 'password', 'mydb');
$class = new MyClass($db);
$resultSet = $class->query("SELECT * FROM MyTable"); //Obviously anything the user could add here is to not be trusted.
using PDO will give you a lot of functions and flexebilty and it has many drivers built-in.
to make what you are trying to do here is a sample :
STEP 1 :
Make a Main class that will handle your database :
class app extends PDO {
protected $database_hostname = "localhost";
protected $database_username = "root";
protected $database_password = "";
protected $database_name = "testdb";
protected $database_type = "mysqli";
public function __construct() {
try {
parent::__construct($this->database_type . ':host=' . $this->database_hostname . ';dbname=' . $this->database_name, $this->database_username, $this->database_password, array(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION));
} catch (PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
}
}
STEP 2 :
then you need to initilze a globale variable as your Database :
$db= new app() ;
STEP 3 :
include a local variable to handle database in the other classes :
class User{
public $db ;
}
STEP 4 :
in the constructor of the other classes ( user for exemple ) you need to pass the local variable by reference to the globale variable :
class User{
public $db ;
public function __construct(){
global $db;
$this->db =& $db;
}
}
STEP 5 :
then if you want to execute a request from inside a class you do it by the local variable :
$this->db->query("SELECT * FROM user");
and from the outside just by using : $db->query("SELECT * FROM user");
I hope that helped !

Could someone give a perfect example of a basic "user" object system, using PDO?

What I'd like is to see the ideal framework for a system which has a group of objects (ie User) whereby the data is contained in a database. I've been advised to have a User class and a UserMapper class and this is my understanding of how it should look:
user.class.php
/* The class for constructing any user's information
*/
class User {
protected $userId, $email, $userGroup;
protected function getEmail() {
return $this->email;
}
protected function getUserId() {
return $this->userId;
}
public function __construct($userId, $email, $userGroup) {
$this->userId = $userId;
$this->email = $email;
$this->userGroup = $userGroup;
}
}
class UserMapper {
// database connection
private $db;
public function __construct($db)
{
$this->db = $db;
}
public function findByUserId ($userId) {
$userObject = new User();
$q = $this->db->prepare("SELECT userId, email, userGroup FROM user WHERE userId = :userId");
$q->bindValue(":userId", $id);
$q->setFetchMode( PDO::FETCH_INTO, $userObject);
$q->execute();
$q->fetch(PDO::FETCH_INTO);
return $userObject;
}
}
?>
main.php
<?php
include user.class.php;
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(PDO::ATTR_PERSISTENT => true));
$getUser = new UserMapper($dbh);
$user = $getUser->findByUserId(41);
echo $user->getEmail();
?>
But this seems a bit messy in terms of the main.php side. Can I not make one PDO object and have that defined in all of my scripts? As well as a UserMapper object? Or do every time I want to get a user from the database do I need to make a NEW userMapper object, then do findByUserId (as above). Or is there a simpler way to doing this?
If I wanted to call a UserGroup object within the class User, how would I do this? (This would also need to connect to the database through PDO). To do the following seems messy:
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(PDO::ATTR_PERSISTENT => true));
$getUserGroup = new UserGroupMapper($dbh);
$userGroup = $getUserGroupMapper->findByUserId($this->userGroup);
?>
one thing that i can think of is making this class a singleton, and create the $user above the declaration of the class, so whenever you include this class you'll have that user object.
Can I not make one PDO object and have that defined in all of my
scripts? As well as a UserMapper object?
You're actually looking for a Front Controller.
That is, in order to avoid the same instantiation of the same classes, you should have prepared them. Most people usually do this in bootstrap.php, that "tweaks" all required dependencies.
But a front controller implementation also includes a dispatcher and a router. I won't go deep into this, but focus on the problem you're trying to solve instead.
Factory pattern
It basically abstracts instantiation logic. The benefits are: 1) you can delay object instantiation 2) You avoid global state, which is bad for unit-testing. The simplified version of it would look like as:
class UserFactory
{
private $pdo;
private $cache = array();
public function __construct($pdo)
{
$this->pdo = $pdo;
}
public function build($mapper)
{
if (isset($this->cache[$mapper])) {
return $this->cache[$mapper];
} else {
// Inject an instance into a mapper
$instance = new $mapper($this->pdo);
// Save the state into a cache
$this->cache[get_class($instance)] = $instance;
return $instance;
}
}
}
And finally
A very simplified version of bootstrap-er would look like as,
<?php
/* File : bootstrap.php */
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(PDO::ATTR_PERSISTENT => true));
// Include here UserFactory class
$userFactory = new UserFactory($dbh);
// Its kinda ready to be used
You would simply include in all scripts that need to access Users
<?php
/* File: main.php */
include(__DIR__ . '/bootstrap.php');
$getUser = $userFactory->build('UserMapper');
$user = $getUser->findByUserId(41);
echo $user->getEmail();
You need to use FETCH_CLASS instead and you don't need a userMapper just extend PDO then set the right fetch mode all in one class.
Don't forget to make the class definition available or use an autoloader
$this->statement->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE,"className");
FETCH_PROPS_LATE is there to get the constructor fired first in your class But you don't need a constructor in your case so just lose it. If you decide to keep it though than you should take a look here first.
Hope this helps good luck

Interacting with PHP classes/functions properly? (OOP)

I started using PHP classes and looked into OOP.
I played around by creating a Database class that looks something like this (snippet):
class Database
{
private $link;
private $result;
private $count;
function connect()
{
$this->link = mysql_connect(DB_HOST, DB_USER, DB_PW);
$return = $this->link ? 'Connected to database.' : 'Failed to connect.';
$this->open(); // I have another function in this class to select the db
echo $return;
}
function query($query)
{
$this->result = mysql_query($query);
}
function fetch()
{
return mysql_fetch_assoc($this->result);
}
function count()
{
$this->count = mysql_num_rows($this->result);
return $this->count;
}
}
Just to test, I created another class called Guestbook that looks like this:
class Guestbook
{
function fetch()
{
Database::query('SELECT * FROM guestbook LIMIT 2');
while($row = Database::fetch()){
$result_array[] = $row;
return $result_array;
}
}
Now I tested calling the functions:
$db = new Database();
$db->connect();
$db->query('SELECT * FROM test');
while($row = $db->fetch()) {
echo $row['id'].'<br />';
}
echo $db->count();
$db->close();
This works as expected. So I went on with the Guestbook class:
$db->connect();
$guestbook = new Guestbook();
$results = $guestbook->fetch();
foreach($results as $gb) {
echo $gb['id'];
}
echo $db->count(); // HERE'S MY PROBLEM !
$db->close();
Everything works as I wanted, but the second time I call $db->count() it echos the previous count and not 2 (as I set LIMIT 2 in the Guestbook fetch function).
How do I interact with these classes properly, so I can use something like $db->count() globally?
Thanks in advance for any hints or solutions!
First off, there is no reason to wrap mysql_* implementations in OOP. IF you are going to do OOP then just use Mysqli or PDO which have OOP classes you can extend.
Secondly you want to hold an instance of the Database in the GuestBook class, not make it an extension of the Database class itself.
It is hard to give you a definitive advice on how you could wrap your database accessor with OOP and still access the count() globally.
Clearly your code is wrong.
by using the notation
Database::query
you are referring to some kind of static methods on the Database class which does not seem to be the intent here. It looks like your code does not crash because of some backward compatibility with PHP4.
you could rewrite Guestbook along this way :
class Guestbook
{
private $db;
function __construct(&$db) {
$this->db = $db;
}
function fetch($option)
{
$this->db->query('SELECT * FROM guestbook LIMIT 2');
while($row = $this->db->fetch()){
$result_array[] = $row;
return $result_array;
}
}
and then
$db = new Database();
$db->connect();
$guestbook = new Guestbook($db);
$results = $guestbook->fetch();
echo $db->count();
This technique uses a pattern known as "Dependency Injection"
Why would you use count from the db class when you have the results from the guestbook->fetch() method?
This does exactly the same trick:
echo count( $resutls );
see the $db is a object of the class Database
never access the function OR property of the Guestbook
you can get this directly with count( $resutls )
OR may have to go with the inheritance concept
Thanks
You mixing static with instantiated versions of your class. If you want to be able to create multiple instances of a class, you should have a __construct function. While it's not required, it's best practice to have one.
You are creating a new instance and assigning it to the $db variable ($db = new Database();). But then in your GuestBook class you are referencing the database class statically (Database::). That syntax references the "base" class which is the same across all instances. What you want to do is reference the instance of the database class you created. Typically you would pass the database instance to use into the GuestBook class in the constructor, store that in a class variable, then reference it using $this.
class Guestbook
private $db = null;
{
function __construct($db) {
$this->db = $db;
}
function fetch($option) {
$this->db->query('SELECT ...');
...
}
}
$db = new Database();
$guestbook = new Guestbook($db);

Categories