I'm looking for some feedback on the following:
I currently have two classes, which are being used in my PHP application.
A database connection class, which is currently using MySQL (but switching to PDO).
Another class (with several functions) which requires database functionality.
I'm looking for the best way to design this, I've read up on singletons (with very mixed reviews), read examples where objects were simply declared as new for each method (class functions), and examples where the connection was assigned to a private variable as part of a __constructor method for each class (then referenced with $this->).
So, how does everyone else do it? I hope you will be kind enough to perhaps give an example, and also welcome opinions on what others have read please.
I've got 2 separate classes, in two separate files. I want to keep clean code, reduce unnecessary overhead on the DB, and avoid anything that could be considered outdated (such as globals).
The Database class, which is responsible for connecting, should be the one connecting to the database, creating the new PDO instance, and saving it to a field in itself.
class Database {
private $pdo;
public __construct() {
$this->pdo = new PDO(...);
}
}
The second class, which doesn't care where the DB connection is from, it just needs it to work should be injected with the Database class:
class WorkerClass {
private $db;
public __construct(Database $db) {
$this->db = $db;
}
}
I've always created it in the __constructor and then used $this-> to get at it. This should work for your needs but I'd encourage you to play around with different styles and see what one works best.
I would NOT create a new object with new every time, unless you have a very good reason to.
Related
Moving from C#/C++ to PHP OOP has proven a bit problematic as I am not sure it is standard to design the code layout in the same manner. As that is the case, I am curious if the following would be considered problematic or wrong when it comes to PHP.
CDeviceManager class (1 initiated)
CDevice class
Keep a private array of CDevice in the CDeviceManager class
Use public methods to fetch devices, search devices, etc.
The most problematic question however is populating each CDevice from a MySQL Database. Would it be safe to include my Database class directly into CDeviceManager and Populate CDevice Array in CDeviceManager Construct?
A lot of what I have read says it is smart to separate the business logic from the view, where I feel this method would do just that. I have not seen many other projects that appear to use this approach though, why I am worried I may be missing something.
It would be best to separate your business logic from data storage system. I recommend using dependency injection to get your job done. The exact implementation would depend on your needs (and project size), but to get an idea here's would be what I would do:
class CDeviceManager
{
private $db; //holder for your database
private $cdevices = array();
//more properties here
public function __construct(Database $db)
{
$this->db = $db; //database connection has now been injected into your class
}
//more methods here
}
Then somewhere along the line when you create your CDeviceManager object you can inject the database connection.
$cdm = new CDeviceManager( new Database(...) );
Your Database class would likely be a wrapper for PDO or MySQLi or whatever database API you would want to use. You could also go farther and have CDeviceManager implement some kind of interface that relate to various CRUD functions in your database. Best part though, is you can test this a whole lot easier because now you can swap out your database connection with a mock/test database so you don't inadvertently screw up your production database.
$cdm = new CDeviceManager( new MockDatabase(...) );
or
$testdb = new TestDatabase(...);
$cdm = new CDeviceManager( $testdb );
So yes, in the end it is good to separate the database connection from your domain models. Some recommend going even farther and making sure that your domain models are completely ignorant to the storage mechanism in general, this way you could be flexible on your storage system/persistence layer. E.g:
$cdm = new CDeviceManager( new FileRetriever() ); //Maybe you are storing stuff in a flat file
Hope that helps clear things up a little bit.
I'm fairly new to OOP PHP and am having trouble with getting a couple of classes to work nicely together. I'm using a database abstract class to do all the grunt work of talking to the database and that is all fine, and I can extend it with another class with the methods to make specific actions. The database class has an include_once to read in the config settings for the database.
Where I am confused is if I need to use a 2nd class to access the database on the same page, I need to reference a 2nd config file that has the same settings.
Example: I have a products class for a site I'm building and it is working fine. I wanted to use a 2nd class to control the actual shopping cart side of things, but when I try and extend the database class with the Cart class the page fails unless I override which config file it needs to reference.
Why do I need separate config files for each class and is there a way around this? It seems silly that I should need as many config files as there are classes that interact with the database.
Thanks for your help.
Jon
* Extra Info *
Sorry guys, Everything is in the same database. Here is some sample code.
All config files are like this:
$DB_HOST = "localhost";
$DB_USER = "abcdef";
$DB_PASS = "123456";
$DB_DATABASE = "newdb_name";
then I override the config file which it needs to pull in but doing this in the sub classes:
function __construct()
{
$this->conffile = "db_conf1.php";
parent::__construct();
}
and change the $this->conffile for each new sub class.
I'm using a database abstract class to do all the grunt work of talking to the database and that is all fine, and I can extend it with another class with the methods to make specific actions. The database class has an include_once to read in the config settings for the database.
This is a bad design. If you need to use two of these classes together in the same script, you're going to end up w--
Where I am confused is if I need to use a 2nd class to access the database on the same page
Phew, you got it already.
You generally only want one database connection per page. This generally means only one database object. You have two good options in PHP to deal with this.
The first has a fancy name: "Dependency Injection." In DI, your objects require some external resource to work. They receive this resource during construction.
In other words, you pass your database object in the constructor.
class Foo {
protected $db;
public function __construct($other, $args, $db) {
$this->db = $db;
}
}
This way, you still get the convenience of referencing the database from within your object without having to make it too intermingled.
The other option also has a fancy name: the "Registry Pattern." Registries act as gateways to "well-known" classes and instances. They're basically look-up tables, allowing you to make your program depend on data that will be present in the Registry rather than hard-coding class names or using globals.
Or, in other words, it's just a global hash with a special name.
Doing it right requires a class. This blog post from 2009 is an interesting starting point because it deals exactly with the problem of what to do with a database adapter. I'll omit example code here, as the blog post does a decent job of explaining itself.
There is a third option, of course, and it's the worst, yet most common in PHP land: assigning the database object to a global, then referencing the global as needed. It's quick, it's dirty, it usually works... but can make maintenance difficult, and can make automated testing impossible to do correctly. Don't do it.
You should remove the dependency on the config file from the database class and pass the variables you need into the database constructor e.g.,
class Database {
public function __construct($host, $user, $pass, $dbname, $port) {
// create connection
}
//...
}
Put the info for both your databases into one config file and create your database objects like this:
include_once 'config.php';
$db1 = new Database($host1, $user1, $pass1, $dbname1, $port1);
$db2 = new Database($host2, $user2, $pass2, $dbname2, $port2);
I have an includes.php page that I load at the start of every page of my website.
As I develop the website, the number of classes that I am using is growing.
So I end up with something like this:
$db = new DB($config);
$login = new Login($db, $config);
$form = new Form($db, $config);
And the list goes on and on.
I have two questions about this practice:
First, Considering I might not be using a class at a certain page (I might not have a $form on every single page), how much does it really matter, performance-wise, to load this class every time any given page is loaded?
Second, you may have noticed that I am passing the class instance $db to all the other classes, as well as a variable $config. In the php code of every class, I do something like this:
public $db;
public $config;
public function __construct($db, $config, $smarty){
$this->db = $db;
$this->config = $config;
}
then in the class methods, I address the database and config files with 'this' as such:
public function myfunction(){
$this->db;
$this->config;
}
When should I use 'extends' rather than passing $db to the class, assuming every class uses the db? Does passing $db to every class hurt in any way in terms of performance?
Thanks!
When should I use 'extends' rather
than passing $db to the class,
assuming every class uses the db?
When it makes sense -- and only when it does !
You have at least two things to consider :
"class A extends B" kind of means "class A **is a** B"
more clearly, a Car is a MotorVehicule ; a MotorVehicule is a Vehicule ; a Bus is a MotorVehicule ; a Bicycle is a Vehicule
however, a Ball is not a Vehicule
In your case, a Form is definitly not a DataBase ! Nor is a Login
In PHP, a class can only extend one class
You can not have something being both a Vehicule and an Animal
But a Car is a MotorVehicule, which, itself, is a Vehicule :-)
In the case of a Database object (in your case, it's more a connection to a DB), mosts of your classes will not themselves "be" a database connection. So, they shouldn't extend that class.
However, they are using a DB connection (a Form "has a" DB connection) ; so, they should have a property representing that DB connection. That's what you are doing.
Instead of passing $db to each constructor, you might use
either the Singleton design pattern
or the Registry design pattern
or some kind of global variable, but that's almost the same... just being worse (not OOP and all that) !
But passing the $db object is great for unit-testing, mock objects, and all that...
I think it could be considered as being the Dependancy Injection design pattern, btw (not sure, but looks like it)
About loading lots of classes, other people gave answers :
Use autoloading if you can
Use an opcode cache, like APC, if you can
Both of those are great suggestions that you should take into consideration ;-)
One last thing :
Does passing $db to every class hurt
in any way in terms of performance?
Maybe it does a little bit ; but, honnestly, except if you are google and have millions of users... who cares ?
If you are doing a couple of DB queries, those will take LOTS of time, comparing to passing one more parameter to even a dozen methods !
So, the small amount of time used passing paremeters can probably be neglected :-)
Have you tried something like this?
function __autoload($class_name) {
require_once("includes/php/class." . $class_name . ".php");
}
So it only loads the class name when the class name is encountered.
(Change the path to suit your php classes... mine are like class.Object.php, with the class name "Object").
Why not include only the files that need to be included? Also, try to instantiate only those objects that you need where you need them. As it is, your includes.php is doing a lot of instantiation that you might not need all the time.
If $db is passed as a reference, it shouldn't affect performance. (I don't know much about PHP5, but with PHP4 there was a concept of reference with the '&' modifier.)
If loading and parsing the script files becomes a bottleneck you can use a bytecode cache like apc to speed up this part of the life cycle.
I'm not sure how exactly you'd want to use inheritance ('extends') here. You could use it to define the two fields $db and $config, but otherwise it would not change much.
Also, it might limit you when you actually do want to inherit something useful from another class.
Depending on your design, you might want to consider making $config global. Is there a situation where there is more than 1 configuration active at the same time? It probably wouldn't be a good idea to introduce a global $db variable however. It's conceivable that you might need more than one database connection at the same time for instance.
I recently took my Db initiating code out of the __construct of my Page class and placed it just after I initiate the Page class. I removed it from within the Page class because I want to be able to access it from anywhere (other classes for example). It also takes server, username, password and database arguments to it when initiated, and I don't wish to enter these every time.
Is there a way I can access it from under the Page class now? I've tried a few methods, even global (which I have been told is an awful way to do things) and so far no avail. I am still new to OO, but I am teaching myself as best as I can.
Should I make it a static class? Will this affect the lazy connector to the Db I have setup?
Any help would be much appreciated.
Thank you
[EDIT]
Similar Question: Global or Singleton for database connection?
A global of some sort (Be that global variables, singleton or some other variant) is an improvement over your previous approach, and as such you're on the right track. Generally speaking though, you should try to minimise the scope of program state (For a number of reasons, which I won't get into here). Having a global variable is in conflict with this principle. There are different solutions to this problem, but the most powerful and often overlooked approach, is to use inversion of control; Instead of obtaining a dependency, your class should receive it. For example, let's say you currently have this
class EditUserController {
function saveUser() {
$db = Database::GetInstance();
$db->execute("update users set ...", ...);
}
}
You could change this into:
class EditUserController {
function saveUser($db) {
$db->execute("update users set ...", ...);
}
}
Passing dependencies on the function-parameter level can be a bit unwieldy though, so a compromise could be to pass it on a per-object level:
class EditUserController {
protected $db;
function __construct($db) {
$this->db = $db;
}
function saveUser() {
$this->db->execute("update users set ...", ...);
}
}
This is a fairly common pattern in OO programming. In addition to being more practical than passing in function parameters, it has the additional benefit of separating construction (Where shared dependencies are wired up to each other), from runtime (Where they are used). This makes a lot of things simpler.
Global variables do have a use, and this would be one of them. Unless it's likely that you're going to be needing multiple database connections, (or even still), then I don't see a problem with setting up a global $db object.
An alternative way is to have a static "Factory" class which you can use to get the object. In Joomla 1.5, the way you access the DB object is like this:
$db =& JFactory::getDBO();
the getDBO function checks if the DB object has been created: if it has, return a reference to it, otherwise connect and initialise, and then return it.
This could equally apply to other "could-be-made-global" objects, like the current User object.
The singleton method was created to make sure there was only one instance of any class. But, because people use it as a way to shortcut globalizing, it becomes known as lazy and/or bad programming.
What is the benefit of using singleton instead of global for database connections in PHP? I feel using singleton instead of global makes the code unnecessarily complex.
Code with Global
$conn = new PDO(...);
function getSomething()
{
global $conn;
.
.
.
}
Code with Singleton
class DB_Instance
{
private static $db;
public static function getDBO()
{
if (!self::$db)
self::$db = new PDO(...);
return self::$db;
}
}
function getSomething()
{
$conn = DB_Instance::getDBO();
.
.
.
}
If there's a better way of initializing database connection other than global or singleton, please mention it and describe the advantages it have over global or singleton.
I know this is old, but Dr8k's answer was almost there.
When you are considering writing a piece of code, assume it's going to change. That doesn't mean that you're assuming the kinds of changes it will have hoisted upon it at some point in the future, but rather that some form of change will be made.
Make it a goal mitigate the pain of making changes in the future: a global is dangerous because it's hard to manage in a single spot. What if I want to make that database connection context aware in the future? What if I want it to close and reopen itself every 5th time it was used. What if I decide that in the interest of scaling my app I want to use a pool of 10 connections? Or a configurable number of connections?
A singleton factory gives you that flexibility. I set it up with very little extra complexity and gain more than just access to the same connection; I gain the ability to change how that connection is passed to me later on in a simple manner.
Note that I say singleton factory as opposed to simply singleton. There's precious little difference between a singleton and a global, true. And because of that, there's no reason to have a singleton connection: why would you spend the time setting that up when you could create a regular global instead?
What a factory gets you is a why to get connections, and a separate spot to decide what connections (or connection) you're going to get.
Example
class ConnectionFactory
{
private static $factory;
private $db;
public static function getFactory()
{
if (!self::$factory)
self::$factory = new ConnectionFactory(...);
return self::$factory;
}
public function getConnection() {
if (!$this->db)
$this->db = new PDO(...);
return $this->db;
}
}
function getSomething()
{
$conn = ConnectionFactory::getFactory()->getConnection();
.
.
.
}
Then, in 6 months when your app is super famous and getting dugg and slashdotted and you decide you need more than a single connection, all you have to do is implement some pooling in the getConnection() method. Or if you decide that you want a wrapper that implements SQL logging, you can pass a PDO subclass. Or if you decide you want a new connection on every invocation, you can do do that. It's flexible, instead of rigid.
16 lines of code, including braces, which will save you hours and hours and hours of refactoring to something eerily similar down the line.
Note that I don't consider this "Feature Creep" because I'm not doing any feature implementation in the first go round. It's border line "Future Creep", but at some point, the idea that "coding for tomorrow today" is always a bad thing doesn't jive for me.
I'm not sure I can answer your specific question, but wanted to suggest that global / singleton connection objects may not be the best idea if this if for a web-based system. DBMSs are generally designed to manage large numbers of unique connections in an efficient manner. If you are using a global connection object, then you are doing a couple of things:
Forcing you pages to do all database
connections sequentially and killing
any attempts at asyncronous page
loads.
Potentially holding open locks on
database elements longer than
necessary, slowing down overall
database performance.
Maxing out the total number of
simultaneous connections your
database can support and blocking
new users from accessing the
resources.
I am sure there are other potential consequences as well. Remember, this method will attempt to sustain a database connection for every user accessing the site. If you only have one or two users, not a problem. If this is a public website and you want traffic then scalability will become an issue.
[EDIT]
In larger scaled situations, creating new connections everytime you hit the datase can be bad. However, the answer is not to create a global connection and reuse it for everything. The answer is connection pooling.
With connection pooling, a number of distinct connections are maintained. When a connection is required by the application the first available connection from the pool is retrieved and then returned to the pool once its job is done. If a connection is requested and none are available one of two things will happen: a) if the maximum number of allowed connection is not reached, a new connection is opened, or b) the application is forced to wait for a connection to become available.
Note: In .Net languages, connection pooling is handled by the ADO.Net objects by default (the connection string sets all the required information).
Thanks to Crad for commenting on this.
The singleton method was created to make sure there was only one instance of any class. But, because people use it as a way to shortcut globalizing, it becomes known as lazy and/or bad programming.
Therefore, I would ignore global and Singleton since both are not really OOP.
What you were looking for is dependency injection.
You can check on easy to read PHP based information related to dependency injection (with examples) at http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection
Both patterns achieve the same net effect, providing one single access point for your database calls.
In terms of specific implementation, the singleton has a small advantage of not initiating a database connection until at least one of your other methods requests it. In practice in most applications I've written, this doesn't make much of a difference, but it's a potential advantage if you have some pages/execution paths which don't make any database calls at all, since those pages won't ever request a connection to the database.
One other minor difference is that the global implementation may trample over other variable names in the application unintentionally. It's unlikely that you'll ever accidentally declare another global $db reference, though it's possible that you could overwrite it accidentally ( say, you write if($db = null) when you meant to write if($db == null). The singleton object prevents that.
If you're not going to use a persistent connection, and there are cases for not doing that, I find a singleton to be conceptually more palatable than a global in OO design.
In a true OO architecture, a singleton is more effective than creating a new instance the object each time.
On the given example, I see no reason to use singletons. As a rule of thumb if my only concern is to allow a single instance of an object, if the language allows it, I prefer to use globals
In general I would use a singleton for a database connection... You don't want to create a new connection everytime you need to interact to the database... This might hurt perfomance and bandwidth of your network... Why create a new one, when there's one available... Just my 2 cents...
RWendi
It is quite simple. Never use global OR Singleton.
As advice both singleton and global are valid and can be joined within the same system, project, plugin, product, etc ...
In my case, I make digital products for web (plugin).
I use only singleton in the main class and I use it by principle. I almost do not use it because I know that the main class will not instantiate it again
<?php // file0.php
final class Main_Class
{
private static $instance;
private $time;
private final function __construct()
{
$this->time = 0;
}
public final static function getInstance() : self
{
if (self::$instance instanceof self) {
return self::$instance;
}
return self::$instance = new self();
}
public final function __clone()
{
throw new LogicException("Cloning timer is prohibited");
}
public final function __sleep()
{
throw new LogicException("Serializing timer is prohibited");
}
public final function __wakeup()
{
throw new LogicException("UnSerializing timer is prohibited");
}
}
Global use for almost all the secondary classes, example:
<?php // file1.php
global $YUZO;
$YUZO = new YUZO; // YUZO is name class
while at runtime I can use Global to call their methods and attributes in the same instance because I do not need another instance of my main product class.
<?php // file2.php
global $YUZO;
$YUZO->method1()->run();
$YUZO->method2( 'parameter' )->html()->print();
I get with the global is to use the same instance to be able to make the product work because I do not need a factory for instances of the same class, usually the instance factory is for large systems or for very rare purposes.
In conclusion:, you must if you already understand well that is the anti-pattern Singleton and understand the Global, you can use one of the 2 options or mix them but if I recommend not to abuse since there are many programmers who are very exception and faithful to the programming OOP, use it for main and secondary classes that you use a lot within the execution time. (It saves you a lot of CPU). 😉