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.
Related
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.
My database class works perfectly and I call it like this $db = new Database('user', 'pass', 'db', 'host');. I top of my script I am defining this database, but later in the script I am trying to use the connection inside a function, but it seems to that the $db is not global, so my function can't access it. I have the possibility to create a new database class connection inside every function in my script, but I really would like to access the $db as a global access point.
Here is some code:
require_once('database_class.php');
$db = new Database('user', 'pass', 'db', 'host');
// I can reach the $db here and make the $db->PDO->'statement'();
function userExists($user) {
$bool = false;
// But in here I can't access $db...
$query = $db->PDO->query('SELECT * FROM login WHERE username = "$user"');
$result = $query->fetch();
if ($result) {
// User exists
$bool = true;
}
return $bool;
}
Put global $db at the beginning of the function like so:
function userExists($user) {
global $db;
// Rest of code here
Variables within functions only exist locally by default in PHP. To use a variable declared outside of a function which is not passed as an argument (e.g $user) you need to use a global variable as shown above.
You could probably just modify your functions to take the $db var as an argument. e.g. :
function userExists($user, $db) {
...
}
Objects are passed by reference by default (see here) so you won't be inadvertently making copies of the $db object with each call.
I use classes for connections and queries too. But it would help that you define already in your class the variables needed for connection, so you don't have to repeat them in every page of code.
and maybe this? use the db as an argument.
function userExists($user, $db) { //codecodecode }
I wrote this code
require('Database.class.php');
function get_info (){
$db = new Database($config['server'], $config['user'], $config['pass'], $config['database'], $config['tablePrefix']);
$db->connect();
$sql = $db->query('SELECT * FROM ja_cat');
while ($options = $db->fetch_array($sql)) {
$cat[].=" ".$options['title'];
}
$db->close();
return $cat;
then I get this Mysql error
Mysql Error : No database selected .
but when I put the require instruction inside the function it's work fine
My guess is Database.class.php creates some variables that are probably global in scope that it relies upon. If you require it inside the function and it works, that supports that theory. Is that your class? Can you change it? Can you post it?
Basically $config needs a global qualifier inside the function.
Make this the first line IN your get_info() function:
global $config;
Also, you may want to define $db outside of the function at the start of the code and then close the connection at the end, instead of having to re-connect multiple times.
You have to import the global variable $config into the scope of the function:
function get_info() {
global $config;
}
I am trying to convert code from mysql to mysqli.
The code uses a single mysql_connect in a file which is included by every other file.
mysql_connect returns a MySQL link identifier that is a superglobal so you can rely on having a database connection available in any of your own functions.
It looks like with mysqli_connect this is not the case, the object returned isn't global.
Does this mean I have to add : global $mysqli; at the top of every function, or is there an way of making it a superglobal?
Relying on the fact that PHP will use the last opened connection resource if you don't specify one, is probably not a very good idea.
What happens if your application changes and you need two connections, or the connection is not there?
So it seems you need to do some refactoring anyway.
Here's a solution similar to Karsten's that always returns the same mysqli object.
class DB {
private static $mysqli;
private function __construct(){} //no instantiation
static function cxn() {
if( !self::$mysqli ) {
self::$mysqli = new mysqli(...);
}
return self::$mysqli;
}
}
//use
DB::cxn()->prepare(....
I usually make a function:
$mysqli = new mysqli(...);
function prepare($query) {
global $mysqli;
$stmt = $msqyli->prepare($query);
if ($mysqli->error()) {
// do something
}
return $stmt;
}
function doStuff() {
$stmt = prepare("SELECT id, name, description FROM blah");
// and so on
}
and then call that. That being said, I've since abandoned mysqli as being too bug-ridden to be considered usable. Shame really.
A very simple way to do this would be with a fixed database class, just to hold the mysqli connection object:
class Database {
public static $connection;
}
Database::$connection = new mysqli(HOST, USERNAME, PASSWORD, DATABASE);
Then you can access it in the normal ways:
$sql = 'SELECT * FROM table';
$result = Database::$connection->query($sql);
$result = mysqli_query(Database::$connection, $sql);
echo 'Server info ' . mysqli_get_server_info(Database::$connection);
To introduce some oop to you and solve your problem, you could use a class like this:
class MyDatabase
{
private static $_connection;
public static function connect()
{
$mysqli = new mysqli(...);
self::$_connection = $mysqli;
}
public static function getConnection()
{
return self::$_connection;
}
}
In your database-connection file you would load this class and execute MyDatabase::connect(); once.
To get the $mysqli-connection anywhere in your script, just call MyDatabase::getConnection();.
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.