I want to be able to call a function which connects to my database, without creating multiple objects, including or having to write the same construct in each class. I Basically want to call a construct function in other classes.
like this below.
class Database{
public function __construct(){
$this->conn = new mysqli("host", "user", "password", "db");
// Check connection
if (!$this->conn) {
die("Connection failed: ".mysqli_connect_error());
}
}
}
class User{
// call Database->__construct();
}
class OtherClass{
// call Database->__construct();
}
ofcourse this isn't the way to go but i don't really know what would be a viable way.
I thought maybe this would work. but it doesn't
Making a new Database object in class to construct a connection
class Database{
public function __construct(){
$this->conn = new mysqli("host", "user", "password", "db");
// Check connection
if (!$this->conn) {
die("Connection failed: ".mysqli_connect_error());
}
}
}
class User{
$conn = new Database();
}
Dependecy injection or constructor injection seems like a nice solution. But i don't know if it's made for something like this and how to apply it.
class Database{
public function connection(){
$this->conn = new mysqli("host", "user", "password", "db");
// Check connection
if (!$this->conn) {
die("Connection failed: ".mysqli_connect_error());
}
}
}
class User{
private $db;
public function __construct(Database $conn){
$this->db = $conn;
}
}
Here what i am doing for connection
class DBConnection{
protected static $db;
private function __construct() {
try {
self::$db = new PDO( 'mysql:host=localhost;dbname=db_abc', 'root', '' );
//self::$db = new PDO( 'mysql:host=localhost;dbname=db_phonebook', 'root', 'QAZwsx2016!' );
self::$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch (PDOException $e) {
echo "Connection Error: " . $e->getMessage();
}
}
public static function getInstance() {
if (!self::$db) {
new DBConnection();
}
return self::$db;
}
public function __destruct() {
$db=NULL;
}
}
And here how I am using to another model class
class User{
private $db;
public function __construct() {
$this->db = DBConnection::getInstance();
}
public function getUsers(){
//....................
//....................
//$sql =
$query = $this->db->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$query->execute();
$customers = $query->fetchAll();
//return .........
}
If you want pure OOP way, please look into the factory methods, and look facade design pattern, Its all about how you gonna achieve some this.
This one is my way (simple way) but to architecture better see the different design patterns.
One useful article here link
and
Design Patterns with PHP-The right way link
Related
I can not make the PDO connection outside the class. Browser gives 500 error. I want to write PDO codes in out class. I am doing global change, but it is not.
try {
$pas = new PDO('mysql:host=localhost; dbname=tets', 'root', '123');
$pas->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$pas->exec("SET CHARACTER SET utf8"); // return all sql requests as UTF-8
} catch (Exception $e) {
echo $e->getMessage();
}
/**
User Avatar Check
**/
class Usercheck
{
public $sql , $paso;
public function __construct()
{
global $pas;
$this->paso =& $pas;
}
public function smf_members($whatid)
{
$this->sql = $this->paso->query("SELECT * FROM smf_members WHERE id_member = $whatid");
}
public function fetchcheck(){
if ($this->sql) {
return $this->sql->fetch(PDO::FETCH_BOTH);
}
}
}
$memberuser = new Usercheck();
$memberuser->smf_members('1');
It is not a good practice to use $global. There are many solutions to achieve what you want to do, and here is my approach.
1) Create a Connection Class to handle the PDO connectivity.
use PDO;
/**
* PDO Connection Classes
* Used by Database wrapper class to ensure that there is only one connection
*/
class Connection
{
private $dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME. ';charset=' . DB_CHARSET;
private $conn;
private $error;
public function __construct()
{
try
{
$this->conn = new PDO($this->dsn, DB_USER, DB_PASSWORD);
}
catch(PDOException $e)
{
$this->error = $e->getMessage();
}
}
public function getConnection()
{
return $this->conn;
}
}
2) Establish the PDO connection via your wrapper class __construct(), the __construct() also ensure that there is only one PDO connection is instantiated.
use PDO;
class UserCheck
{
private $conn;
private $db;
public function __construct()
{
if (!$this->db) {
$conn = new Connection();
$this->db = $conn->getConnection();
}
}
}
I'm highly recommend that you read this PDO tutorial on how to use PDO and many best practice tips.
This question already has an answer here:
How to use PDO connection in other classes?
(1 answer)
Closed 3 months ago.
I am using class to do all the database related stuff. Inside a config file contains a class that has a 'Connect' function to establish connection to the database. I have created a connection file which contains information to connect to database. Now for to retrieve the data from the specific table I called the same class and 'Query' function. But in Query function, I need $conn of Connect function. I am little bit weak in object oriented. Can anybody guide me how can I make this work. I have included my files config.php, connection.php and index.php files below.
config.php page
<?php
class DBConnection{
public function __construct(){
}
public function Connect(){
try {
$conn = new PDO('mysql:host='.$this->server_name.';dbname='.$this->db,$this->user, $this->pass);
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (Exception $e) {
echo 'ERROR: ' . $e->getMessage();
}
}
static public function Query($sql){
return $conn->prepare($sql);
}
}
connection.php page
<?php
require_once('config');
$default=array(
'DB_SERVER'=>'Localhost',
'DB_USER'=>'root',
'DB_PASS'=>'',
'DB_NAME'=>'hqe'
);
$m_db = new DBConnection();
$m_db->server_name=$default['DB_SERVER'];
$m_db->user=$default['DB_USER'];
$m_db->pass=$default['DB_PASS'];
$m_db->db=$default['DB_NAME'];
$m_db->Connect();
index.php page
<?php
include("connection.php");
$usr = DBConnection::Query("Select id, first_name, last_name from tbl_user");
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::.
i have a question about php.
I was wondering how can i add this code to a new object so i can later just add it to existing code and use it.
<?php
$mysqli = new mysqli("localhost", "root", "", "kooliasi");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
printf ("System status: %s\n", $mysqli->stat());
$mysqli->close();
?>
Thanks !
Make a class for the connection:
class Database{
private static $link = null ;
public static function getConnection ( ) {
if (self :: $link) {
return self :: $link;
}
$dsn = "mysql:dbname=social_network;host=localhost";
$user = "user";
$password = "pass";
self :: $link = new PDO($dsn, $user, $password); //OR mysqli - matter of preference
return self :: $link;
}
}
Then you can get the connection like this:
Database::getConnection();
This is a Singleton Pattern. You could use this if you like, but it is hard to scale - However, I think it will be fine for your needs. It takes a lot of load off your database.
There is a php.ini setting for prepending a file to every script -> http://www.php.net/manual/en/ini.core.php#ini.auto-prepend-file
You can create a db class where you can keep the connection handle. Add functions to the class as needed. For example
class db{
private $link;
public function __construct(){
$this->link = mysqli_connect(DB_SERVER, DB_USER, DB_PASS,DB_NAME);
}
public function __destruct() {
mysqli_close($this->link);
}
public function query($q){
... add code here for the query
}
}
Then to use the class you call:
$db = new db();
$db->query($parameters_you_want_to_pass);
My first real foray into using PHP OOP and PDO extensively. I have finally gotten the script to work, but as you notice in order to do it I had to move the PDO connect into the login function - originally it was just in the __construct(). I do not want to have to open a new PDO connect and this is sloppy. How can I maintain the same connection throughout the whole class?
<?php
class user{
public $id;
public $name;
public $email;
private $password;
public function __construct() {
$DBH = new PDO("mysql:host=HOST;dbname=DB", "USER", "PASS");
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public function login($email,$password,$type){
$DBH = new PDO("mysql:host=HOST;dbname=DB", "USER", "PASS");
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$password_hash = sha1($password);
try{
if ($type != "actives") {
throw new Exception("Type Handling Error");
}
$STH = $DBH->query("SELECT id, email, password FROM $type WHERE email='$email' AND password='$password_hash'");
$STH->setFetchMode(PDO::FETCH_ASSOC);
$row_count = $STH->rowCount();
$row = $STH->fetch();
if($row_count == 1){
session_start();
session_regenerate_id();
$_SESSION['id'] == $row[id];
return true;
}
else{
return false;
}
}
catch (Exception $e) {
echo $e->getMessage();
}
}
public function loggout(){
session_destroy();
setcookie(session_name(), session_id(), 1, '/');
}
Make the database handle a private member within the class:
class user
{
public $id;
public $name;
public $email;
private $password;
private $dbh;
public function __construct(PDO $dbh)
{
$this->dbh = $dbh;
}
public function login($email, $password, $type)
{
$dbh = $this->dbh;
...
}
Usage:
$pdo = new PDO("mysql:host=HOST;dbname=DB", "USER", "PASS");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$user = new User($pdo);
Sooner or later, you may need the PDO connection object somewhere else in your code(outside your user object). Therefore,
I would suggest to use one class which will provide static method as below to get the PDO connection object everywhere you want.
class Database{
private static $datasource='mysql:host=HOST dbname=DB';
private static $username='USER';
private static $password='PASS';
private static $db;
//make the constructor private and empty so that no code will create an object of this class.
private function __construct(){}
//the main public function which will return the required PDO object
public static function getDB(){
if(!isset(self::$db)){
try{
self::$db=new PDO(self::$datasoure,self::$username,self::$password);
}
catch(PDOExceptin $e)
{
$error=$e->getMessage(); //variable $error can be used in the database_error.php file
//display database error file.
include('database_error.php');
exit();
}
}
return self::$db;
}
}
Then you can use the static method like below any time you want PDO connection
$conn=Database::getDB();
Use ceejayoz' proposal or add a global function which is responsible for establishing the database connection. The function is written as to connect to the database at most 1 time per HTTP request:
function getPDOConnection() {
// Thanks to the static-specifier, this variable will be initialized only once.
static $conn = new PDO("mysql:host=HOST;dbname=DB", "USER", "PASS");
return $conn;
}
This enables you to maintain the same connection in your whole application (but of course you don't have to use the function everywhere). Basically, this is a very simple application of the Singleton pattern. See the documentation of the static specifier/keyword and try to get familiar with the Singleton pattern.
Add your database connection as a parameter in the constructor, So you when you create a new instance from the user class it automatically runs across the instantiated object
The variable $DBH needs to be a member variable of your class.
Below private $password;, add private $DBH; and you're good to go with deleting the new-connection code from your login function.
I want to be able to make classes which extend the MySQLi class to perform all its SQL queries.
$mysql = new mysqli('localhost', 'root', 'password', 'database') or die('error connecting to the database');
I dont know how to do this without globalising the $mysql object to use in my other methods or classes.
class Blog {
public function comment() {
global $mysql;
//rest here
}
}
Any help would be appreciated.
Thanks.
I was working on something similar. I'm happy about this singleton class that encapsulates the database login.
<?php
class db extends mysqli
{
protected static $instance;
protected static $options = array();
private function __construct() {
$o = self::$options;
// turn of error reporting
mysqli_report(MYSQLI_REPORT_OFF);
// connect to database
#parent::__construct(isset($o['host']) ? $o['host'] : 'localhost',
isset($o['user']) ? $o['user'] : 'root',
isset($o['pass']) ? $o['pass'] : '',
isset($o['dbname']) ? $o['dbname'] : 'world',
isset($o['port']) ? $o['port'] : 3306,
isset($o['sock']) ? $o['sock'] : false );
// check if a connection established
if( mysqli_connect_errno() ) {
throw new exception(mysqli_connect_error(), mysqli_connect_errno());
}
}
public static function getInstance() {
if( !self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
public static function setOptions( array $opt ) {
self::$options = array_merge(self::$options, $opt);
}
public function query($query) {
if( !$this->real_query($query) ) {
throw new exception( $this->error, $this->errno );
}
$result = new mysqli_result($this);
return $result;
}
public function prepare($query) {
$stmt = new mysqli_stmt($this, $query);
return $stmt;
}
}
To use you can have something like this:
<?php
require "db.class.php";
$sql = db::getInstance();
$result = $sql->query("select * from city");
/* Fetch the results of the query */
while( $row = $result->fetch_assoc() ){
printf("%s (%s)\n", $row['Name'], $row['Population']);
}
?>
My suggestion is to create a Singleton DataAccess class, instantiate that class in a global config file and call it in your Blog class like $query = DataAccess::query("SELECT * FROM blog WHERE id = ".$id).
Look into the Singleton pattern, it's a pretty easy to understand designpattern. Perfect for this situation.
Your DataAccess class can have several methods like query, fetchAssoc, numRows, checkUniqueValue, transactionStart, transactionCommit, transactionRollback etc etc. Those function could also be setup as an Interface which gets implemented by the DataAccess class. That way you can easily extend your DataAccess class for multiple database management systems.
The above pretty much describes my DataAccess model.
You can use PHP's extends keyword just for any other class:
class MyCustomSql extends mysqli {
public function __construct($host, $user, $password, $database) {
parent::__construct($host, $user, $password, $database);
}
public function someOtherMethod() {
}
}
$sql = new MyCustomSql('localhost', 'root', 'password', 'database') or die('Cannot connect!');
or better use object aggregation instead of inheritance:
class MySqlManipulator {
private $db;
public function __construct($host, $user, $password, $database) {
$this->db = new mysqli($host, $user, $password, $database);
}
public function someOtherMethod() {
return $this->db->query("SELECT * FROM blah_blah");
}
}
$mysqlmanipulator = new MySqlManipulator('localhost', 'root', 'password', 'database') or die('Cannot connect!');
My standard method is to make a singleton class that acts as the database accessor, and a base class that everything requiring such access inherits from.
So:
class Base {
protected $db;
function __construct(){
$this->db= MyDBSingleton::get_link();
//any other "global" vars you might want
}
}
class myClass extends Base {
function __construct($var) {
parent::__construct();// runs Base constructor
$this->init($var);
}
function init($id) {
$id=(int) $id;
$this->db->query("SELECT * FROM mytable WHERE id=$id");
//etc.
}
}
Have a look at PDO, which throw exceptions for you to catch if a query fails. It's widely used and tested so you shouldn't have a problem finding existing solutions whilst using it.
To inject it into your blog class:
class Blog {
private $_db;
public function __construct(PDO $db) {
$this->_db = $db
}
public function comment() {
return $this->_db->query(/*something*/);
}
}