Is the Registry design pattern a good solution for this in PHP?
For a social network site (facebook, myspace).
let's say I have a Database class which creates a single DB connection and lets me do DB stuff and a Sessions class which lets me handle sessions as well as a Cache class which lets me cache items and retrieve them. SO that is 3 main classes that I will need to be able to access on every page of my site. After reviewing the Registry Pattern for the past hour, I am thinking that it is the perfect solution maybe. I can store my Database, Session, and Cache objects into a registry Object and then Inject the Registry object into every page or every other class and have access to my database, sessions, and cache.
Before this I was using a singleton pattern so I would have to call my singleton method for all 3 of my MAIN classes inside of every page or other class.
So I am just wondering is there any downfalls of using the Registry class? 1 that I can see is it seems it may be harder to see what classes depend on which other classes and such. Other then that it seems like a great solution for this, also I saw another post on here of a user's registry class where they were storing setting in the registry an having access to them in all the other classes that the registry Object is passed into, I am sure I will find a good use for that feature as well.
So the only question here is am I missing something or did I just hot the lotto?
UPDATE
Also if using a registry to store objects in, should I do something like this...
$this->session = $registry->getObject('session');
or this instead
$this->registry->session = $registry->getObject('session');
The second method seems like it would maybe be easiar to understand where the object came from?
You mean a registry of Singletons, right? If so, it sounds like all you really want is access to three global objects everywhere, but contained inside another object.
So if you wrote cache.php, sessions.php, and database.php, which define the classes Cache, Sessions, and Database, you want to contain them all inside a Registry object defined in registry.php.
First of all, it's great to control the ORDER of instantiation this way. It's better than simply doing a require_once of cache.php, sessions.php, and database.php, and inside of them you define not only the class but the single global instance of it. That controls the ORDER of instantiation by how you include/require it. Kind of sleazy. Better to have your Registry object, that when it gets created and becomes a $registry global, first thing is does is control the creation of your globals in the order and how you want.
Second of all, it's great to have a single Registry.php that has a single $registry global. Defining globals here and there over various files gets hard to manage.
Now that I've agreed with you, I pose an important question to you. How do you see these being different:
$registry->getObject('session');
$registry->getObject('database');
$registry->getObject('cache');
versus:
$registry->getSession ();
$registry->getDatabase ();
$registry->getCache ();
Personally, I like the latter. You aren't using a string "session" to refer to a Session object, obtained through a super-generic getObject. Instead, you are using getSession() to get a Session. It reads better.
Your registry, after all, knows all about the three globals, it creates them explicitly, so it's already locked into a single purpose. Adding concrete methods also tied to its single purpose isn't "weak" or "bad". Instead, I think it's less code and easier on the eyeballs.
Related
Why should I use Zend_Registry instead of the Singleton pattern?
My coworker and me recently had a discussion about this. His point was that we should use Zend_Registry for all consistent objects, but I wanted to use the singleton pattern, since Zend_Registry just does the same, but wrapped.
I have a problem with code like this:
$list = Zend_Registry::get('database')->getList($sql);
Since theres a chance that database isn't in Zend_Registry. In cases of lazy loading, I would have to make my own registry with information about specific objects in my system. Like if the database takes specific parameters on loadtime, then it would have to know this.
I would instead use getInstance and then all the code would reside in the same object. Does that make sense?
Even though you phrased your question as an either/or, might I suggest a third alternative?
I try to avoid both singletons and Zend_Registry wherever possible, since they function, in effect, as globals. When a segment of code can reach into the global ether - via a call to a singleton or a global registry - to get something it needs, it creates a hidden - or at least, a non-explicit - dependency that makes things harder to debug and unit-test.
In contrast, I try to follow dependency injection advice, paraphrased as: "Give a component what it needs. Don't make it find what it needs."
I find that for most entities for which I might feel I need a registry/singleton - db connections, loggers, etc - I can create them at Bootstrap, store them in the Bootstrap registry and inject them into my controllers, usually during init() using $this->getInvokeArg('bootstrap')->getResource('myResource'). Only controllers reach back into the Bootstrap. Then, any models or services that need these dependencies get them passed-in explicitly by the controller, either via constructor or by setter injection.
A hybrid approach to which I do sometimes fall back is to design my service/model classes with getters/setters for these dependencies - getDbAdapter() and setDbAdapter(); getLogger() and setLogger(), etc. The getter lazy-loads from the global registry - whether some singleton or by Zend_Registry, throwing exceptions when they are not where I expect them to be. In that sense, it is similar to what you are suggesting. It does violate the purist dependency injection philosophy. But at least the presence of the getter/setter methods explicitly demonstrates that there is a dependency and allows me to mock it out or to provide non-default implementations.
It does for simple blog or something. Otherwise you're stuck with only one DB instance. And that's NOT what you want in the long run. You may want to connect to other server (to log errors to central db, to import products from someone, ...) or connect as different user (for security reasons - you don't want your API to have access to admin_users table, but you still need to connect to it to check if user is valid in the first place).
You can do one-purpose registers (My_Db_Admin, My_Db_ReadOnly, ...) but that does not make much sense to me. Using registry you're not stuck with one instance. You can create one outside registry and work with it for a while and then trash it ;)
I've got this Config-class that I use in my PHP5 application to load & parse my static config. This far I've managed to keep the class from being a singleton/registry and instead passed the instance of the Config class around to wherever it's needed with the help of Dependency injection.
But now as I need to set/make changes in my Config during runtime at one place, my changes aren't reflected globally and being far from a specialist with the use of the static modifier in PHP, I need to ask:
What is the best way to ensure that changes to the properties in my Config-class are reflected throughout my application without making the class into a singleton? Can I just make the variable holding the config data static?
This far I've managed to keep the class from being a singleton/registry and instead passed the instance of the Config class around to wherever it's needed with the help of Dependency injection.
If you pass the same instance of your Config class to every part of your application and you change a setting it should be reflected everywhere else.
In case you are creating multiple objects of the class (and parse that config file every time?!) you might want to stop doing that. It's possibly wasteful and I'd say it is confusing.
So if you create only one and pass that around everything should be fine.
Under the assumption that you create multiple instances of the object that only should exist once:
If you are able to "fix" your architecture to allow you to do that: Do so.
If you can't to that... well.. creating a static property to hold your values in a class that you can have multiple instances off is, at least in my book, a major wtf factor. If you can't fix (meaning it's to much off a hassle to do so) just "break" it in an expected way so other people don't trip over it.
I'd rather have a singleton than something that creates all the issues with singletons and also lies about being a wrapper for a global variable.
Blindly avoiding design patterns because you hear on Internet forums that they're bad is about as much an anti-pattern as singletons are in general. If a tool is right for a job, then it's right.
Look at your question, you're trying to emulate singletons through a complex multi-update system for God's sakes... And just so you know, making a class static is essentially turning it into a singleton, albeit an insecure one that can be overwritten at any time.
TL;DR: Think for yourself and use the right tools; make your config class a singleton.
Firstly, I want to restrict this question to web development only. So this is language agnostic as long as the language is being used for web development. Personally, I am coming at this from a background in PHP.
Often we need to use an object from multiple scopes. For example, we might need to use a database class in the normal scope but then also from a controller class. If we create the database object in normal scope then we cannot access it from inside the controller class. We wish to avoid creating two database objects in different scopes and so need a way of reusing the database class regardless of scope. In order to do so, we have two options:
Make the database object global so that it can be accessed from anywhere.
Pass the database class to the controller class in the form of, for example, a parameter to the controller's constructor. This is known as dependency injection (DI).
The problem becomes more complex when there are many classes involved all demanding objects in many different scopes. In both solutions, this becomes problematic because if we make each one of our objects global, we are putting too much noise into the global scope and if we pass too many parameters into a class, the class becomes much more difficult to manage.
Therefore, in both cases, you often see the use of a registry. In the global case, we have a registry object which is made global and then add all of our objects and variables to that making them available in any object but only putting a single variable, the registry, into the global scope. In the DI case, we pass the registry object into each class reducing the number of parameters to 1.
Personally, I use the latter approach because of the many articles that advocate it over using globals but I have encountered two problems. Firstly, the registry class will contain huge amounts of recursion. For example, the registry class will contain database login variables needed by the database class. Therefore, we need to inject the registry class into the database. However, the database will be needed by many other classes and so the database will need to be added to the registry, created a loop. Can modern languages handle this okay or is this causing huge performance issues? Notice that the global registry does not suffer from this as it is not passed into anything.
Secondly, I will start passing large amounts of data to objects that don't need it. My database doesn't care about my router but the router will get passed to the database along with the database connection details. This is made worse through the recursion problem because if the router has the registry, the registry has the database and the registry and the registry is passed to the database, then the database is getting passed to itself via the router (i.e. I could do $this->registry->router->registry->database from inside the database class`).
Furthermore, I don't see what the DI is giving me other than more complexity. I have to pass an extra variable into each object and I have to use registry objects with $this->registry->object->method() instead of $registry->object->method(). Now this obviously isn't a massive problem but it does seem needless if it is not giving me anything over the global approach.
Obviously, these problems don't exist when I use DI without a registry but then I have to pass every object 'manually', resulting in class constructors with a ridiculous number of parameters.
Given these issues with both versions of DI, isn't a global registry superior? What am I losing by using a global registry over DI?
One thing that is often mentioned when discussing DI vs Globals is that globals inhibit your ability to test your program properly. How exactly do globals prevent me from testing a program where DI would not? I have read in many places that this is due to the fact that a global can be altered from anywhere and thus is difficult to mock. However, it seems to me that since, at least in PHP, objects are passed by reference, changing an injected object in some class will also change it in any other class into which it has been injected.
Let's tackle this one by one.
Firstly, the registry class will contain huge amounts of recursion
You do not have to inject the Registry class into the database class. You can just as well have dedicated methods on the Registry to create the required classes for you. Or if you inject the Registry, you can simply not store it but only grab from it what is needed for the class to be instantiated properly. No Recursion.
Notice that the global registry does not suffer from this as it is not passed into anything.
There might be no recursion for the Registry itself, but objects in the Registry may very well have circular references. This could potentially lead to memory leaks when unsetting objects from the Registry with PHP Versions before 5.3 when the Garbage Collector would not collect those properly.
Secondly, I will start passing large amounts of data to objects that don't need it. My database doesn't care about my router but the router will get passed to the database along with the database connection details.
True. But that's what the Registry is for. It's not much different from passing $_GLOBALS into your objects. If you dont want that, dont use a Registry, but only pass in the arguments required for the class instances to be in a valid state. Or simply dont store it.
I could do $this->registry->router->registry->database
It is s unlikely that router exposes a public method to get the Registry. You wont be able to get to database from $this through router, but you will be able to get to database directly. Certainly. It's a Registry. That's what you wrote it for. If you want to store the Registry in your objects, you can wrap them into a Segregated Interface that only allows access to a subset of the data contained within.
Obviously, these problems don't exist when I use DI without a registry but then I have to pass every object 'manually', resulting in class constructors with a ridiculous number of parameters.
Not necessarily. When using constructor injection, you can limit the number of arguments to those absolutely necessary to put the object into a valid state. The remaining optional dependencies can very much be set through setter injection as well. Also, no one hinders you to add the arguments in an Array or Config object. Or use Builders.
Given these issues with both versions of DI, isn't a global registry superior? What am I losing by using a global registry over DI?
When you use a global Registry you are tight coupling this dependency to the class. This means the using classes cannot be used without this concrete Registry class anymore. You assume there will be only this Registry and not a different implementation. When injecting the dependecies, you are free to inject whatever fulfills the responsibility of the dependency.
One thing that is often mentioned when discussing DI vs Globals is that globals inhibit your ability to test your program properly. How exactly do globals prevent me from testing a program where DI would not?
They do not prevent you from testing the code. They just make it harder. When Unit-Testing you want to have the system in a known and reproducable state. If your code has dependencies on the global state, you have to create this state on each test run.
I have read in many places that this is due to the fact that a global can be altered from anywhere and thus is difficult to mock
Correct, if one test changes the global state, it might affect the next tests if you do not change it back. This means you have to take effort to recreate the environment in addition to setting your Subject-Under-Test into a known state. This might be easy if there is just one dependency, but what if there is many and those depend on the global state too. You'll end up in Dependency Hell.
I'll post this as an answer since I'd like to include the code.
I've benchmarked passing an object versus using global. I basically created a relatively simple object, but one with a self reference and a nested object.
The results:
Passed Completed in 0.19198203086853 Seconds
Globaled Completed in 0.20970106124878 Seconds
And the results are identical if I remove the nested object and the self reference...
So yes, it appears that there's no real performance difference between these two different methods of passing data. So make the better architectural choice (IMHO that's the Dependency Injection)...
The script:
$its = 10000;
$bar = new stdclass();
$bar->foo = 'bar';
$bar->bar = $bar;
$bar->baz = new StdClass();
$bar->baz->ar = 'bart';
$s = microtime(true);
for ($i=0;$i<$its;$i++) passed($bar);
$e = microtime(true);
echo "Passed Completed in ".($e - $s) ." Seconds\n";
$s = microtime(true);
for ($i=0;$i<$its;$i++) globaled();
$e = microtime(true);
echo "Globaled Completed in ".($e - $s) ." Seconds\n";
function passed($bar) {
is_object($bar);
}
function globaled() {
global $bar;
is_object($bar);
}
Tested on 5.3.2
I'm currently working on an oophp application. I have a site class which will contain all of the configuration settings for the app. Originally, I was going to use the singleton pattern to allow each object to reference a single instance of the site object, however mainly due to testing issues involved in this pattern, I've decided to try a different approach.
I would like to make the site class the main parent class in my app and call it's constructor from within the constructors of the child classes, in order to make all the properties available whenever needed.
When run for the first time, the class will only contain the db details for the app. To get the remaining values a query must be performed using the db details. However, any subsequent instances will be clones of the original (with all values). I may also set a Boolean flag to perform the query again a completely new instance is required.
Would this be a viable alternative to the singleton and would it solve the testing issues it causes? This is all theory atm, I haven't started to code anything yet,
Any thoughts or advice greatly appreciated.
Thanks.
I think a better way is to have an 'configuration' object that will get passed to the constructors of all your other classes. So, almost something like a singleton, except it's explicitly created and passed only to classes that need it. This approach is usually called dependency injection.
After trying many different techniques, what I have found functional and reliable is this method:
Use a bootstrap, or initialization file. It is located in the ROOT of the site with the proper permission and safe-guards against direct access.
All pages in the site first include this file. Within it, I create all my global objects (settings, user), and reference them from there.
For example:
// OBJECT CREATION
$Config = new Configuration();
$User = new User();
Then within classes that require these objects:
public function __construct($id = NULL) {
global $Config; // DEPENDENCY INJECTION SOUNDS LIKE AN ADDICTION!
if($Config->allow_something) {
$this->can_do_something = true;
}
if(NULL !== $id) {
$this->load_record($id);
}
}
Notice that I just access these global objects from within the class, and how I don't have to include the object variables as the first constructor parameter each and every time. That gets old.
Also, having a static Database class has been very helpful. There are no objects I have to worry about passing, I can just call $row = DB::select_row($sql_statement);; check out the PhpConsole class.
UPDATE
Thanks for the upvote, whoever did that. It has called attention to the fact that my answer is not something I am proud of. While it might help the OP accomplish what they wanted, it is NOT a good practice.
Passing objects to new object constructors is a good practice (dependency injection), and while "inconvenient," as with other things in life, the extra effort is worth it.
The only redeeming part of my answer is use of the facade pattern (eg. DB::select_row()). This is not necessarily a singleton (something the OP wanted to avoid), and gives you an opportunity to present a slimmed down interface.
Laravel is a modern PHP framework that uses dependency injection and facades, among other proven design patterns. I suggest that any novice developer review these and other such design practices thoroughly.
I need some help in planning out how to do my classes in PHP. I have a session class and a database class that I pretty much need to access inside of every other class I use (forums, mail, users, lots more classes)
So I am looking for how I should access the session class inside of my other classes, 1 option is to make it GLOBAL, another is to pass $session and $database objects into every class I use like this...
$mail = new Mail($session, $database);
but this seems pretty tedious if I have to do it for 15+ different classes? Is there a better way?
Below is an example of some methods from my sessions class that I would be calling inside of other classes.
// set a value into session
$session->set('auto_id', 'some value for auto_id');
// get a value from session
$session->get('auto_id');
For scenarios like this i would make use of the registry pattern. This is a pretty good explanation.
The registry pattern acts like a storage for objects.
A code example is on it's way.
Edit:
In your example (new Mail($session, $database)), i think you should do this even if you use the registry pattern. This makes every thing less coupled and easier to understand and change parts independently. As I have not done so much PHP in the last couple of years, i don't know if there is any IOC-framework available, but that would help you instantiating your classes.
I'd have thought the singleton pattern would be a very good fit in this instance.
There's a nice simple tutorial (with some sample code) over at talkPHP that seems like a reasonable implementation.
For things like sessions and databases, I think global variables are fine here.
I disagree completely with using globals. I would either use the Registry pattern as suggested or make both the Session and DB themselves Singletons, although this will make unit testing much more difficult.