5

Let's say you have a object that is unique, and it's used by all other classes and functions ...something like $application.

How would you access this object in your functions?

  1. using a global variable in each of you functions:

    global $application;
    $application->doStuff();
    
  2. creating a function, like application() that instantiates the object into a static variable and returns it; then use this function everywhere you need to access the object:

    application()->doStuff();
    
  3. create a singleton thing, like a static method inside the object class which returns the only instance, and use this method to access the object:

    Application::getInstance()->doStuff();
    
  4. KingCrunch & skwee: Pass the application object as argument to each function/class where is needed

    ...
    public function __construct(Application $app, ...){
      ....
    

If there are other options please post them. I'm wondering which of these options is the most efficient / considered "best practice".

Alex
  • 66,732
  • 177
  • 439
  • 641
  • 2
    Do you have a specific question, or are you just looking to make a list? –  Feb 08 '12 at 21:16

3 Answers3

4

Singletons, God Classes, monolithic classes, etc. are all anti patterns, so I would suggest a fourth option: dependency injection. You can create an instance of application in your application via a factory (or perhaps even new if it has no dependencies, but this can end up complicating things later).

Then, any class that needs access to application can get it as a member, helpfully via the constructor. I'm sure that not every class needs access to application. Remember the Law of Demeter.

If you need some generic functionality like converting one static string to another, I suggest using php's global functions (as opposed to, for instance, a faux static class). I believe they were designed for that purpose.

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
4

I'd pass it to all the needed methods. i.e.

function doFoo(Application $app) {
    $app->doStuff();
}

Both global and singleton considered bad and ties your code too much and this makes unit testing more difficult. There is one rule when you are allowed to use singleton, if you answer "yes" to the following statement:

Do I need to introduce global state to my application AND I must have a single instance of given object AND having more than one instance will cause error

If you answer yes to all the 3 parts then you can use singleton. In any other case just pass all the instances to all the method who needs them. If you have too much of them, consider using something like Context

class Context {
    public $application;
    public $logger;
    ....
}
========
$context = new Context();
$context->application = new Application();
$context->logger = new Logger(...);
doFoo($context);
========
function doFoo(Context $context) {
    $context->application->doStuff();
    $context->logger->logThings();
}

(you can use getters/setters if you need to protect the data or manipulate it or if you want to use lazy initiation etc).

Good luck!

Dmitry Kudryavtsev
  • 16,354
  • 4
  • 25
  • 32
  • 2 (I must have a single instance of given object) is kind of true :) – Alex Feb 08 '12 at 21:33
  • But having more than one instance will cause error in the program? Its a logical statement of A && B && C, in your case B is true and A and C false, so the statement is false :) I really can't think of a situation where the answer to this statement will be true. Maybe when programming some sort of micro-controller when I have a single CPU or something like this... – Dmitry Kudryavtsev Feb 08 '12 at 21:39
1

Or just give it to the ones, that are interested in it. All the suggestions you made are like global variables, even if you call it not that in 2 of 3 variants.

Before it comes to that: If you want to say "Thats not possible, because everything needs it", than maybe it does too much, can too much, and/or knows too much.

KingCrunch
  • 128,817
  • 21
  • 151
  • 173
  • This is true, I could pass the application as a argument to __construct of each class where I needed it. But I don't know... Using `$this->application` inside that class looks kind of weird – Alex Feb 08 '12 at 21:30
  • also I would have to pass that argument to each static method of the class too... – Alex Feb 08 '12 at 21:38
  • Using `$this->property` looks exactly how access to a dependency should looks like. Regarding your second comment: Sounds, that you have too much static methods too. – KingCrunch Feb 08 '12 at 21:42