My question is:
Can I still do query's from within an object like this:
$result = mysql_query ($q,$dbc)
or
trigger_error("Query: $q\n<br />MySQL Fout: " . mysql_error($dbc));
by passing the global dbconnection variable $dbc to the constructor
or is there a better way?
Or creating a singleton class for the databaseconnection, but
I see a lot off negativity that people are writing about it.
I am new to making objects, so I don't know if I mayby have to do it all a little
different, with the db I mean.
thanks, Richard
If you looking for database abstraction, why not consider using the DB classes provided by Zend Framework.
They also include a way to set an adapter as the default, making it a snap to perform operations.
Add to that the fact that Zend_Db defaults to using parameterised queries instead of old fashioned quoted ones, thus adding security and peace of mind.
using globals is pretty much a bad idea, its far too easy to accidentally overwrite one! along with all the other reasons you will find for not using them with a quick google.
Making a db connection with Zend Framework is a snap,
$db = Zend_Db::factory('Pdo_Mysql', array(
'host' => '127.0.0.1',
'username' => 'webuser',
'password' => 'xxxxxxxx',
'dbname' => 'test'
));
It really is as simple as that. you can then either make your table classes to provide quick access to individual tables, or use the select and statement objects for more advanced joined querys.
Also, with Zend Framework, you do not have to use the whole stack, you can simply use just the DB components if you like.
If you don't want to use Zend Framework for this, I would strongly recommend you consider alternatives such as an ORM like Doctrine over writing your own DB abstraction. you will end up with a monster very quickly, and an ORM or Zend Framework have a great many developers squashing bugs, and even more reporting any that are there.
Yes, you can pass the database connection around like that.
IMHO it makes coding a little harder but testing a lot easier.
Here's how you would use it:
class DB {
private $dbc;
public function __construct($dbConn) {
$this->dbc = $dbConn;
}
public function runQuery() {
mysql_query($query, $this->dbc);
}
}
Pass the variable. Singletons have a bad reputation for a reason - they were invented to solve a very specific problem, and they didn't even do that particularly well. Don't use them as a way to avoid passing variables around, that's how it should be done.
I use a singleton class for this purpose, but I still pass around my class variable through globals.
The reason the singleton class was created in the first place was to make sure that only one instance of a class is ever created. In this case, I want to make sure that only one instance to the database is ever created. By placing the class as a singleton class, anyone who writes code that interfaces with this class will get the same connection. But, it is still not a replacement for globaling the variable.
For the Singleton class, here is an example:
class datbasebase
{
static $class = false;
static function get_connection()
{
if(self::$class == false)
{
self::$class = new database;
}
else
{
return self::$class;
}
}
// This will ensure it cannot be created again.
protected function __construct()
{
$this->connection = mysql_connect();
}
public function query($query)
{
return mysql_query($query, $this->connection;
}
}
$object = database::get_connection();
The main reason I do it this way instead of simply passing around the connection is purely because I don't want to repeat code over and over. So it is a time saver to have my query, connect, and various other DB functions in the same class.
Related
I have a database class that I developed. But I have doubts about performance in case of load. There are two issues that I was curious about and couldn't find the answer even though I searched.
When the database connection is bound to a static variable in the class,
class DB
{
static $connect;
......
function __construct()
{
try {
self::$connect = new PDO("{$this->db_database}:host={$this->db_host};dbname={$this->db_name};charset=utf8mb4", "{$this->db_username}", "{$this->db_password}");
self::$connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
self::$connect->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES utf8mb4");
} catch ( PDOException $e ){
echo '<b>ERROR: </b>'.$e->getMessage();
exit;
}
}
}
PDO::ATTR_PERSISTENT => true
Does it have an equivalent ability?
Also, I didn't fully understand the pdo permalink logic, it uses the existing connection instead of opening a separate connection for each user. But how does he use the existing link here? For example "ip address" etc.
Thank you for your help.
Let me approach the issues from a different direction.
A program should have only one connection to the database. (There are rare exceptions.) Your code, as it stands, seems to be inconsistent. It has a single ("static") connection, yet the class can be instantiated multiple times, thereby connecting multiple times. (I don't want to depend on anything "persist" to clean up the inconsistency.)
Either make the class a singleton or otherwise avoid being able to call __construct a second time. One approach goes something like this:
class DB {
private static $connect;
......
public function __construct() {
if (! self::$connect) {
self::$connect = ...
}
}
public function Fetch(...) {
self::$connect->...
return ...;
}
$con = new DB();
$data = $con->Fetch(...);
(plus suitable try/catch)
Note that that allows you to sub-class as needed.
Another approach might involve preventing the use of new:
private function __construct() { ... }
plus having some public method invoke that constructor.
Here's another approach. It can be used on an existing class that you don't want to (or can't) modify:
function GetConnection() {
static $db;
if (! $db) {
$db = new ...;
}
return $db;
}
$db = GetConnection();
$db->Fetch(...)'
As for "connection pooling", it is of limited use with MySQL. (Other products need it much more than MySQL does.) In my opinion, don't worry about such.
Do not use "auto-reconnect". If the connection dies in the middle of a transaction and is automatically restarted, then the first part of the transaction will be rolled back while the rest might get committed. That is likely to lead to data inconsistency.
Singletons, statics, globals, void*, critical sections all make me cringe. When I need such, I rush to find a way to "hide" it, even if that means writing cryptic code in some class(es).
For performance, MySQL really needs a single connection throughout the program. I compromise by hiding the connection in a "static" that serves at a "global". Then I hide that inside the class that I use to abstract the object(s).
I agree with Karwin's [now delete] Answer -- that this discussion is "much ado about nothing". MySQL performance is mostly about indexing, query formulation, and even the architecture of the application. Not about connections, common code elimination, redundant function calls, etc.
I know there are loads of questions on this, I have done quite a bit of reading. I'd like to ask this in context of my project to see what suggestions you may have.
I have quite a large web application with many classes, e.g. users and articles (which i consider to be the main classes) and smaller classes such as images and comments. Now on a page, lets say for example an article, it could contain many instances of images and comments. Makes sense right? Now on say an articles page I call a static method which returns an array of article objects.
That's the background, so here are the questions.
Since building a large amount of the app I came to realise it would be very useful to have a core system class containing settings and shared functions. There for I extended all of my classes with a new core class. Seemed relatively simple and quick to implement. I know CodeIgniter does something similar. I feel now though my app is becoming a bit messy.
Question Is this a good idea? Creating an instance of core is exactly what I want when calling an instance of an article, but what about when i'm creating multiple instances using the static method, or calling multiple images or comments on a page. I'm calling the core class unnecessarily right? Really it only needs to be called once per page (for example the constructor defines various settings from the database, I don't want to this every time, only once per page obviously), but all instances of all classes should have access to that core class. Sounds exactly like I want the singleton approach, but I know that's a waste of time in PHP.
Here's an idea of what my code looks like at this point. I've tried to keep it as simple as I can.
class core {
public function __construct(){
...define some settings which are retrieve from the database
}
public function usefulFunction(){
}
}
class user extends core {
public function __construct(){
parent::__construct();
}
public function getUser($user_id){
$db = new database();
$user = /* Get user in assoc array from db */
$this->__setAll($user);
}
public static function getUsers(){
$db = new database();
$users = /* Get users from database in assoc array from db */
foreach($users as $user) {
$arrUsers[] = new self();
$arrUsers[]->__setAll($user);
}
return $arrUsers;
}
private function __setAll($attributes) {
foreach($attributes as $key => $value)
{
$this->__set($key, $value);
}
}
public function __set($key, $value) {
$this->$key = $value;
}
}
The other issue I'm having is efficiently using/sharing a database connection. Currently each method in a class requiring a database connection creates a new instance of the database, so on a page I might be doing this 5 or 10 times. Something like the dependency injection principle sounds much better.
Question Now if i'm passing the instance of the DB into the new user class, i know I need something like this...
class user{
protected $db;
public function __construct($db){
$this->db = $db;
}
... etc
}
$db = new database();
$user = new user($db);
... but when I want to run the static function users::getUsers() what is the best way to gain access to the database instance? Do i need to pass it as a variable in each static method? (there are many static methods in many classes). It doesn't seem like the best way of doing it but maybe there isn't another way.
Question If extending all of my classes off the core class as suggested in part 1, can I create an instance of the DB there and access that some how?
Question I also have various files containing functions (not oop) which are like helper files. What's the best way for these to access the database? Again i've been creating a new instance in each function. I don't really want to pass the db as a parameter to each one. Should I use globals, turn these helper files into classes and use dependency injection or something different all together?
I know there is lots of advice out there, but most info and tutorials on PHP are out of date and don't ever seem to cover something this complex...if you can call it complex?
Any suggestions on how to best layout my class structure. I know this seems like a lot, but surely this is something most developers face everyday. If you need any more info just let me know and thanks for reading!
You asked in a comment that I should elaborate why it is a bad idea. I'd like to highlight the following to answer that:
Ask yourself if you really need it.
Do design decisions for a need, not just because you can do it. In your case ask yourself if you need a core class. As you already have been asked this in comments you wrote that you actually do not really need it so the answer is clear: It is bad to do so because it is not needed and for not needing something it introduces a lot of side-effects.
Because of these side-effects you don't want to do that. So from zero to hero, let's do the following evolution:
You have two parts of code / functionality. The one part that does change, and the other part that is some basic functionality (framework, library) that does not change. You now need to bring them both together. Let's simplify this even and reduce the frame to a single function:
function usefulFunction($with, $four, $useful, $parameters)
{
...
}
And let's reduce the second part of your application - the part that changes - to the single User class:
class User extends DatabaseObject
{
...
}
I already introduced one small but important change here: The User class does not extend from Core any longer but from DatabaseObject because if I read your code right it's functionality is to represents a row from a database table, probably namely the user table.
I made this change already because there is a very important rule. Whenver you name something in your code, for example a class, use a speaking, a good name. A name is to name something. The name Core says absolutely nothing other that you think it's important or general or basic or deep-inside, or that it's molten iron. No clue. So even if you are naming for design, choose a good name. I thought, DatabaseObject and that was only a very quick decision not knowing your code even, so I'm pretty sure you know the real name of that class and it's also your duty do give it the real name. It deserves one, be generous.
But let's leave this detail aside, as it's only a detail and not that much connected to your general problem you'd like to solve. Let's say the bad name is a symptom and not the cause. We play Dr. House now and catalog the symptoms but just to find the cause.
Symptoms found so far:
Superfluous code (writing a class even it's not needed)
Bad naming
May we diagnose: Disorientation? :)
So to escape from that, always do what is needed and choose simple tools to write your code. For example, the easiest way to provide the common functions (your framework) is as easy as making use of the include command:
include 'my-framework.php';
usefuleFunction('this', 'time', 'really', 'useful');
This very simple tow-line script demonstrates: One part in your application takes care of providing needed functions (also called loading), and the other part(s) are using those (that is just program code as we know it from day one, right?).
How does this map/scale to some more object oriented example where maybe the User object extends? Exactly the same:
include 'my-framework.php';
$user = $services->store->findUserByID($_GET['id']);
The difference here is just that inside my-framework.php more is loaded, so that the commonly changing parts can make use of the things that don't change. Which could be for example providing a global variable that represents a Service Locator (here $services) or providing auto-loading.
The more simple you will keep this, the better you will progress and then finally you will be faced with real decisions to be made. And with those decisions you will more directly see what makes a difference.
If you want some more discussion / guidance for the "database class" please consider to take a read of the very good chapter about the different ways how to handle these in the book Patterns of Enterprise Application Architecture which somewhat is a long title, but it has a chapter that very good discusses the topic and allows you to choose a fitting pattern on how to access your database quite easily. If you keep things easy from the beginning, you not only progress faster but you are also much easier able to change them later.
However if you start with some complex system with extending from base-classes (that might even do multiple things at once), things are not that easily change-able from the beginning which will make you stick to such a decision much longer as you want to then.
You can start with an abstract class that handles all of your Database queries, and then constructs them into objects. It'll be easy to set yourself up with parameterized queries this way, and it will standardize how you interact with your database. It'll also make adding new object models a piece of cake.
http://php.net/manual/en/language.oop5.abstract.php
abstract class DB
{
abstract protected function table();
abstract protected function fields();
abstract protected function keys();
public function find()
{
//maybe write yourself a parameterized method that all objects will use...
global $db; //this would be the database connection that you set up elsewhere.
//query, and then pack up as an object
}
public function save()
{
}
public function destroy()
{
}
}
class User extends DB
{
protected function table()
{
//table name
}
protected function fields()
{
//table fields here
}
protected function keys()
{
//table key(s) here
}
//reusable pattern for parameterized queries
public static function get_user( $id )
{
$factory = new User;
$params = array( '=' => array( 'id' => $id ) );
$query = $factory->find( $params );
//return the object
}
}
You'll want to do your database connection from a common configuration file, and just leave it as a global variable for this pattern.
Obviously this is just scratching the surface, but hopefully it gives you some ideas.
Summarize all answers:
Do not use single "God" class for core.
It's better to use list of classes that make their jobs. Create as many class as you need. Each class should be responsible for single job.
Do not use singletones, it's old technique, that is not flexible, use dependecy injection container (DIC) instead.
First, the the best thing to do would be to use Singleton Pattern to get database instance.
class Db{
protected $_db;
private function __construct() {
$this->_db = new Database();
}
public static function getInstance() {
if (!isset(self::$_db)) {
self::$_db = new self();
}
return self::$_db;
}
}
Now you can use it like db::getInstance(); anywhere.
Secondly, you are trying to invent bicycle called Active Record pattern, in function __setAll($attributes).
In third, why do you wrote this thing in class that extends Core?
public function __construct(){
parent::__construct();
}
Finally, class names should be capitalized.
For years I have used global $var,$var2,...,$varn for methods in my application. I've used them for two main implementations:
Getting an already set class (such as DB connection), and passing info to functions that display to page.
Example:
$output['header']['log_out'] = "Log Out";
function showPage(){
global $db, $output;
$db = ( isset( $db ) ) ? $db : new Database();
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
There are, however, performance and security ramifications of doing it like this.
What alternative practice can I use that will maintain my functionality but improve design, performance, and/or security?
This is the first question I've ever asked on SO, so if you need clarifications please comment!
1. Globals. Works like a charm. Globals are hated thus my thoughts of not using it.
Well, globals are not just hated. They are hated for a reason. If you didn't run so far into the problems globals cause, fine. There is no need for you to refactor your code.
2. Define a constant in my config.php file.
This is actually just like a global, but with another name. You would spare the $ as well and to use the global at the beginning of functions. Wordpress did this for their configuration, I'd say this is more bad than using global variables. It makes it much more complicated to introduce seams. Also you can not assign an object to a constant.
3. Include the config file in the function.
I'd consider this as overhead. You segmentize the codebase for not much gain. The "global" here will become the name of the file you inlcude btw..
Taken these three thoughts of you and my comments to them into account I'd say: Unless you run into actual issues with some global variables, you can stick to them. Global then work as your service locator (configuration, database). Others do much more to create the same.
If you run into problems (e.g. you probably want to develop test-driven), I suggest you start with putting one part after the other under test and then you learn how to avoid the globals.
Dependency Injection
As inside comments it became clear you're looking for dependency injection, and if you can not edit the function parameter definition, you can - if you use objects - inject dependencies via the constructor or by using so called setter methods. In the following example code I'll do both which is for demonstration purposes only as you might have guessed, it's not useful to use both at once:
Let's say the configuration array is the dependency we would like to inject. Let's call it config and name the variable $config. As it is an array, we can type-hint it as array. first of all define the configuration in a include file maybe, you could also use parse_ini_file if you prefer the ini-file format. I think it's even faster.
config.php:
<?php
/**
* configuration file
*/
return array(
'db_user' => 'root',
'db_pass' => '',
);
That file then can just be required inside your application where-ever you want to:
$config = require('/path/to/config.php');
So it can be easily turned into an array variable somewhere in your code. Nothing spectacular so far and totally unrelated to dependency injection. Let's see an exemplary database class which needs to have the configuration here, it needs to have the username and the password otherwise it can't connect let's say:
class DBLayer
{
private $config;
public function __construct(array $config)
{
$this->setConfig($config);
}
public function setConfig(array $config)
{
$this->config = $config;
}
public function oneICanNotChange($paramFixed1, $paramFixed2)
{
$user = $this->config['db_user'];
$password = $this->config['db_pass'];
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
throw new DBLayerException('Connection failed: ' . $e->getMessage());
}
...
}
This example is a bit rough, but it has the two examples of dependency injection. First via the constructor:
public function __construct(array $config)
This one is very common, all dependencies the class needs to do it's work are injection at creation time. This also ensures that when any other method of that object is called, the object will be in a pre-determinable state - which is somewhat important for a system.
The second example is to have a public setter method:
public function setConfig(array $config)
This allows to add the dependency later, but some methods might need to check for things being available prior doing their job. E.g. if you could create the DBLayer object without providing configuration, the oneICanNotChange method could be called without that object having configuration and should had to deal with that (which is not shown in this example).
Service Locator
As you need to probably integrate code on the fly and you want your new code to be put under test with dependency injection and all that what's making our live easier, you might need to put this together with your ancient / legacy code. I think that part is tough. Dependency injection on it's own is pretty easy, but putting this together with old code is not that straight forward.
What I can suggest here is that you make one global variable that is the so called service locator. It contains a central point to fetch objects (or even arrays like your $config) from. It can be used then and the contract is that single variable name. So to remove globals we make use of a global variable. Sounds a bit counter-productive and it even is if your new code uses it too much as well. However, you need some tool to bring old and new together. So here is the most bare PHP service locator implementation I could imagine so far.
It consists of one Services object that offers all of your services, like the config from above. Because when a PHP script starts, we yet do not know if a service at all is needed (e.g. we might not run any database query, so we don't need to instantiate the database), it offers some lazy initialization feature as well. This is done by using factory-scripts that are just PHP files that setup the service and return it.
A first example: Let's say the function oneICanNotChange would not have been part of an object but just a simple function in the global namespace. We would not have been able to inject config dependency. This is where the Services Service Locator object comes in:
$services = new Services(array(
'config' => '/path/to/config.php',
));
...
function oneICanNotChange($paramFixed1, $paramFixed2)
{
global $services;
$user = $services['config']['db_user'];
$password = $services['config']['db_pass'];
...
As the example already shows, the Services object does map the string 'config' to the path of the PHP file that defines the $config array: /path/to/config.php. It uses the ArrayAccess interface than to expose that service inside the oneICanNotChange function.
I suggest the ArrayAccess interface here, because it's well defined and it shows that we have some dynamic character here. On the other hand it allows us the lazy initialization:
class Services implements ArrayAccess
{
private $config;
private $services;
public function __construct(array $config)
{
$this->config = $config;
}
...
public function offsetGet($name)
{
return #$this->services[$name] ?
: $this->services[$name] = require($this->config[$name]);
}
...
}
This exemplary stub just requires the factory scripts if it has not done so far, otherwise will return the scripts return value, like an array, an object or even a string (but not NULL which makes sense).
I hope these examples are helpful and show that not much code is needed to gain more flexibility here and punching globals out of your code. But you should be clear, that the service locator introduces global state to your code. The benefit is just, that it's easier to de-couple this from concrete variable names and to provide a bit more flexibility. Maybe you're able to divide the objects you use in your code into certain groups, of which only some need to become available via the service-locator and you can keep the code small that depends on the locator.
The alternative is called dependency injection. In a nutshell it means that you pass the data a function/class/object requires as parameters.
function showPage(Database $db, array &$output) {
...
}
$output['header']['log_out'] = "Log Out";
$db = new Database;
showPage($db, $output);
This is better for a number of reasons:
localizing/encapsulating/namespacing functionality (the function body has no implicit dependencies to the outside world anymore and vice versa, you can now rewrite either part without needing to rewrite the other as long as the function call doesn't change)
allows unit testing, since you can test functions in isolation without needing to setup a specific outside world
it's clear what a function is going to do to your code just by looking at the signature
There are, however, performance and security ramifications of doing it like this.
To tell you truth, there are no performance nor security ramifications. Using globals is a matter of cleaner code, and nothing more. (Well, okay, as long as you're not passing variables of tens of megabytes in size)
So, you have to think first, will alternatives make cleaner code for you, or not.
In matters of cleaner code, I'd be in fear if I see a db connection in the function called showPage.
One option that some people may frown upon is to create a singleton object responsible for holding the application state. When you want to access some shared "global" object you could make a call like: State::get()->db->query(); or $db = State::get()->db;.
I see this method as a reasonable approach as it saves having to pass around a bunch of objects all over the place.
EDIT:
Using this approach can help simplify the organization and readability of your application. For example, your state class could call the proper methods to initialize your database object and decouple its initialization from your showPage function.
class State {
private static $instance;
private $_db;
public function getDB() {
if(!isset($this->_db)){
// or call your database initialization code or set this in some sort of
// initialization method for your whole application
$this->_db = new Database();
}
return $this->_db;
}
public function getOutput() {
// do your output stuff here similar to the db
}
private function __construct() { }
public static function get() {
if (!isset(self::$instance)) {
$className = __CLASS__;
self::$instance = new State;
}
return self::$instance;
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup() {
trigger_error('Unserializing is not allowed.', E_USER_ERROR);
}
}
and your show page function could be something like this:
function showPage(){
$output = State::get()->getOutput();
$output['header']['title'] = State::get()->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
An alternative to using a singleton object is to pass the state object to your various functions, this allows you to have alternative "states" if your application gets complicated and you will only need to pass around a single state object.
function showPage($state){
$output = $state->getOutput();
$output['header']['title'] = $state->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
$state = new State; // you'll have to remove all the singleton code in my example.
showPage($state);
function showPage(&$output, $db = null){
$db = is_null( $db ) ? new Database() : $db;
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
and
$output['header']['log_out'] = "Log Out";
showPage($output);
$db =new Database();
showPage($output,$db);
Start designing your code in OOP, then you can pass config to the constructor. You could also encapsulate all your functions into a class.
<?php
class functions{
function __construct($config){
$this->config = $config;
}
function a(){
//$this->config is available in all these functions/methods
}
function b(){
$doseSomething = $this->config['someKey'];
}
...
}
$config = array(
'someKey'=>'somevalue'
);
$functions = new functions($config);
$result = $functions->a();
?>
Or if you cant refactor the script, loop through the config array and define constants.
foreach($config as $key=>$value){
define($key,$value);
}
I am not sure if this is totally the wrong thing to do, so I am looking for a bit of advice.
I have set up a database class with the constructor establishing a PDO connection to a MySQL database.
I've been looking at singletons and global variables, but there always seems to be someone who recommends against either/or.
I'm experimenting with a user class which extends the database class, so I can call upon the PDO functions/methods but maintain separate user class code. Is this a stupid thing to do?
You should generally pass a connection into your user, so your user class would take a database type object into its constructor and then use that database object to execute queries against the database. That way your data access logic remains separate from your business logic. This is called composition, as opposed to what you're talking about, which is inhertance.
If you really wanted to be technical, it would be best to have a user object with nothing but public variables, and then you would use a 'service' to implement your business logic.
class UserService implements IUserService
{
private $_db;
function __construct(IDb $db) {
$this->_db = db;
}
function GetAllUsers() {
$users = Array();
$result = $this->_db->Query("select * from user")
foreach($result as $user) {
//Would resolve this into your user domain object here
users[] = $user;
}
return users;
}
}
Well, ask yourself if User is a special case of Database. I'm not sure how others perceive it, but I would be kind of offended. I think what you need is to read about the Liskov substitution principle.
As for solving your "people tell me that globals are bad" issue, here are two videos you should watch:
The Clean Code Talks - Don't Look For Things!
The Clean Code Talks - Global State and Singletons
The idea behind class extensions in OOP is for child classes to be related to the parent classes. For instance, a school might have a Person class with extension classes of Faculty and Students. Both of the child classes are people, so it makes sense for them to extend the Person class. But a User is not a type of Database, so some people might get upset if you make it an extension.
Personally, I would send the database object as an argument to the User class in the constructor and simply assign that object to a class property. For instance:
class User
{
protected $db;
function __construct($username, $password, $db)
{
//some code...
$this->db = $db;
}
}
Alternatively, though some might yell at you for it, you can use the global keyword to inherit a variable in the global scope for use within your methods. The downside is that you would then have to declare it global in every method that needs it, or you could do:
class User
{
protected $db;
function __construct($username, $password)
{
global $db;
//some code...
$this->db = $db;
}
}
But in answer to your question, no I don't think you should make User an extension of Database; even though it would do what you need, it isn't a proper OOP practice.
It is pretty simple according to the definition of an object. It is the encapsulation of data and the operation which is performed on that data so if we only consider the theoretical point of view it would leads us in pleasurable environment.
My suggestion would be to create an abstract data access class with the generalized basic crud operations and a simple query execution using either PDO, ADO or some other database abstraction library. Now use this class as a parent for most of your model classes like the User.
Now the basic CRUD is provided by the abstract data access class and you can write the behavior specific to the user object like getting all posts for the user by consuming the simple query interface of the abstract parent class.
This approach will bring more modularity in term of coupling functionality and more readability and reuse-ability.
I don't see anything wrong with it for specific cases. You could use it for something as simple as wrapping a user's DB credentials in an object so they don't have to specify them everywhere the DB object is used.
$db = new UserDB();
would be a bit nicer than
$db = new StandarDB($username, $password, $default_db);
For years I have used global $var,$var2,...,$varn for methods in my application. I've used them for two main implementations:
Getting an already set class (such as DB connection), and passing info to functions that display to page.
Example:
$output['header']['log_out'] = "Log Out";
function showPage(){
global $db, $output;
$db = ( isset( $db ) ) ? $db : new Database();
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
There are, however, performance and security ramifications of doing it like this.
What alternative practice can I use that will maintain my functionality but improve design, performance, and/or security?
This is the first question I've ever asked on SO, so if you need clarifications please comment!
1. Globals. Works like a charm. Globals are hated thus my thoughts of not using it.
Well, globals are not just hated. They are hated for a reason. If you didn't run so far into the problems globals cause, fine. There is no need for you to refactor your code.
2. Define a constant in my config.php file.
This is actually just like a global, but with another name. You would spare the $ as well and to use the global at the beginning of functions. Wordpress did this for their configuration, I'd say this is more bad than using global variables. It makes it much more complicated to introduce seams. Also you can not assign an object to a constant.
3. Include the config file in the function.
I'd consider this as overhead. You segmentize the codebase for not much gain. The "global" here will become the name of the file you inlcude btw..
Taken these three thoughts of you and my comments to them into account I'd say: Unless you run into actual issues with some global variables, you can stick to them. Global then work as your service locator (configuration, database). Others do much more to create the same.
If you run into problems (e.g. you probably want to develop test-driven), I suggest you start with putting one part after the other under test and then you learn how to avoid the globals.
Dependency Injection
As inside comments it became clear you're looking for dependency injection, and if you can not edit the function parameter definition, you can - if you use objects - inject dependencies via the constructor or by using so called setter methods. In the following example code I'll do both which is for demonstration purposes only as you might have guessed, it's not useful to use both at once:
Let's say the configuration array is the dependency we would like to inject. Let's call it config and name the variable $config. As it is an array, we can type-hint it as array. first of all define the configuration in a include file maybe, you could also use parse_ini_file if you prefer the ini-file format. I think it's even faster.
config.php:
<?php
/**
* configuration file
*/
return array(
'db_user' => 'root',
'db_pass' => '',
);
That file then can just be required inside your application where-ever you want to:
$config = require('/path/to/config.php');
So it can be easily turned into an array variable somewhere in your code. Nothing spectacular so far and totally unrelated to dependency injection. Let's see an exemplary database class which needs to have the configuration here, it needs to have the username and the password otherwise it can't connect let's say:
class DBLayer
{
private $config;
public function __construct(array $config)
{
$this->setConfig($config);
}
public function setConfig(array $config)
{
$this->config = $config;
}
public function oneICanNotChange($paramFixed1, $paramFixed2)
{
$user = $this->config['db_user'];
$password = $this->config['db_pass'];
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
throw new DBLayerException('Connection failed: ' . $e->getMessage());
}
...
}
This example is a bit rough, but it has the two examples of dependency injection. First via the constructor:
public function __construct(array $config)
This one is very common, all dependencies the class needs to do it's work are injection at creation time. This also ensures that when any other method of that object is called, the object will be in a pre-determinable state - which is somewhat important for a system.
The second example is to have a public setter method:
public function setConfig(array $config)
This allows to add the dependency later, but some methods might need to check for things being available prior doing their job. E.g. if you could create the DBLayer object without providing configuration, the oneICanNotChange method could be called without that object having configuration and should had to deal with that (which is not shown in this example).
Service Locator
As you need to probably integrate code on the fly and you want your new code to be put under test with dependency injection and all that what's making our live easier, you might need to put this together with your ancient / legacy code. I think that part is tough. Dependency injection on it's own is pretty easy, but putting this together with old code is not that straight forward.
What I can suggest here is that you make one global variable that is the so called service locator. It contains a central point to fetch objects (or even arrays like your $config) from. It can be used then and the contract is that single variable name. So to remove globals we make use of a global variable. Sounds a bit counter-productive and it even is if your new code uses it too much as well. However, you need some tool to bring old and new together. So here is the most bare PHP service locator implementation I could imagine so far.
It consists of one Services object that offers all of your services, like the config from above. Because when a PHP script starts, we yet do not know if a service at all is needed (e.g. we might not run any database query, so we don't need to instantiate the database), it offers some lazy initialization feature as well. This is done by using factory-scripts that are just PHP files that setup the service and return it.
A first example: Let's say the function oneICanNotChange would not have been part of an object but just a simple function in the global namespace. We would not have been able to inject config dependency. This is where the Services Service Locator object comes in:
$services = new Services(array(
'config' => '/path/to/config.php',
));
...
function oneICanNotChange($paramFixed1, $paramFixed2)
{
global $services;
$user = $services['config']['db_user'];
$password = $services['config']['db_pass'];
...
As the example already shows, the Services object does map the string 'config' to the path of the PHP file that defines the $config array: /path/to/config.php. It uses the ArrayAccess interface than to expose that service inside the oneICanNotChange function.
I suggest the ArrayAccess interface here, because it's well defined and it shows that we have some dynamic character here. On the other hand it allows us the lazy initialization:
class Services implements ArrayAccess
{
private $config;
private $services;
public function __construct(array $config)
{
$this->config = $config;
}
...
public function offsetGet($name)
{
return #$this->services[$name] ?
: $this->services[$name] = require($this->config[$name]);
}
...
}
This exemplary stub just requires the factory scripts if it has not done so far, otherwise will return the scripts return value, like an array, an object or even a string (but not NULL which makes sense).
I hope these examples are helpful and show that not much code is needed to gain more flexibility here and punching globals out of your code. But you should be clear, that the service locator introduces global state to your code. The benefit is just, that it's easier to de-couple this from concrete variable names and to provide a bit more flexibility. Maybe you're able to divide the objects you use in your code into certain groups, of which only some need to become available via the service-locator and you can keep the code small that depends on the locator.
The alternative is called dependency injection. In a nutshell it means that you pass the data a function/class/object requires as parameters.
function showPage(Database $db, array &$output) {
...
}
$output['header']['log_out'] = "Log Out";
$db = new Database;
showPage($db, $output);
This is better for a number of reasons:
localizing/encapsulating/namespacing functionality (the function body has no implicit dependencies to the outside world anymore and vice versa, you can now rewrite either part without needing to rewrite the other as long as the function call doesn't change)
allows unit testing, since you can test functions in isolation without needing to setup a specific outside world
it's clear what a function is going to do to your code just by looking at the signature
There are, however, performance and security ramifications of doing it like this.
To tell you truth, there are no performance nor security ramifications. Using globals is a matter of cleaner code, and nothing more. (Well, okay, as long as you're not passing variables of tens of megabytes in size)
So, you have to think first, will alternatives make cleaner code for you, or not.
In matters of cleaner code, I'd be in fear if I see a db connection in the function called showPage.
One option that some people may frown upon is to create a singleton object responsible for holding the application state. When you want to access some shared "global" object you could make a call like: State::get()->db->query(); or $db = State::get()->db;.
I see this method as a reasonable approach as it saves having to pass around a bunch of objects all over the place.
EDIT:
Using this approach can help simplify the organization and readability of your application. For example, your state class could call the proper methods to initialize your database object and decouple its initialization from your showPage function.
class State {
private static $instance;
private $_db;
public function getDB() {
if(!isset($this->_db)){
// or call your database initialization code or set this in some sort of
// initialization method for your whole application
$this->_db = new Database();
}
return $this->_db;
}
public function getOutput() {
// do your output stuff here similar to the db
}
private function __construct() { }
public static function get() {
if (!isset(self::$instance)) {
$className = __CLASS__;
self::$instance = new State;
}
return self::$instance;
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup() {
trigger_error('Unserializing is not allowed.', E_USER_ERROR);
}
}
and your show page function could be something like this:
function showPage(){
$output = State::get()->getOutput();
$output['header']['title'] = State::get()->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
An alternative to using a singleton object is to pass the state object to your various functions, this allows you to have alternative "states" if your application gets complicated and you will only need to pass around a single state object.
function showPage($state){
$output = $state->getOutput();
$output['header']['title'] = $state->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
$state = new State; // you'll have to remove all the singleton code in my example.
showPage($state);
function showPage(&$output, $db = null){
$db = is_null( $db ) ? new Database() : $db;
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
and
$output['header']['log_out'] = "Log Out";
showPage($output);
$db =new Database();
showPage($output,$db);
Start designing your code in OOP, then you can pass config to the constructor. You could also encapsulate all your functions into a class.
<?php
class functions{
function __construct($config){
$this->config = $config;
}
function a(){
//$this->config is available in all these functions/methods
}
function b(){
$doseSomething = $this->config['someKey'];
}
...
}
$config = array(
'someKey'=>'somevalue'
);
$functions = new functions($config);
$result = $functions->a();
?>
Or if you cant refactor the script, loop through the config array and define constants.
foreach($config as $key=>$value){
define($key,$value);
}