Reputation: 377
I have been working on moving over to OOP in PHP. I have reading explanations on php.net, but I was hoping I could get some specific answers here.
I tried to create the following example to illustrate my question. Say I have "Database", "Products", and "Users" classes, and I want to display products if a user has access.
So I call the "Products" class "showProducts()" function, which in turn creates an instance of the "User" class, which creates an instance of the "Database" object and checks the users access level.
If the user has access, then the "showProducts()" function creates another instance of the "Database" object, and queries the database.
class Database{
public function query(){
//runs query here
}
public function __construct() {
//sets up connection here
}
}
class User{
public function checkAccess(){
$db = new Database();
$db->query( //pass in query to check access )
//does stuff, then returns true or false
}
}
class Products{
public function showProducts(){
$user = new User();
if($user->checkAccess())
$db = new Database();
$db->query( //pass in query to get products )
}
}
I was hoping someone could illustrate how to do this the proper way.
I would like to have some sort of controller class, that creates one "Database" object, that is available to all of the classes that need to access it, without having to create multiple instances of the "Database" object. I would like the same thing with the users class, so there is one $users object that all the classes can access, without having to create a new object every time I need to use something in the "User" class.
I apologize if my question is not clear, and thanks in advance for any responses!!
Thanks to everybody for the replies!
Upvotes: 7
Views: 10954
Reputation: 2614
To make one object for all your code use Singleton pattern:
class Database{
private $db_descriptor;
private function __construct(){
/* connect and other stuff */
}
public static function getInstance(){
static $instance;
if($instance === null){
$instance = new self();
}
return $instance;
}
}
And you can use the same technique with users, i say more with php 5.4 you can use 1 trait for singleton pattern. One last tip: when you work with database and other heavy things use technique called lazy initialization. When you improve your OOP skills look at Doctrine Project they use that techniques a lot!
Upvotes: 0
Reputation: 1355
When moving form procedural to Object Oriented programming you should grasp more then just how to build classes. OOP is not writing classes, its about following best practices, principles and patterns in OOP.
You should not instantiate new objects inside another, you should give the User object, his Database object that User depends on, through constructor, or setter method. That is called Dependency Injection. The goal is to give objects to a class that needs them through constructor or setter method. And they should be instanciated from outside of that class, so its easier to configure class. And when building a class you want its easy to see what dependencies that class have. You can read about Inversion of Control principle here: IoC
So then your code would look like this:
<?php
// User object that depends on Database object, and expects it in constructor.
class User
{
protected $database;
public function __construct($database)
{
$this->database = $database;
}
// -- SNIP --
}
?>
Now to use that user class you do this:
<?php
$database = new Database($connParams);
$user = new User($database);
?>
You can also use Dependency Injection using setter methods to set dependencies, but Il let you google that for yourself :)
Thats it, joust read about Inversion of Controll principle, and about Dependency Injection and Dependency Injection Containers, these are the best ways to manage classes.
I have seen lots of PHP code that is "OOP" and in fact they are only using Classes as functionality namespaces :) So joust learn about OOP principles and patterns.
Have fun! :)
Upvotes: 12
Reputation: 70933
Don't instantiate objects inside your constructors or other methods. Pass them as parameter, preferably inside a different class known as factory. This will make it easy to test your code, but also make it easy to create the objects.
Also, don't try to use singletons. This is the object oriented version of "global variables", and you do not want to use global variables. It makes testing of your code really hard, nearly impossible.
Watch this video http://www.youtube.com/watch?v=-FRm3VPhseI to understand why it is bad to use singletons. Especially the CreditCard example at 19:00 is worth watching.
If you really want to do it state-of-the-art, have a look at the concept of "dependency injection". Essentially, passing stuff that is needed from outside into a class is the whole secret, but there are frameworks that do this for you automatically, so you do not have to write a factory yourself anymore. These are called "Dependency Injection Container" or "DIC".
Upvotes: 2