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.
Related
I've been taking help from this site by years now, but I have never asked, so this is my first question here. This is a theoretic question, I would like to know if I'm thinking in the right way.
First of all, sorry for my English.
I was thinking if I could simplify my existing MySQL object.
For the connection, I use the singleton pattern to ensure that my app connect only one time during script execution. So, in every class, when I want to use MySQL, a get the instance.
$db = db::getInstance();
$result = $db->query("SELECT * FROM data;");
the $result is a dbResult class, on which I can use loops (while($row = $result->nextRow()) {...}), jump to row number, etc...
after all things are done, then I $result->free(); the result class.
Question 1.
Why not return an associative array instead of the dbResult class? I could use a foreach on it. But what about a result with 1.000.000 rows?
Question 2.
Do I have to get the instance every time I want to use SQL?
class db{
...
private static $instance;
...
public static function query($_query){
if (!self::$instance){
self::$instance = new db(); //first we need to connect...
self::query($_query);
}
else{
//execute query, then load result in array,
//or in case of insert, return insert_id
return $return_array;
}
}
In this case, I can simply call a query from anywhere in my code without instantiating the db object.
$result = db::query("SELECT * FROM data;");
...
//or insert
db::query("INSERT INTO test VALUES ('test_value');");
Would be this a bad practice?
Have a look at Doctrine 2 for example. It's a big project, but when u master it, its damn awesome :)
If this is too big for you, refactor your class to not use singleton pattern implementation and/or static methods.
Here's what I suggest:
Create a Database class.
<?php
class Database {
private $db;
private $host;
private $username;
private $password;
// Should probably not put your DB credentials here, just the Databases, but its just here for this purpose
const DB_HOST = '';
const DB_USERNAME = '';
const DB_PASSWORD = '';
// Just an example of having multiple databases, so you can just Database::DB_1 when you need to use them
const DB_1 = '';
const DB_2 = '';
const DB_3 = '';
public function __construct($db = self::DB_1, $host = self::DB_HOST, $username = self::DB_USERNAME, $password = self::DB_PASSWORD) {
$this->db = $db;
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->db = $db;
}
// So if you have different databases, you can create different functions to connect to them via PDO drivers
public function connectToMySQL($db = null) {
$dsn = is_string($db) ? 'mysql:dbname='.$db.';host='$this->host : 'msql:dbname='.$this->db.';host='$this->host;
try {
return new PDO($dsn, $this->username, $this->password);
} catch (PDOException $E) {
echo 'Connection error: '.$E->getMessage();
exit();
}
}
To use this you would just:
/*
* Remeber how we defined it? you can leave the parameters blank, or pass in things
*/
$Database = new Database();
/*
* A PDO database object that connects to your database automaticaly.
* You can also passin Database::DB_2 sand stuff if you hav multiple databases.
* is a PDO object, so to use it, just look up PHP's PDO tutorials
*/
$PDO = $Database->connectToMySQL();
/*
* Then to end the connection, it's just as simple as setting it to null
*/
$PDO = null;
This way, you create 1 Database object that can generate MANY connections, it's like a Factory class.
I believe this why is most versatile, but I'm always open to suggestions as well.
Today i tried to convert my functions to PHP Class.
I tried with some basic steps.
<?php
class DataBase {
private $host;
private $user;
private $password;
private $db;
private $mysqli;
function __construct() {
$this->host = "localhost";
$this->user = "root";
$this->password = "";
$this->db = "my_database";
$this->mysqli = new mysqli($this->host, $this->user, $this->password, $this->db);
}
function __destruct() {
$this->mysqli->close();
}
public function query($query, $params = '', $bind_result) {
$stmt = $this->mysqli->prepare($query);
//Need to change this to process the array of params
$stmt->bind_param('i', $params);
$stmt->execute();
//Change this to handle array of bind
$stmt->bind_result($bind_result);
//Loop the result and store it in a temp array
$stmt->fetch();
//Don't print the statement. Just close the statement and return the array.
printf("%s\n", $bind_result);
/* close statement */
$stmt->close();
}
}
?>
I have to now create another class. I created one dummy table in database.
<?php
class Dummy {
private $database;
function __construct() {
$this->database = new Database();
}
public function getAllDummy() {
$query = "SELECT name FROM dummy WHERE id = ?";
$this->database->query($query, 1, 'name');
}
}
?>
But I don't think it is the right way to do the things. I feel some of them are in the right way and some of them are wrong.
When i call the query() function, Do i need to connect the database all the time in every classes' construct method? Or Do i need to change the Database class to static functions? So i can call the functions like Database::query();
It seems i need to create everything from the start. Is such a model already available in internet? like cakephp, codeigniter
I would like to recommend you to read something about ORM for PHP. For example I m using Doctrine 2 (http://www.doctrine-project.org/) It is kinda complex but definitely worth to learn. There is everything you are trying to code already done, so why you should make it again?
In your OOP principe there are some mistakes.
You are creating Database instance for every class like Dummy, if you will have class Users, Articles, you will create 3x Database, it isnt really good. You should make Database as service or Singleton and make it just once. Good solution for this can be Dependency injection (http://en.wikipedia.org/wiki/Dependency_injection).
Also I would recommend you to generalize whole Dummy class, to make it more general. Dont make method "getAllDummy" but for example "getAll($tableName)"so you can use it for every table.
Besides Doctrine (Which is powerfull and almighty already but still to complex) I can suggest you db.php (http://dbphp.net) which does everything what doctrine but is single file and is very easy to use. Cons: It is not well documented yet and has no big community yet.
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();
?>
Okay, it seems the word on the street is that global variables are bad.
Well, if I have:
$dbc = mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
and then I have several functions and such that all depend on that db connection, what is the most sound way to access $dbc in all my functions?
Is this a case where making it global is okay? Declaring it as a global variable inside each function seems redundant.
What is the best way to tackle this?
In this case, the global variables won't be a problem.
Another way to tackle this though could be to write a Database class which stores these variables. The plus side of this is that if you feel you need to switch to a new database handler, say PDO, it will be a rather simple task.
<?php
class Database
{
private $host;
private $user;
private $password;
private $dbname;
public function __construct()
{
$this->host = '';
$this->dbname = '';
$this->user = '';
$this->password = '';
}
public function connect() {
return mysqli_connect($this->host, $this->user, $this->password, $this->dbname);
}
}
?>
In the future you could easily:
switch to PDO without worrying about massive refactoring
you could inject connection details into the constructor
use the Singleton pattern to store your connection
I am trying to create a class with various methods that will need to interact with a database, so I am trying to create a database object using mySQLi in the __construct, depending on if I still have a db connection or not, but I am unsure of how I can access the db object from within a method as I am new to object oriented PHP, here is my code,
class my_class
{
private $db_host = '';
private $db_user = '';
private $db_pass = '';
private $db_name = '';
function __construct() {
$myconn = new mysqli($this->db_host,$this->db_user,$this->db_pass,$this->db_name);
if($myconn) {
$this->con = true;
return true;
} else {
return false;
}
}
private function my_function(){
//not sure how I can access the database object from here to run a query
}
}
any advice on how I can improve this, or approach this in a better way, will be appreciated!
Please excuse my ignorance on the subject!
Thanx in advance guys!
Store the object ($myconn) in an member of the object.
$this->oConnection = $myconn;
Then you can simply use $this->oConnection to access your object.
Mind the deceleration in of your new member private $oConnection at the top of your class.