What is the best way to share objects between other classes?
For example; a "database" object with functions that are required by the "article" and "user" objects.
I don't want to use globals (that includes singletons) or create a new instance of the object in each class, such as
function __construct() {
$this->database = new database;
$this->cache = new cache;
}
Would passing the objects in, eg.
class test{
function __construct( $obj ) {
$this->obj = $obj;
}
}
$database = new database;
$test = new test( $database );
Be the way to go?
Yes. Passing the objects to the constructor - or to a setter - is the best way to go. This pattern is known as dependency injection. It has the added benefit that it makes your code easier to test (using stubs or mocks).
Yes, that's pretty much the way you want to do. If a class has external requirements, don't create them inside the class, but require them as arguments in the constructor.
The way to go would be singletons if they have a single instance. If not, the only way is to pass them during initialization (say: in the constructor).
That would be a step in the right direction, but it does seem to me that you do actually want a singleton there, even if not actually constrained in code.
You could also use objects that have been loaded in session or in cache (APC,memcached) before.
Personnaly i think singleton is the best way to go there (especially for database class)
Related
I was wondering if there's a good way to implement the registry pattern in PHP, let me be more clear:
I do know that a Registry is used when you need to keep track of the object you instantiate in order to reuse them and not re-instantiate them again from script to script, e.g. I have a Database class that I want to instantiate only once and then use for all my scripts and I do not want to re-instantiate it again and again. Another example could be a User class that represents an instance of the currently logged in user. I could not use a Singleton in this case, cause e.g. I need another User instance for example when I want to retrieve a friend of the currently logged in user etc.
So I came up with the idea that the Registry better suits this kind of needs in such cases.
I also know that there are two ways of implementing it, or better two ways in order to access the stored instances:
Explicitly or externally, meaning that the Registry should be called every time you need to recover an instance inside your scripts or you need to put an instance inside of it;
Implicitly or internally, meaning that you make kind of an abstract class with a getInstance() method that returns an instance with the get_called_class() late static binding feature, adds it to the registry and then return that instance from the registry itself taking care that if a $label parameter is passed to the getInstance() method, then that particular instance from the registry will be returned. This approach is kinda transparent to the consumer and in my opinion is cleaner and neater (I'll show both implementations, though).
Let's take a basic Registry (really simple implementation, just an example took from a book):
class Registry {
static private $_store = array();
static public function set($object, $name = null)
{
// Use the class name if no name given, simulates singleton
$name = (!is_null($name)) ? $name: get_class($object);
$name = strtolower($name);
$return = null;
if (isset(self::$_store[$name])) {
// Store the old object for returning
$return = self::$_store[$name];
}
self::$_store[$name]= $object;
return $return;
}
static public function get($name)
{
if (!self::contains($name)) {
throw new Exception("Object does not exist in registry");
}
return self::$_store[$name];
}
static public function contains($name)
{
if (!isset(self::$_store[$name])) {
return false;
}
return true;
}
static public function remove($name)
{
if (self::contains($name)) {
unset(self::$_store[$name]);
}
}
}
I know, Registry could be a Singleton, so you never have two Registry at the same time (who needs them someone could think, but who knows).
Anyway the externally way of storing/accessing instances is like this:
$read = new DBReadConnection;
Registry::set($read);
$write = new DBWriteConnection;
Registry::set($write);
// To get the instances, anywhere in the code:
$read = Registry::get('DbReadConnection');
$write = Registry::get('DbWriteConnection');
And internally, inside the class (taken from the book) when getInstance is called:
abstract class DBConnection extends PDO {
static public function getInstance($name = null)
{
// Get the late-static-binding version of __CLASS__
$class = get_called_class();
// Allow passing in a name to get multiple instances
// If you do not pass a name, it functions as a singleton
$name = (!is_null($name)) ?: $class;
if (!Registry::contains($name)) {
$instance = new $class();
Registry::set($instance, $name);
}
return Registry::get($name);
}
}
class DBWriteConnection extends DBConnection {
public function __construct()
{
parent::__construct(APP_DB_WRITE_DSN, APP_DB_WRITE_USER, APP_DB_WRITE_PASSWORD);
} }
class DBReadConnection extends DBConnection {
public function __construct()
{
parent::__construct(APP_DB_READ_DSN, APP_DB_READ_USER,APP_DB_READ_PASSWORD);
}
}
Apparently referring to the registry indirectly (second case) seems more scalable for me, but what if some day I would need to change the registry and use another implementation, I would need to change that calls to Registry::get() and Registry::set() inside the getInstance() method in order to suit the changes or is there a smarter way?
Did someone of you came across this problem and found an easy way to interchange different registries depending on the type of application on the complexity etc.?
Should be a configuration class the solution? Or is there a smarter way to achieve a scalable registry pattern if it is possible?
Thanks for the attention! Hope for some help!
First of all. It's great that you spotted the problem of your approach by yourself. By using a registry you are tight coupling your classes to the registry where you pull your dependencies from. Not only that, but if your classes have to care about how they are stored in the registry and get grabbed from it (in your case every class would also implement a singleton), you also violate the Single-Responsibility-Principle.
As a rule of thumb keep in mind: Accessing objects globally from within a class from whatever storage will lead to tight coupling between the class and the storage.
Let's see what Martin Fowler has to say about this topic:
The key difference is that with a Service Locator every user of a service has a dependency to the locator. The locator can hide dependencies to other implementations, but you do need to see the locator. So the decision between locator and injector depends on whether that dependency is a problem.
and
With the service locator you have to search the source code for calls to the locator. Modern IDEs with a find references feature make this easier, but it's still not as easy as looking at the constructor or setting methods.
So you see it depends on what you are building. If you have a small app with a low amount of dependencies, to hell with it, go on with using a registry (But you absolutely should drop a classes behavior to store itself into or getting grabbed from the registry). If that's not the case and you are building complex services and want a clean and straightforward API define your dependencies explicitly by using Type Hints and Constructor Injection.
<?php
class DbConsumer {
protected $dbReadConnection;
protected $dbWriteConnection;
public function __construct(DBReadConnection $dbReadConnection, DBWriteConnection $dbWriteConnection)
{
$this->dbReadConnection = $dbReadConnection;
$this->dbWriteConnection = $dbWriteConnection;
}
}
// You can still use service location for example to grab instances
// but you will not pollute your classes itself by making use of it
// directly. Instead we'll grab instances from it and pass them into
// the consuming class
// [...]
$read = $registry->get('dbReadConnection');
$write = $registry->get('dbWriteConnection');
$dbConsumer = new DbConsumer($read, $write);
Should be a configuration class the solution? Or is there a smarter way to achieve a scalable registry pattern if it is possible?
That approach is encountered very often and you maybe have heard something about a DI-Container. Fabien Potencier writes the following:
A Dependency Injection Container is an object that knows how to instantiate and configure objects. And to be able to do its job, it needs to knows about the constructor arguments and the relationships between the objects.
The boundaries between a service locator and a DI-Container seem to be pretty blurry but I like the concept to think about it like that: A Service Locator hides the dependencies of a class while a DI-Container does not (which comes along with the benefit of easy unit testing).
So you see, there is no final answer and it depends on what you are building. I can suggest to dig more into the topic since how dependencies are managed is a core concern of every application.
Further Reading
Why Registry Pattern is antipattern. And what is alternative for it.
Service Locator is an Anti-Pattern
Do you need a Dependency Injection Container?
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!
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! :)
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".
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!
I understand the basic principles of inheritance in OOP, but I have a specific thing I am trying to do and want advice on how best to do it.
Lets say I have a core class:
class Core {
....
}
and I also have 2 or more other classes that extend this functionality
class MyClass1 extends Core {
....
}
class MyClass2 extends Core {
....
}
and I also have a database class in which I perform my queries, I want to pass an instantiated object of the database class (possibly by reference) to each one of my classes. One of the reasons for this would be to store a list or count of the queries that page as executed.
How should / can I go about this?
You could pass your instance of your database object to a constructor for your classes :
class Core
protected $db;
public function __construct(Your_Db_Class $database) {
$this->db = $database;
}
}
And, then, from your methods, work with $this->db, to access your database.
Of course, when instanciating your classes, you'll have to specify the database object :
// somewhere, instanciate your DB class
$db = new Your_Db_Class();
// And, then, when instanciating your objects :
$obj = new MyClass1($db);
Another way would be to use the Singleton design pattern, so there can be only one instance of your database class.
Probably a bit easier to setup ; but less easy to unit-test, after.
You could pass the database object as a parameter to the __construct function of your class, and then in said function assign the db object to member of the class, for instance $this->database_handler.
Another possibility is to work with a global variable that is your database object, but global variables are evil for many reasons, so let's disregard that.
Another note: By default, all objects are passed by reference, so you don't need to worry about that.
Main goal is to make core classes (instantiated with params) available from any place in application - in controllers, mappers, models, helpers etc.
For example, we have mapper which depends on Database object:
class Foo_Mapper
{
private $database;
public function __construct(Database $database)
{
$this->database = $database;
}
public function getFoo(array $criteria)
{
// ...
}
}
Variant 1: Basic dependency injection. The problem is that every time when I need to create mapper, I also need to instantiate a database object (with params).
$database = new Database($params);
$foo_mapper = new Foo_Mapper($database);
Variant 2: Registry. Core objects are instantiated and put into registry so every other object can easily access them.
// Somewhere in bootstrap...
$registry = Registry::getInstance();
$registry->database = new Database($params));
// Usage
$registry = Registry::getInstance();
$foo_mapper = new Foo_Mapper($registry->database);
Is there a better way to do what I want? Any drawbacks?
Variant 1: Basic dependency injection. The problem is that every time when I need to
create mapper, I also need to instantiate a database object (with params).
or passing it along. If you use a Dependency Injection Container, you would even have to do that manually: you simply add that you need to retrieve a Database, and a Database will be created (or reused) for you. Ask the Container to create a controller, and make sure you list your dependencies in the constructor. There are a few decent Dependency Injection containers for PHP, to wit:
Bucket https://github.com/troelskn/bucket
Symfony Dependency Injection http://components.symfony-project.org/dependency-injection/
Phemto http://phemto.sourceforge.net/
Sphoof\Container http://code.google.com/p/sphoof/source/browse/lib/container.php?repo=v2
For full disclosure: I wrote the last one.
Variant 2: Registry. Core objects are instantiated and put into registry so every other
object can easily access them.
You could make the registry non-static, but if you're going to rely on a Registry object in your application, you might as well leave it static. This is a perfectly viable solution, with one obvious drawback: you don't know what objects are used by what objects by looking at the API. You'll have to dig into the code.
You could make this a Singleton. Like this:
class Database
{
private static $instance = null;
public static getInstance()
{
if (self::$instance == null) self::$instance = new Database();
return self::$instance;
}
// ... METHODS ... //
// ... METHODS ... //
// ..... //
}
Then you can use
new Foo_Mapper(Database::getInstance());
It looks like you did this with your registry. Then you don't really need your registry anymore. Though if your classes are coded by someone else you would still have to use something like a registry or make a helper class/function for every of those classes that do not use the singleton pattern.
I think the way you illustrated it seems ok to me. It would be bad if you call your registry from within Foo_Mapper, because that class should probably not know about the existence of the registry, but this way looks ok.
I am using a Factory class to manage the instantiation of objects and am passing into their constructors any dependency objects (Dependency Injection) e.g.
function createBasket() {
//pass in dependent objects
$apiCon = $this->createAPIConnector($this);
$basket = new Basket($this, $apiCon);
return $basket;
}
I am trying to avoid using the 'new' keyword within any classes (other than Factory), to allow simpler and more robust unit test, clearer code etc.
Now, my question relates to configuration values that many classes require e.g.
$apiURL = 'http://some.api.com';
$apiKey = 'abcde12345';
$adminEmail = 'someone#site.com';
These values remain constant for each application instance. I currently have them in a singleton class Config and they are reachable from within any class by the following:
$cfg = Config::getInstance();
$address = $cfg->apiURL;
However, this class instance is still a dependency within any Class that calls it, so should I think about passing this into class constructors, e.g.
function createBasket() {
//pass in dependent objects
$apiCon = $this->createAPIConnector($this);
$cfg = Config::getInstance();
//pass singleton config object to constructor
$basket = new Basket($this, $apiCon, $cfg);
return $basket;
}
...or perhaps pass them in via a set method, rather than via constructor:
function createBasket() {
//pass in dependent objects
$apiCon = $this->createAPIConnector($this);
$basket = new Basket($this, $apiCon);
//pass singleton config object to setter
$basket.setConfig(Config::getInstance());
return $basket;
}
Any guidance on the best approach would be much appreciated.
Thanks, James
Seems like that defeats the purpose of having a singleton config object that's globally available. The entire point is to avoid having to pass it as a parameter to every class you make.
Ive always seen them made as constants. I don't know that this is the "best" solution but I've seen this, and used it many times. Because its a const (the same is true for static vars, I would be interested to hear why one is better than the other) you don't need to instantiate the class which would probably save you some overhead if you want to be nit picky...
class SomeClass
{
const MYCONS = "APIKEY or Whateva";
}
then in when you need to use it require the file and do something like
SomeClass::MYCONST //to get your config info
I use a similar method, setting everything up in a single array or file and defining it accordingly:
$config = array(
'MYCONST_1'=>'myValue',
'USER'=>'username',
'PASSWORD'=>'y3ahr1ght'
);
foreach($config as $const=>$value){
define($const,$value);
}