I'm just getting started with OOP PHP and all of the information out there is about a car that is red or blue...it's hard to get my head around the database connection only object as such.
I have a haunting suspicion that my __construct() shouldn't have the connection string in it and instead be it's own method inside the class.. but it works so....
Is it incorrect to define my connection class like below.. If it is wrong - how should it look?
class dbConnect {
// Declare connection info for PDO
private $dbType = 'mysql';
private $dbHost = 'localhost';
private $dbUser = 'user';
private $dbPass = 'password';
private $dbName = 'db';
// Declare connection variable for object
private $dbConn;
// Construct object
private function __construct() {
// Create Database connection and assign it to object as dbConn
$this -> dbConn = new PDO( $this -> dbType . ':' . 'host=' . $this -> dbHost . ';' . 'dbname=' . $this -> dbName , $this -> dbUser , $this -> dbPass );
}
}
I don't think what I think you are doing is very useful. It looks like you are going to have a database class. I just cannot see the advantage of doing it like that because PDO already is a class, so there is no need to extend it unless you have a very good reason to do so.
A much better option imho would be the initialize the PDO instance at bootstrap phase and inject the connection in the classes that need it;
$dbConnection = new PDO('mysql:host=localhost;dbname=db', 'user', 'password');
$someInstance = new ClassThatNeedsDatabase($dbConnection);
$someInstance->doSomething();
class ClassThatNeedsDatabase
{
private $dbConnection ;
public function __construct(PDO $dbConnection)
{
$this->dbCOnnection = $dbConnection;
}
public function doSomething()
{
$stmt = $this->dbConnection->prepare('UPDATE....');
// etc
}
}
On a generic note you may want to avoid using the new keyword inside other classes, because they introduce tight coupling. Which will hurt maintainability (it's hard to tell the class is used by looking at the class signature), testablity (you cannot easily swap the class) etc. If you really need to build new instances inside other classes (which in this specific case is really not needed imo as stated above) you may want to implement the factory pattern:
class Foo
{
public function doSomething()
{
}
}
class FooFactory
{
public function build()
{
return new Foo();
}
}
class Bar
{
private $fooFactory;
public function __construct(FooFactory $fooFactory)
{
$this->fooFactory = $fooFactory;
}
public function soSomethingWhichNeedsToBuildAnInstance()
{
$foo = $this->fooFactory->build();
}
}
This also prevent tight coupling of code.
The above naming sucks, but it is just to illustrate the point. :-)
Yes, you should be extending the existing PDO object.
How about this as your base:
define('DB_USER', 'username');
define('DB_PASS', 'password');
define('DB_DSN', 'dsn');
class dbConnect extends PDO {
public function __construct($user = DB_USER, $pass = DB_PASS, $dsn = DB_DSN) {
parent::__construct($dsn, $user, $pass, $options);
}
}
Related
I recently started to update my Api code on an Apache server by using more inheritance. As I was a bit careful to use it in the past due to inexperience.
The thing is I noticed that for each Model instance a new database connection is set. So I created an alternative connection on a Static variable to pass to each Model. My question is will multiple database connection on each new Model instance cause problems if I create a connection such in my example below using __construct?
class ApiEnterprises {
protected $db;
private $table;
public function __construct(){
$this->messager = new Messager();
$this->table = 'enterprisetable';
$this->db = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
if ($this->db === NULL || !$this->db) {
// set response code
echo $this->messager->databaseFailed();
}
}
}
class ApiUsers {
protected $db;
private $table;
public function __construct(){
$this->messager = new Messager();
$this->table = 'usertable';
$this->db = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
if ($this->db === NULL || !$this->db) {
// set response code
$this->messager->databaseFailed();
}
}
}
Alternatively will a Static variable be safer? As I can remove it in the Controller __destruct method.
class Database {
static $connect;
protected static function conn() {
self::$connect = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
return self::$connect;
}
}
class ApiUserController extends Database {
private $user_model;
private $enterprise_model;
public $connection;
public function __construct($data){
$this->connection = parent::conn();
//pass connection to models
$this->user_model = new ApiUsers($this->connection);
$this->enterprise_model = new ApiEnterprises($this->connection);
}
}
What you need is IoC container, but before you get there you need to design your models in a such a way that they accept the database instance as a parameter in the constructor. This is called dependency injection. All dependant instances are injected into the new object at the time of instantiation.
Since your Database is useless I would not recommend to use it, but you should write some database abstraction library or use one that is already available on the web. e.g. EasyDB
Here is an example of a single dependency injection:
class ApiEnterprises {
protected $db;
protected $messager;
private $table = 'enterprisetable';
public function __construct(mysqli $db, Messager $messager) {
$this->db = $db;
$this->messager = $messager;
}
}
// mysqli connection somewhere at the start of your application
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
$mysqli->set_charset('utf8mb4'); // always set the charset
// instantiate the model and pass mysqli as an argument
$enterprise = new ApiEnterprises($mysqli, $messager);
I'm trying to learn how to properly code PHP OOP.
This is where I'm running into issues.
I created several classes that extend main Application class and I want to make things work properly.
I have main file that's index.php that looks like this:
include_once('classes/Application.php');
include_once('classes/Configuration.php');
include_once('classes/Database.php');
$app = new Application;
$config = new Configuration;
$db = new Database;
var_dump($app->db_connected);
var_dump($db->db_connected);
$db->connect($config->dbhost, $config->dbuser, $config->dbpass, $config->dbname);
var_dump($app->db_connected);
var_dump($db->db_connected);
The output is:
1. bool(false)
2. bool(false)
3. bool(false)
4. bool(true)
My main application file looks like this:
class Application {
public $db_connected = false;
}
And my Database class looks like this:
class Database extends Application {
function connect($dbhost, $dbuser, $dbpass, $dbname) {
if(!$this->db_connected) {
mysql_connect($dbhost, $dbuser, $dbpass) or die(mysql_error());
mysql_select_db($dbname) or die(mysql_error());
$this->db_connected = true;
}
}
}
So the question is, why would line #3 of the output of index.php display false? The db_connected property has been overridden in Database class and set to TRUE, but it still returns false.
Although when accessed directly from Database class instance it shows TRUE correctly. What's the deal here?
Also when does the class EXTEND command occurs? Whenever parent class' instance is created or I have to manually create instance of the child class?
It seems you are reaching for the concept of of a static variable all instances of a class share the same static variable so using the new twice will not be an issue.
You can see the code on ideaone.
// your code goes here
class Application {
static $db_connected = false;
}
class Database extends Application {
function connect() {
if(!static::$db_connected) {
static::$db_connected = true;
}
}
}
$app = new Application;
$db = new Database;
var_dump(Application::$db_connected);
var_dump(Database::$db_connected);
$db->connect();
var_dump(Application::$db_connected);
var_dump(Database::$db_connected);
Your comment make me think you are looking for a better pattern all together. I would like to throw out some key principles namely OCP and LSP SOLID.
In this case you would avoid having Application being an instance of Database but instead use dependency injection. Here is the refactored code.
class Database {
private $db_connect = false;
public function connect () {
if(!$this->db_connect) { /* do connection */ }
}
}
class Application {
private $db;
public function setDatabse(Database $db) {
$this->db = $db;
}
public function getDatabase() {
return $this->db;
}
}
$db = new Database;
$app = new Application;
$app->setDatabase($db);
$app->getDatabase()->connect();
This line is your hint
Although when accessed directly from Database class instance it shows TRUE correctly. What's the deal here?
You have 2 instances. Above you are checking $db instance which you connected with, and then you print from $app which was never connected. They are separate entities, one is connected one is not.
Extend occurs as soon as the file is loaded, read by the php interpreter, this happens regardless of ever using the class.
Extend is called from the child and inherits everything form the class it extends. So if you call a child method in the parent, well you are doing it backwards. It goes one way, Prent -> Child.
I would use Dependance injection for the database, then you can reuse it's code.
Like this:
//parent class
class Application {
//holds a reference to the Database class
protected static $db_conn = false;
public function __construct($db){
self::$db_conn = $db;
}
}
//child class of Application
class Application2 extends Application {
public function getSomething($id){
return self::$db_conn->getbyId($id) ;
}
}
//separate utility class
class Database{
static $conn;
public function __construct( $dbhost, $dbname, $dbuser, $dbpass, $dbname) {
static::$conn = mysqli_connect($dbhost, $dbuser,$dbpass,$dbname);
}
public function getbyId( $id ){
..code to get stuff by id using $conn - previous connection ...
return $result;
}
}
$db = new Database("myhost", "myuser", "mypassw", "mybd");
$app = new Application2( $db );
$app->getSomething(1);
//create another app with the same database connection, this is the value of injecting it.
$second_app = new Application2( $db );
See you can reuse database over and over, you can replace it without changing the code in Application as long as the calls for the functions of the Database class don't change. Each thing is responsible for it's own business.
This is called separation of concerns.
Inheritance is good, when it's needed. You might have an basic application for free users of you're services and then extend that with a premium application for paid members. Sense they paid they get all the free functionality, but also the premium stuff to.
In my example above the database is something they both need, as well as other things will probably use this. Such as a login system may need a database connection, payment system might, a shopping cart might. These are all separate objects, they don't / nor should they extend off of one Master Class, that's a bad idea. Keep them separate.
STATIC
I seen mention of the :: static object operator. My example is a bit flawed when using the static property protected static $db_conn = false;
$app = new Application2( $db );
$second_app = new Application2( $db ); //assigning db 2x is not needed.
The reason for :: and the -> normal way. Is that static :: is shared across all instance of a class, and -> is just this instance of the class. I had assigned the $db class to a static variable 2 times a better way would have been like this.
//parent class
class Application {
protected static $db_conn = false;
//separate method then construct.
public function connect($db){
self::$db_conn = $db;
}
}
//we'll keep the rest of the code the same here.
$db = new Database();
$app = new Application2();
$app->connect( $db );
$second_app = new Application2();
$second_app->getSomething(1);
Now in this example $second_app never ran it's connect method. But because the first $app did and because the static for the database variable protected static $db_conn. Now all classes that have extended the Application class have a database connection. This is what static does. It's value is shared across all instance of the class. So when you see :: think all class instance and when you see -> think only this class instance. It's actually one thing I love about php, makes it so much easier to keep track of then in some other languages.
Not to confuse you but the other use of the :: is not actually needing an instance at all. Assume you have a Config class like this.
class Config{
static $db = 'hello';
static $items = array('one' => 'item 1' );
private __construct(){} // no construction allowed
static function getItem( $which ){
return self::$items[$which];
}
}
Now without ever creating an instance of the class by calling new Config() , you can simply.
echo Config::$db;
// prints hello
echo Config::getItem('one');
// prints 'item 1'
This is quite use full for config type classes. Where they are an empty shell just used to store data in and you don't need an object for them, essentially a way to keep things organized. So tying this in to the previous examples
$db = new Database(Config::$myhost, Config::$myuser, Config::$mypassw, Config::$mybd);
In your case best OOP practice is to use Mediator pattern. Concrete Mediator will be Application class:
class ApplicationBase {
private $db;
private $cfg;
public function setDb(Database $db) {
$this->db = $db; return $this;
}
public function setConfig(Config $cfg) {
$this->cfg = $cfg; return $this;
}
}
class Application extends ApplicationBase {
public function getDsn() {
return $this->cfg->getDsn();
}
public function getDbUser() {
return $this->cfg->getDbUser();
}
public function getDbPass() {
return $this->cfg->getDbPass();
}
public function getConnection() {
return $this->db->getConnection();
}
}
class AppComponent {
protected $app;
public function __construct(Application $app) {
$this->app = $app;
}
}
class Config extends AppComponent {
private $dsn;
private $dbuser;
private $dbpass;
// ... getters and setters
}
class Database extends AppComponent {
private $connection;
private function connect() {
$this->connection = new PDO(
$this->app->getDsn(),
$this->app->getUser(),
$this->app->getPass()
);
}
public function getConnection() {
if (null === $this->connection) $this->connect();
return $this->connection;
}
}
class Model extends AppComponent {
protected $table;
// Model stuff here
}
class Content extends Model {
public function getNews() {
$db = $this->app->getConnection();
return $db->query("SELECT * FROM $this->table LIMIT 5")->fetchAll();
}
}
Such architecture will be enough for simple, clean-looking applications and classes will be ready for easy unit-testing:
$app = new Application();
$cfg = new Config($app);
$db = new Database($app);
$app->setDb($db)->setConfig($cfg);
$content = new Content($app);
$news = $content->getNews();
I am building an API in PHP and I have a question. I'm using classes, and some of these classes need to access my database. However, I don't want to define variables for the database in every single class in order to open it, or have to send my mysqli object as a parameter of every single class constructor.
What would be the best way to go about this? Do I define a global variable of some kind?
A classic solution would be as follows
Create an instance of dbatabase handler class, either raw mysqli (worse) or better abstraction class (way better)
In the constructor of your application class take this db class instance as a parameter and assign it to a local variable
Use this variable with your class.
A quick example:
class Foo()
{
protected $db;
function __construct($db);
{
$this->db = $db;
}
function getBar($id)
{
return $this->db->getOne("SELECT * FROM bar WHERE id=?i", $id);
}
}
$db = new safeMysql();
$foo = new Foo($db);
$bar = $foo->getBar($_GET['id']);
How about using a static classes?
class mysqli_wrapper {
private static $db = null;
public static function open() {
GLOBAL $opts; // this can be global or setup in other ways
if (!self::$db) {
self::close();
self::$db = null;
}
self::$db = #mysqli_connect('p:'.$opts['hn'], $opts['un'], $opts['pw'], $opts['db']);
return self::$db;
}
public static function query($qry) {
return mysqli_query ( self::$db, $qry );
}
public static function affected_rows() { return #mysqli_affected_rows(self::$db); }
public static function error() { return #mysqli_error(self::$db); }
public static function close() { #mysqli_close(self::$db); }
} // end mysqli_wrapper
mysqli_wrapper::open(); // Here's how to call it
In a system I maintain my app needs to access its own MySQL db, as well as remote Oracle and SQL Server databases, and I use a trait for it. Here's a simplification of my code, just using MySQL:
dbaccess.php
trait DatabaseAccess {
protected $db;
private $host = 'host', $dbName = 'db', $username = 'username', $password = 'pword';
public function connectToMysql() {
$this->db= new mysqli(......);
}
}
then in myclass.php
require 'dbaccess.php';
class MyClass {
use DatabaseAccess;
//class code.....
}
All elements of DatabaseAccess will be available as if you hand-typed them in MyClass.
Note: if you're using PHP < 5.4, then this solution won't be possible.
<?
class DbConn {
const DB_HOST = 'localhost';
const DB_USER = 'root';
const DB_PASS = 'pw';
const DB_NAME = 'db';
static private $instance = NULL;
private $_db;
static function getInstance()
{
if (self::$instance == NULL)
{
self::$instance = new DbConn();
if(mysqli_connect_errno()) {
throw new Exception("Database connection failed: ".mysqli_connect_error());
}
}
return self::$instance;
}
private function __construct()
{
$this->_db = new mysqli(self::DB_HOST, self::DB_USER, self::DB_PASS, self::DB_NAME) or die('Couldnt connect');
}
private function __clone() {}
}
DbConn::getInstance()->query();
?>
Im just learning and know I've got to singleton pattern, I tried to make my own DBConnect class using singleton, but when I'm trying executing it, it gives an error when calling DbConn::getInstance()->query(); saying that Call to undefined method DbConn::query() What am I doing wrong?
You are calling query() on a object of class DbConn - which hasn't got any query() method.
The implementation of the singleton pattern is good in your example. But you can't call the mysqli functions on the DbConn object directly, you have to wrap them or provide a getter for the private _db property, and call query() on that object.
Try adding the following after the __construct function
public function query($sql)
{
return $this->_db->query($sql);
}
then try
DbConn::getInstance()->query("SELECT * FROM Table"); //Replace your sql
You have to
extend the mysqli class to use methods from that class
or write a query method yourself.
or make the $db public and use DbConn::getInstance()->$db->query();
Why make it a Singleton? mysqli does connection pooling, and making it a singleton add extra complexity without any benefits.
I'm pretty new at this, so correct me if I'm wrong.
Can't you simply extend the mysqli class and change the contructor a little?
class DbConn {
becomes
class DbConn extends mysqli {
and:
$this->_db = new mysqli(
self::DB_HOST,
self::DB_USER,
self::DB_PASS,
self::DB_NAME) or die('Couldnt connect');
becomes
parent::__construct(
self::DB_HOST,
self::DB_USER,
self::DB_PASS,
self::DB_NAME) or die('Couldnt connect');
Now, DbConn::getInstance()->query(); should work
I have db class which looks like that
class db {
protected $db;
public function __construct() {
$this->connect();
}
protected function connect() {
$this->db = new MySQLi(db_host, db_user, db_pass, db_name) or die($this->db->error);
$this->db->set_charset('utf8');
}
}
Every class inside my PHP app extends this db class
Like
class registration extends db {
var $validation;
function __construct() {
parent::__construct();
$this->validation = new validation();
...
And validation looks like that
class validation extends db {
var $ajax, $common;
function __construct() {
parent::__construct();
...
Getting error message "Too many connections". I feel that, this is not right approach: I'm every time reconnecting to db. So what's right way in your opinion? Is that possible to define('db', ...) 1 time and use everywhere inside app?
registration and validation are classes the use db but are not a sub-class of it.
Your code should look like:
$db = new DB();
$db->connect();
$registration = new Registration($db);
class Registration {
private $db;
public function __construct(DB $db) {
$this->db = $db;
...
You pass a reference to an instance of $db to all classes that require it.
The reason you're opening too many connections is probably because currently each class makes it's own connection to your database, and that is not what you want to do, or need to do.
You want to use composition here instead. Also might consider investigating Singleton pattern.
To elaborate, using composition, each class in your library will have an instance of the db class rather than be an instance of the db class.
Singleton will make the db class enforce only one instance of the class is ever created which is useful for shared resources like database connections. Have a look at this link for further reading on the topic.
http://php.net/manual/en/language.oop5.patterns.php
EDIT: Adding some code
Turning the db class into a Singleton
<?php
class db
{
static private $_oInstance = null;
protected $db;
private function __construct()
{
$this->connect();
}
static public function getInstance()
{
if(self::$_oInstance === null)
self::$_oInstance = new db();
return self::$_oInstance();
}
protected function connect()
{
$this->db = new MySQLi(db_host, db_user, db_pass, db_name) or die($this->db->error);
$this->db->set_charset('utf8');
}
}
Revising the rest of your classes to compose the db instance rather than extend the db class
class registration
{
private $_oDb;
public $validation;
function __construct()
{
parent::__construct();
$this->_oDb = db::getInstance();
$this->validation = new validation();
}
// ...
}