I have a function like this:
function write_to_db($foo) {
$db = new PDO("sqlite:bar.db");
$query = $db->prepare("INSERT INTO table VALUES (?)");
$query->bind_param("s", $foo);
$query->execute();
}
Problem is that I am calling this function multiple times inside my php-script(s). Is there a way to make the $db variable static somehow so that it won't need to open & close the file multiple times during executing of the php-script?
Sending the database as a parameter is not an option as the function is called withing classes and other functions and then I would need to make all of them aware of the database.
Edit: ok, I was told this is the best practice and I guess I don't need to worry about performance.
Yes there is way to make it. You can do it via Singleton object. You can find more information about of Singleton Pattern.
So I made a simple implementation of it which what you want to do.
class SqliteSingleton
{
private static $connection = null;
public static function getConnection($path = null){
if ($this->connection == null) {
$this->connection = new PDO("sqlite:" . $path);
}
return $this->connection;
}
}
You can use it at anywhere you want.
$connection = SqliteSingleton::getConnection('bar.db');
Also you can do research and made more efficient class design then this.
Related
So I am basically re-doing some code on an existing system, mainly the database functions and I am putting them in a class rather than a function (currently the mysqli_connect DSN information is set in global variables and is being used every single time a query is being done which is why I am trying to clean this up but I am not trying to re-do this entire system all right now).
Current system has many PHP files that will include the main dbconnect.php file with a function of something like function db_query($query,$DSN){} and we have in almost every single other file the actual SQL query being written out and then passed off as db_query($query); and that is it.
I have moved over to something along the lines of the below code:
dbconnect.php
class Db {
protected static $connection;
function __construct() {
if (! isset($GLOBALS['DEBUG'])) { $GLOBALS['DEBUG'] = 0; }
}
public function connect() {
if(!isset(self::$connection)) {
self::$connection = new mysqli($GLOBALS['DSN']);
}
if(self::$connection === false) {
return false;
}
unset($GLOBALS['DSN']); //unset so that login info is not roaming around anymore now that the connection has been established
return self::$connection;
}
public function db_query($query) {
$connection = $this->connect();
$result = $connection->query($query);
return $result;
}
}
otherphpfile.php
include_once 'dbconnect.php';
(new Db()); //I have also tried new Db();
$query = "SELECT * FROM table;";
db_query($query); //I have to try to do it like this since 99.9% of the system is already using this method and I don't want to have to go through all the code and update it with something like:
$db = new Db();
$db->db_query($query);
I understand that $db = new Db(); $db->db_query($query); is correct but I am trying to do it like this new Db(); without a variable assigned to it because all of the other functions for dbconnect.php are written without a variable in front of the function call such as db_query($query); like they are right now without me having to go and update all of them to $db->db_query($query);.
I hope this makes sense and any suggestions would be great without compromising the benefit of using classes to begin with (AKA setting public static functions is just not worth it)
Thank you
Part of refactoring is to update code. Honestly, any IDE would make replacing the usage of db_query() a breeze. You can replace the db_query( with (new Db())->db_query(. Since you are already storing the connection statically, I suggest making the class methods also static. Having something like Db::query(...) would be less redundant and more readable.
A couple of the options are:
$connection = {my db connection/object};
function PassedIn($connection) { ... }
function PassedByReference(&$connection) { ... }
function UsingGlobal() {
global $connection;
...
}
So, passed in, passed by reference, or using global. I'm thinking in functions that are only used within 1 project that will only have 1 database connection. If there are multiple connections, the definitely passed in or passed by reference.
I'm thining passed by reference is not needed when you are in PHP5 using an object, so then passed in or using global are the 2 possibilities.
The reason I'm asking is because I'm getting tired of always putting in $connection into my function parameters.
I use a Singleton ResourceManager class to handle stuff like DB connections and config settings through a whole app:
class ResourceManager {
private static $DB;
private static $Config;
public static function get($resource, $options = false) {
if (property_exists('ResourceManager', $resource)) {
if (empty(self::$$resource)) {
self::_init_resource($resource, $options);
}
if (!empty(self::$$resource)) {
return self::$$resource;
}
}
return null;
}
private static function _init_resource($resource, $options = null) {
if ($resource == 'DB') {
$dsn = 'mysql:host=localhost';
$username = 'my_username';
$password = 'p4ssw0rd';
try {
self::$DB = new PDO($dsn, $username, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
} elseif (class_exists($resource) && property_exists('ResourceManager', $resource)) {
self::$$resource = new $resource($options);
}
}
}
And then in functions / objects / where ever:
function doDBThingy() {
$db = ResourceManager::get('DB');
if ($db) {
$stmt = $db->prepare('SELECT * FROM `table`');
etc...
}
}
I use it to store messages, error messages and warnings, as well as global variables. There's an interesting question here on when to actually use this type of class.
Try designing your code in an object-oriented fashion. Methods that use the database should be grouped in a class, and the class instance should contain the database connection as a class variable. That way the database connection is available to the functions that need it, but it's not global.
class MyClass {
protected $_db;
public function __construct($db)
{
$this->_db = $db;
}
public function doSomething()
{
$this->_db->query(...);
}
}
I see that a lot of people have suggested some kind of static variable.
Essentially, there is very little difference between a global variable and a static variable. Except for the syntax, they have exactly the same characteristics. As such, you are gaining nothing at all, by replacing a global variable with a static variable. In most examples, there is a level of decoupling in that the static variable isn't referred directly, but rather through a static method (Eg. a singleton or static registry). While slightly better, this still has the problems of a global scope. If you ever need to use more than one database connection in your application, you're screwed. If you ever want to know which parts of your code has side-effects, you need to manually inspect the implementation. That's not stuff that will make or break your application, but it will make it harder to maintain.
I propose that you chose between one of:
Pass the instance as arguments to the functions that needs it. This is by far the simplest, and it has all the benefits of narrow scope, but it can get rather unwieldy. It is also a source for introducing dependencies, since some parts of your code may end up becoming a middleman. If that happens, go on to ..
Put the instance in the scope of the object, which has the method that needs it. Eg. if the method Foo->doStuff() needs a database connection, pass it in Foo's constructor and set it as a protected instance variable on Foo. You can still end up with some of the problems of passing in the method, but it's generally less of a problem with unwieldy constructors, than with methods. If your application gets big enough, you can use a dependency injection container to automate this.
My advice is to avoid global in the bulk of the code - it's dangerous, hard to track and will bite you.
The way that I'd do this is to have a function called getDB() which can either be at class level by way of a constructor injection or static within a common class.
So the code becomes
class SomeClass {
protected $dbc;
public function __construct($db) {
$this->dbc = $db;
}
public function getDB() {
return $this->dbc;
}
function read_something() {
$db = getDB();
$db->query();
}
}
or using a common shared class.
function read_something() {
$db = System::getDB();
$db->query();
}
No matter how much elegant system design you do, there are always a few items that are necessarily global in scope (such as DB, Session, Config), and I prefer to keep these as static methods in my System class.
Having each class require a connection via the constructor is the best way of doing this, by best I mean most reliable and isolated.
However be aware that using a common shared class to do this can impact on the ability to isolate fully the objects using it and also the ability to perform unit tests on these objects.
None of the above.
All the mysql functions take the database connection argument optionally. If you leave that argument out, the last connection by mysql_connect() is assumed.
function usingFunc() {
$connection = getConnection();
...
}
function getConnection() {
static $connectionObject = null;
if ($connectionObject == null) {
$connectionObject = connectFoo("whatever","connection","method","you","choose");
}
return $connectionObject;
}
This way, the static $connectionObject is preserved between getConnection calls.
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 trying to refactor some code but I'm kinda confused. I define my database connection like so:
try{
global $conn;
$conn = new PDO("mysql:host=$host",$root,$pw); [...]
Now I'd like a function for retrieving table rows but it needs $conn. Is there any way in which I can pass $conn into this function? I tried to set it as a default value but that doesn't work:
function get($table,$conn=$conn,$limit=10){ [...]
I then tried the use keyword but I think it's only available for anonymous functions:
function get($table,$limit=10)use($conn){
$query = $conn->query(" [...]
How do other people do this? Am I missing something obvious here?
function get($table, $limit=10)
As you already wrote in your question, this function header is incomplete. The function itself can not do what it needs to do without having $conn.
As this is a function in the global namespace, the most straight forward thing could be to use a global variable:
function conn_get($table, $limit=10) {
global $conn;
I also name-spaced the function to make the relation clear. The problem with this are two things:
global functions are expensive to maintain
global variables are expensive to maintain
So what you normally do in that case is to wrap this into a class:
class Conn
{
private $conn;
public function __construct(PDO $conn) {
$this->conn = $conn;
}
public function get($table, $limit=10) {
$query = $this->conn->query("[...]");
...
}
}
You then pass around a Conn object which can be used:
$pdo = new PDO("mysql:host=$host", $root, $pw);
$conn = new Conn($pdo);
And then:
$conn->get('ColorTable', 200);
The private variable takes over the role of the global variable with the benefit that every method inside the same object can access it. So everything now is in it's own space and contrary to the global space, will not go into each others way that fast. This is easy (easier) to change and maintain over time.
When you call the function i.e:
$table_rows = get($table, $conn);
You are passing local variables inside the function scope.
However you can't define a not-static variable as default: $conn=$conn will throw a fatal error.
In PHP, use is the way to go for anonymous / lambda-functions but not for ordinary functions.
If you have the database connection flying around in global scope, you can either pass it as a normal variable to your functions like so:
function get(PDO $conn, $table,$limit=10) {
$query = $conn->query(" [...]
}
Other than that (bad practice!) is to get the global $conn variable into the function like so:
function get($table,$limit=10) {
$query = $GLOBALS['conn']->query(" [...]
}
However, an object oriented approach is recommended! You might want to inject the Database Class via dependency injection into the classes, where you need it.
the most simple thing you can do is to create a function that will return you the $conn variable
function conn (){
$conn = NULL;
...some database connection setup etc...
return $conn;
}
and call it to other functions that you need to use it
function getDb(){
conn()->query(" [...]");
}
the conn() function will be available to all your functions on your PHP script.
but if you plan to make a more complex web application I recommend you to use a PHP framework or make a PHP class and apply OOP principles that would handle the database connection for you.
A couple of the options are:
$connection = {my db connection/object};
function PassedIn($connection) { ... }
function PassedByReference(&$connection) { ... }
function UsingGlobal() {
global $connection;
...
}
So, passed in, passed by reference, or using global. I'm thinking in functions that are only used within 1 project that will only have 1 database connection. If there are multiple connections, the definitely passed in or passed by reference.
I'm thining passed by reference is not needed when you are in PHP5 using an object, so then passed in or using global are the 2 possibilities.
The reason I'm asking is because I'm getting tired of always putting in $connection into my function parameters.
I use a Singleton ResourceManager class to handle stuff like DB connections and config settings through a whole app:
class ResourceManager {
private static $DB;
private static $Config;
public static function get($resource, $options = false) {
if (property_exists('ResourceManager', $resource)) {
if (empty(self::$$resource)) {
self::_init_resource($resource, $options);
}
if (!empty(self::$$resource)) {
return self::$$resource;
}
}
return null;
}
private static function _init_resource($resource, $options = null) {
if ($resource == 'DB') {
$dsn = 'mysql:host=localhost';
$username = 'my_username';
$password = 'p4ssw0rd';
try {
self::$DB = new PDO($dsn, $username, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
} elseif (class_exists($resource) && property_exists('ResourceManager', $resource)) {
self::$$resource = new $resource($options);
}
}
}
And then in functions / objects / where ever:
function doDBThingy() {
$db = ResourceManager::get('DB');
if ($db) {
$stmt = $db->prepare('SELECT * FROM `table`');
etc...
}
}
I use it to store messages, error messages and warnings, as well as global variables. There's an interesting question here on when to actually use this type of class.
Try designing your code in an object-oriented fashion. Methods that use the database should be grouped in a class, and the class instance should contain the database connection as a class variable. That way the database connection is available to the functions that need it, but it's not global.
class MyClass {
protected $_db;
public function __construct($db)
{
$this->_db = $db;
}
public function doSomething()
{
$this->_db->query(...);
}
}
I see that a lot of people have suggested some kind of static variable.
Essentially, there is very little difference between a global variable and a static variable. Except for the syntax, they have exactly the same characteristics. As such, you are gaining nothing at all, by replacing a global variable with a static variable. In most examples, there is a level of decoupling in that the static variable isn't referred directly, but rather through a static method (Eg. a singleton or static registry). While slightly better, this still has the problems of a global scope. If you ever need to use more than one database connection in your application, you're screwed. If you ever want to know which parts of your code has side-effects, you need to manually inspect the implementation. That's not stuff that will make or break your application, but it will make it harder to maintain.
I propose that you chose between one of:
Pass the instance as arguments to the functions that needs it. This is by far the simplest, and it has all the benefits of narrow scope, but it can get rather unwieldy. It is also a source for introducing dependencies, since some parts of your code may end up becoming a middleman. If that happens, go on to ..
Put the instance in the scope of the object, which has the method that needs it. Eg. if the method Foo->doStuff() needs a database connection, pass it in Foo's constructor and set it as a protected instance variable on Foo. You can still end up with some of the problems of passing in the method, but it's generally less of a problem with unwieldy constructors, than with methods. If your application gets big enough, you can use a dependency injection container to automate this.
My advice is to avoid global in the bulk of the code - it's dangerous, hard to track and will bite you.
The way that I'd do this is to have a function called getDB() which can either be at class level by way of a constructor injection or static within a common class.
So the code becomes
class SomeClass {
protected $dbc;
public function __construct($db) {
$this->dbc = $db;
}
public function getDB() {
return $this->dbc;
}
function read_something() {
$db = getDB();
$db->query();
}
}
or using a common shared class.
function read_something() {
$db = System::getDB();
$db->query();
}
No matter how much elegant system design you do, there are always a few items that are necessarily global in scope (such as DB, Session, Config), and I prefer to keep these as static methods in my System class.
Having each class require a connection via the constructor is the best way of doing this, by best I mean most reliable and isolated.
However be aware that using a common shared class to do this can impact on the ability to isolate fully the objects using it and also the ability to perform unit tests on these objects.
None of the above.
All the mysql functions take the database connection argument optionally. If you leave that argument out, the last connection by mysql_connect() is assumed.
function usingFunc() {
$connection = getConnection();
...
}
function getConnection() {
static $connectionObject = null;
if ($connectionObject == null) {
$connectionObject = connectFoo("whatever","connection","method","you","choose");
}
return $connectionObject;
}
This way, the static $connectionObject is preserved between getConnection calls.