I'm new to OOP. Originally I was defining variables and assigning values to them within the class and outside of the constructor, but after an OOP lesson in Java today, I was told this is bad style and should be avoided.
Here is my original PHP database connection class that I mocked-up:
class DatabaseConnection {
private $dbHost = "localhost";
private $dbUser = "root";
private $dbPass = "";
private $dbName = "test";
function __construct() {
$connection = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass)
or die("Could not connect to the database:<br />" . mysql_error());
mysql_select_db($this->dbName, $connection)
or die("Database error:<br />" . mysql_error());
}
}
Is the above considered okay? Or is the following a better way?
class DatabaseConnection {
private $dbHost;
private $dbUser;
private $dbPass;
private $dbName;
function __construct() {
$this->dbHost = "localhost";
$this->dbUser = "root";
$this->dbPass = "";
$this->dbName = "test";
$connection = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass)
or die("Could not connect to the database:<br />" . mysql_error());
mysql_select_db($this->dbName, $connection)
or die("Database error:<br />" . mysql_error());
}
}
What should I be focusing on to make sure I am understanding OOP correctly?
First of all: this is pointless.
You are creating an object wrapper for the 10+ year old mysql_* function. This php extension is no longer maintained and the process of deprecation has already begun. You should not use this API for any new projects in 2012.
Instead you should learn how to use PDO or MySQLi and work with prepared statements.
That said .. lets take a look at your code:
Constructor should receive all the parameters required for creating new instance, parameters should not be hard-coded in the class definition. What if you need to work with two databases at the same time ?
When connection is created, it should be stored in object's scope variable. Something along the lines of $this->connection = mysql_conn.... Instead you store it in local variable, which you "loose" right after constructor is done.
You should not use private variables for everything. They are not visible to classes which would extend your original class. Unless it is intentional, you should choose protected for this.
The or die('..') bit most go. Do not stop the whole application if connection fails. Instead you should throw an exception, which then can be handled outside of the constructor.
Well, it's not going to run quite yet. You need to change your variables so that they match your connection params:
$dbHost = "localhost";
Should be
$this->dbHost = 'localhost';
I normally don't put my login params inside of the class at all. I would pass them into the constructor when the object is created. Use an outside config file so you can actually use this class on more than one build. :)
Update::
Okay, so here are a few little OOP configuration gold-nuggets that help you build a dynamic Database class.
Check out http://redbeanphp.com/ It will allow you to do a psuedo ORM style of data modelling. Super easy to install, and ridiculously easy to get your database up and running. http://redbeanphp.com/manual/installing
Create a configuration file that contains things like constants, template setups, common functions, and an AUTOLOADER Configuration files are key when working in version controlled environments. :)
Build your Database class as an abstract class http://php.net/manual/en/language.oop5.abstract.php
abstract class Database
{
public function update()
{
}
public function deactivate()
{
}
public function destroy()
{
}
//etc.
}
class MyAppObject extends Database
{
}
Put all of your class files into a library folder, and then put your configuration file into that library. Now, to make your life easier you can use an autoloader function to bring your classes to life whenever you need them, without having to include any specific class. See below:
//note: this is never explicitly instantiated
//note: name your files like this: MyAppObject.class.php
function my_fancypants_autoloader( $my_class_name )
{
if( preg_match( "%^_(Model_)%", $my_class_name ) ) return;
require_once( "$my_class_name.class.php" );
}
spl_autoload_register( 'my_fancypants_autoloader' );
Now all you have to do is include one configuration file in your .php files to access your classes.
Hope that points you in the right direction! Good luck!
Since your are only using them into the __construct method, you don't need them as class attributes. Only the $connection has to be kept for later use imho.
It might be much much better to not give any default values to those arguments but let them being set from the outside.
$db = new DatabaseConnection("localhost", "user", "password", "db");
They are plenty of PHP tools for that already, find them, read them and learn from that. First of all, use PDO and what is true in Java isn't always true in PHP.
The latter is probably better, but with an adjustment: pass some arguments to the constructor, namely the connection info.
Your first example is only useful if you've got one database connection and only if you're happy hard-coding the connection values (you shouldn't be). The second example, if you add say, a $name parameter as an argument, could be used to connect to multiple databases:
I'm new to OOP. Originally I was defining variables and assigning values to them within the class and outside of the constructor, but after an OOP lesson in Java today, I was told this is bad style and should be avoided.
class DatabaseConnection {
private $dbHost;
private $dbUser;
private $dbPass;
private $dbName;
function __construct($config) {
// Process the config file and dump the variables into $config
$this->dbHost = $config['host'];
$this->dbName = $config['name'];
$this->dbUser = $config['user'];
$this->dbPass = $config['pass'];
$connection = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass)
or die("Could not connect to the database:<br />" . mysql_error());
mysql_select_db($this->dbName, $connection)
or die("Database error:<br />" . mysql_error());
}
}
So using this style, you now have a more useful class.
Here is mine and it works rather well:
class Database
{
private static $_dbUser = 'user';
private static $_dbPass = 'pwd';
private static $_dbDB = 'dbname';
private static $_dbHost = 'localhost';
private static $_connection = NULL;
/**
* Constructor
* prevents new Object creation
*/
private function __construct(){
}
/**
* Get Database connection
*
* #return Mysqli
*/
public static function getConnection() {
if (!self::$_connection) {
self::$_connection = #new mysqli(self::$_dbHost, self::$_dbUser, self::$_dbPass, self::$_dbDB);
if (self::$_connection -> connect_error) {
die('Connect Error: ' . self::$_connection->connect_error);
}
}
return self::$_connection;
}
}
By making the __construct empty, it prevents a new class being instantiated from anywhere. Then, make the function static so now all I need to do to get my connection is Database::getConnection() And this is all in an include file, in a password protected folder on the server and just included with each class file. This will also check to see if a connection is already open before attempting another one. If one is already established, it passes the open connection to the method.
<?php
class config
{
private $host='localhost';
private $username='root';
private $password='';
private $dbname='khandla';
function __construct()
{
if(mysql_connect($this->host,$this->username,$this->password))
{
echo "connection successfully";
}
}
function db()
{
mysql_select_db($this->$dbname);
}
}
$obj=new config();
?>
Related
I am looking into oop to enhance my web dev knowledge. At the moment i am having a bit of an issue. I have created a Database class that contains all the queries etc. ( fetch, count, etc. ) This just allows the queries or updates to take up less space in the other classes etc. The issue i am having is passing this class along and making it globally accessible. I have used
global $db;
within a class function but i read that it is bad practice to use that. I also do not want to pass the $db variable as a parameter if i did i would have to change a lot of my current classes and it would just be easier if i can make $db globally available in a "good" practice way.
I can provide my Database class if necessary it is just a simple class with the variable that initiates the connection through construct.
( Second Question )
I was also reading about the singleton instance function, before implementing i read that it was also considered bad practice. Is there something that should take its place?
( I decided to place the class below )
class Database {
private $host = 'localhost';
private $user = 'xxx';
private $pass = 'xxxx';
private $dbname = 'xxxxx';
private $dbh;
private $error;
public function __construct(){
// Set DSN
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
// Set options
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
PDO::ATTR_EMULATE_PREPARES => false
);
// Create PDO Instance
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
public function fetch($sql, $param = "") {
$this->stmt = $this->dbh->prepare($sql);
if (empty($param)) {
$this->stmt->execute();
} else {
$this->stmt->execute($param);
}
return $this->stmt->fetch();
}
}
$db = new Database();
An example of what i am attempting to accomplish is as follows
( User Profile Page )
class User {
function set_user($input) {
if (is_numeric($input)) {
$this->user = $input;
} else {
$user = $db->fetch("SELECT userid FROM users WHERE url=:url", array(':url' => $input));
$this->user = $user['userid'];
}
}
}
AN issue with your approach is not the global var, but that the DB connection is permanently open. It is not always good. This is kind of service object and it is not partiularily bad to have it globally visible.
If you don't want it global and want to solve the open connection issue, you can easily close the connection in the destructor, remove the global var and create/use/delete the DB wherever required.
Another approach would be not to use singleton, but so called service class. Make DB class not instanciable, but rather define service methods (all static) - open, close, execute, or whatever. Than the DB clients should not create DB object, but only access the static methods. This approach fits the reality very nice, as DB-access is seen as a service.
I am wondering if I use mysql with php secure. This is my class:
class DB{
public $mysqli = null;
public $result = array();
private $_host = 'localhost';
private $_user = 'root';
private $_password = 'root';
private $_db_name = 'DBNAME';
public function __construct()
{
$this->mysqli = new mysqli($this->_host,$this->_user, $this->_password, $this->_db_name);
if ($this->mysqli->connect_errno){
echo "Error MySQLi: (" . $this->mysqli->connect_errno . ") " . $this->mysqli->connect_error;
exit();
}
$this->mysqli->set_charset("utf8");
}
public function __destruct(){
$this->mysqli->close();
}
public function query($query){
$this->result = $this->mysqli->query($query);
if($this->result){
return $this->result;
}else{
return false;
}
}
Is that way to comunicate with database good enough or should I use Doctrine ?
I am asking because something strange is in my code. If I vardump any object contains reference to DB object, I can see :
["_host":"DB":private]=> string(9) "localhost" ["_user":"DB":private]=> string(4) "root"
["_password":"DB":private]=> string(4) "root" ["_db_name":"DB":private]=> string(10) >"DBNAME" }
If you are worried about the DB settings shown on var_dump, I suggest you place those settings in a config file and send those configs as params.
Personally, I wouldn't worry about it. If someone has access to your object (maybe another shared object) they probably have the ability to read your settings. The only positive I see with having a config file is that you can update those configs without having to touch the php codebase.
Is there a reason why you think this would be an issue?
Also your code structure is nice, keep it extracted from mysqli, don't switch to an extend. This will give you flexibility in the future should you decide to switch to PDO or any other better extensions that come up.
Why reinvent the wheel? Your query function pretty much does what mysqli_query is already doing for you. I would just use the base mysqli class as you're already doing by making this class extend that one
class DB extends mysqli {
private $_host = 'localhost';
private $_user = 'root';
private $_password = 'root';
private $_db_name = 'DBNAME';
public function __construct()
{
parent::__construct($this->_host,$this->_user, $this->_password, $this->_db_name);
}
}
Your question is like "should I put a hat or a cap ?".
Actually, there is no best way to deal with a database. It depends of witch approach you have.
If you prefer write SQL code, then your solution is good and works well for your usage.
However, if you do not want to write SQL query and work only with objects, then you will prefer use doctrine.
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.
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 !
So recently I've really started to use php actively, and I need some insights on different ways to use database connections.
At first I just used the simple mysql_connect():
<?php
$connection = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die(mysql_error());
mysql_select_db(DB_DB, $connection);
?>
After a while I created a database class which I started to include and initialize in every file - something like this:
<?php
class MySQL_DB {
var $connection;
function MySQL_DB(){
$this->connection = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die(mysql_error());
mysql_select_db(DB_DB, $this->connection);
}
function query($q){
$res = mysql_query($q, $this->connection) or die(mysql_error());
return $res;
}
}
$database = New MySQL_DB;
?>
And this is what I'm using at the time - and it's working fine - but there are always ways to improve.
So my question to you is how do you manage your database connections?
Do you use classes?
What does your classes contain (just
the connection or even functions?)
What practices do you recommend?
I recommend to use PDO. Don't reinvent the weel. It's a nice OO-interface to many database engines.
Additionally I create a small function which just inititializes PDO object. So all connection settings can be changed in one place.
Your current approach is pretty standard, and works well. I used it for a long time. It's true that modules like PDO provide base functionality like this now, which is very nice as well and can get you away from problems with home-brew code.
However, I've taken the connection management one step further. If you get into a complex application, you might get into a situation where you have multiple databases, or heavy database use. Including a single database connection file and having a global $database variable becomes unwieldy for multiple databases, and it's unnecessary for application requests that might not need a database connection. Remember, connecting to the database is expensive.
What I've done is create a singleton DatabaseManager class that handles the database object for me, and makes sure multiple connections to a given DB don't get instantiated. Instead of initializing a new database object at the top of your app, you simply call on the DatabaseManager every time you need the object.
$db = DatabaseManager::getDatabase();
Here's an example class that I had whipped up for a CodeIgniter project. You can see in the getDatabase() function it simply loads CodeIgniter's default database object, which you would substitute for your own class (and run the connection routine for it) if you weren't using CI. This is a pretty simplistic management class, and could be extended to manage multiple connections to different databases fairly easily.
<?php
/**
* Implements the Singleton pattern to prevent multiple instantiations and connections
* to the application database.
*
*/
class Database_manager
{
private static $instance;
public $db;
/**
* Constructor function is declared private to prevent instantiation.
*
*/
protected function __construct()
{
parent::__construct();
}
/**
* Returns an instance of a Database_manager.
*
* #return object Database_manager object
*/
public static function getInstance()
{
if (self::$instance == null) {
$className = __CLASS__;
self::$instance = new $className();
}
return self::$instance;
}
public static function getDatabase()
{
$instance = self::getInstance();
if ($instance->db == null) {
//utilize CodeIgniter's database loader
$instance->db = $instance->load->database('',true);
if (! is_object($instance->db)) throw new Exception("Could not load database.");
}
return $instance->db;
}
}
Perhaps the most common advantage I get out of using this style of connection management is when I have to take down an application for database maintenance. By not instantiating a database connection until I need it, I can easily put up a "maintenance in progress" message on a site (short circuiting normal MVC dispatching), and not worry about requests to the application opening a DB connection while maintenance is in progress.
Usage of classes are the way to go to increase customized re-usability.
Bring in all generic implementations into the class. You are on the right track.
This website has the following clean approach.
This website link is no longer present. Archive Link.
class connection {
// Possible Modules are as follows:
// DBX_MYSQL, DBX_ODBC, DBX_PGSQL, DBX_MSSQL, DBX_FBSQL, DBX_SYBASECT, DBX_OCI8, DBX_SQLITE
private $module = DBX_MYSQL;
private $host = "localhost";
private $database = "test";
private $username = "testuser";
private $password = "testpass";
private $link;
private $result;
public $sql;
function __construct($database=""){
if (!empty($database)){ $this->database = $database; }
$this->link = dbx_connect($this->module,$this->host,$this->database,$this->username,$this->password);
return $this->link; // returns false if connection could not be made.
}
function query($sql){
if (!empty($sql)){
$this->sql = $sql;
$this->result = dbx_query($this->link,$sql,DBX_RESULT_UNBUFFERED);
return $this->result;
}else{
return false;
}
}
function fetch($result=""){
if (empty($result)){ $result = $this->result; }
return dbx_fetch_row($result);
}
function __destruct(){
dbx_close($this->link);
}
}
In your database manager example, you did not define a parent for your class.
Therefore, invoking parent::__constructor() yields an exception,
and also, you cannot use the load property of code ignitor.
Which class did you use as an extension for your DatabaseManager?
Since i do not know where you placed your databasemanager code, nor which class you used as its parent, i circumvented the exceptions by making the getDatabase() method receive an input parameter which i called $loader.
Normally, this $loader object will be the model class requiring access to a database.
public static function getDatabase($loader)
{
$instance = self::getInstance();
if ($instance->db == null) {
//utilize CodeIgniter's database loader
$instance->db = $loader->load->database('default',true);
if (! is_object($instance->db)) throw new Exception("Could not load database.");
}
return $instance->db;
}
Best regards.