SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 42
  1. #1
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    A year on, how are you finding DI?

    Hi.

    The DependencyInjection pattern has been knocking around this forum for a year or two. Anyone willing to share their practical experiences with it? Any useful DI tricks or gotchas?

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  2. #2
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  3. #3
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wouldn't say I've done alot with it but http://ren.dotgeek.org/DooX/index.php currently uses DI. A DI container is being passed around from the front controller to the individual contollers, as a "context". I doesn't contain anything too complicated, a Config object, a data layer, and the PDO wrapper it requires. Plus the a Request & Response object when its run from the web, (it has CLI admin interface).

    Another DI container is used to register all the controllers for the application. Which is handed to the routes style request mapper, so it can create the controller. Its has a slight twist in that it can adapt the created controller, based on an action provided by the request mapper. So can have multiple actions defined in a single controller class.

  4. #4
    SitePoint Zealot crashmakerMX's Avatar
    Join Date
    Jun 2005
    Location
    Germany
    Posts
    129
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  5. #5
    SitePoint Enthusiast
    Join Date
    Mar 2005
    Posts
    53
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hello,

    Just for reference I've been using a pretty minimal DI-powered ServiceLocator within Mojavi 4. You can take a look here:

    http://trac.mojavi.org/browser/branc...ckages/locator

    Basically how it works is you register your "Services" with the SL (ServiceLocator) using an object that extends Service, and depending upon that implementation (ConstructorInjectionService, etc) it stitches it up. I used Pico as a reference (the person who wrote it did an amazing job), so you'll be certain to see similarities. Currently it doesn't support decorators, as i haven't needed them yet, but I imagine there will come a time when I need to handle that sort of stuff.

  6. #6
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have a script working that is more like a ServiceLocator but it needs to be tidied up first, before I post it to the forum, since that appears to be what everyone else is doing at the moment

    Hell, here it is, in it's complete uglyness...

    PHP Code:
    session_start();
        
    error_reportingE_ALL E_STRICT );
        
        class 
    ServiceLocator {
            private static 
    $factories = array();
            private static 
    $instances = array();
            
            public function 
    __construct() {}
            public static function 
    registerFactory$factory ) {
                
    $factory strtolower$factory );
                if( 
    is_arrayself::$factories ) && !in_array$factoryself::$factories ) ) {
                    
    self::$factories[$factory] = $factory;
                }
            }
            
            public static function 
    registerInstance$instance ) {
                
    $classname strtolowerget_class$instance ) );
                if( 
    is_object$instance ) ) {
                    if( 
    is_arrayself::$instances ) && !array_key_exists$classnameself::$instances ) ) {
                        
    self::$instances[$classname] = $instance;
                    } 
                }
            }
            
            public static function 
    getService$service ) {
                
    $service strtolower$service );
                if( 
    array_key_exists$serviceself::$instances ) ) {
                    
    // service found so return
                    
    return self::$instances[$service];
                }
                
    // seek service from available factories
                
    foreach( self::$factories as $factory ) {
                    
    // factory found...
                    
    if( array_key_exists$factoryself::$instances ) ) { 
                        
    // ... does factory hold service?
                        
    $factory self::$instances[$factory];
                        if( 
    $factory -> hasService$service ) ) {
                            
    // yes so keep service instance and return
                            
    $instance $factory -> createService$service );
                            
    self::registerInstance$instance );
                            return 
    $instance;
                        }
                    } else {
                        
    $instance self::createInstance$factory );
                        
    self::registerInstance$instance );
                        
                        
    // does factory hold service?
                        
    if( $instance -> hasService$service ) ) {
                            
    self::$instances[$service] = $instance -> createService$service );
                            return 
    self::$instances[$service];
                        } else if( 
    strtolowerget_class$instance ) ) == $service ) {
                            
    // dealing with service it's self
                            
    return $instance;
                        }
                    }
                }
            }
            
            private static function 
    createInstance$classname$args = array() ) {
                
    $classname strtolower$classname );
                
    $reflected = new ReflectionClass$classname );
                
                
    $constructor $reflected -> getConstructor();
                
    $parameters $constructor -> getParameters();
                
                foreach( 
    $parameters as $parameter ) { 
                    
    $args self::createInstance$parameter -> getName(), $args );
                }
                
                
    $callback = array( new ReflectionClass$classname ), 'newInstance' ); 
                return 
    call_user_func_array$callback, array( $args ) );
            }
        }
        
        class 
    DbFactory {
            private 
    $config;
            
            public function 
    __constructConfig $config ) {
                
    $this -> config $config;
            }
            
            public function 
    createService$service ) {
                return new 
    Pdo
                    
    $this -> config -> get'dsn' ), 
                    
    $this -> config -> get'usr' ), 
                    
    $this -> config -> get'pwd' ) );
            }
            
            public function 
    hasService$service ) {
                return 
    in_array$service, array( 'db_connection' ) );
            }
        }
        
        class 
    Config {
            private 
    $parameters = array( 'dsn' => 'mysql:host=localhost;dbname=tmpdb''usr' => 'username''pwd' => 'password' );
            
            public function 
    __construct() {}
            public function 
    get() {
                
    $parameters func_get_args();
                return 
    $this -> parameters[strtolowerarray_shift$parameters ) )];
            }
            
            public function 
    hasService$service ) {
                return 
    false;
            }
        }
        
        
    ServiceLocator::registerFactory'config' );
        
    ServiceLocator::registerFactory'dbfactory' );
        
        
    $config ServiceLocator::getService'config' );
        
        
    ServiceLocator::registerInstance( new DbFactoryServiceLocator::getService'config' ) ) ); // works without this as well
        // just to be sure... comment it out :p
        
    $pdo ServiceLocator::getService'db_connection' );
        
        echo( 
    '<pre>' ); print_r$pdo ); echo( '</pre>' );
        
        exit; 
    You just need to register the service - directly as it is - or the factory to which the service belongs to, either as a string, or an instance it's self, ie

    PHP Code:
    ServiceLocator::registerFactory'Request' ); // or
    ServiceLocator::registerInstance$request = new Request() ); 
    If a class constructor has dependencies, then you need to register them before you create an instance of that class - the script at the moment doesn't autoload files, etc for you. But in saying that though, it is recursive, so if the dependencies have their own dependencies, you just (again) register those dependencies as well.

    A further point to note at the moment is that the dependencies are actually based on the constructors parameters themselves, and not their type hints, so beware (I need to work on it some more).

    Questions, etc then I'm sure I'll be around. As for true Dependency Injection with PHP, well...
    Last edited by Dr Livingston; Apr 3, 2006 at 13:38. Reason: ...

  7. #7
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    The DependencyInjection pattern has been knocking around this forum for a year or two. Anyone willing to share their practical experiences with it?
    I haven't found a need for full-blown DI (which may simply be a comment on my own experience and the kinds of things I've been working on). Instead I've been using a simple factory object to wire everything up - the DI discussions here started me thinking along these lines. A "global" scope solves a lot of problems - a bit like a party where anyone can be introduced to anyone else but (unlike real globals) no-one is allowed to chat unless you do explicitly introduce them.

    Quote Originally Posted by lastcraft
    Any useful DI tricks or gotchas?
    The only thing I've wondered about is how to manage actions which must take place in a certain sequence. Wiring everything up right at the start possibly creates more of a risk that something can be called at the wrong time. Maybe a complex domain could throw up lots of "bad sequence" bugs - and all the while unit tests could be running green. Just a niggling suspicion. I haven't run into any real problems.

  8. #8
    SitePoint Enthusiast
    Join Date
    Sep 2005
    Posts
    55
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    as of yet, i still can't see a valid reason why i may implement a DI. a service locator, yes ... but not a full blown DI.

    i have had a little fiddle and have read up on the subject a fair bit - but haven't 100% fully grasped the concept yet. i understand it, but not enough to consider trying to mess about with implementing one just yet.

    i guess it's one of those things that i'll eventually get back round to doing ... but for now is on a back burner.

  9. #9
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by smithie
    this seems to be a common problem when people come to trying to implement a DI - the need, or want, to simplify it all, effectively turning it back into more of a service locator - either through wanting to make it easier to develop, or to make things simpler overall - possibly because of lack of understanding of it? that's definitely the case where myself is concerned ...
    Yes. The paradox I was facing is that DI is too rigid. As long as the dependencies are just other classes, it's fine, but in a real world application, you'd want to provide configuration as part of the wiring too. The DB connection object is a fine example. You'd want the factory to manage the credentials for you.
    Another problem is that you'll need to pass the container on all over your code, which can be rather impractical at times.

  10. #10
    SitePoint Enthusiast
    Join Date
    Oct 2005
    Posts
    66
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    Hi.

    The DependencyInjection pattern has been knocking around this forum for a year or two. Anyone willing to share their practical experiences with it? Any useful DI tricks or gotchas?

    yours, Marcus
    Hello, I am currently playing with Service Locator at the moment.

    Dependency Injection seems good but still is difficult to me to grasp the concept fully. The harder part for me is to understand the real differences between Service Locator and DI.

    Stefano

  11. #11
    SitePoint Enthusiast silicate's Avatar
    Join Date
    Nov 2004
    Location
    Toronto
    Posts
    43
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey,

    I guess the biggest debate with DI is whether or not it's "worth it" to implement it over a simple Locator. For me, I am not sure that I am setting up so many objects that I really need some mechanism to do it for me. Even if I was doing something complex, am I saving anything by having to register the db factory with the DI Locator before using the database rather than just calling the factory get* method and sticking it in a regular locator?

    Then again maybe the point is that the regsitered Server Component/Resource only gets instantiated when it's needed, but it's available to be created anywhere, any time?

    A couple of things that I think could be interesting are based on the fact that DI's primary responsibility is dependancy resolving. Proper placement of require_once statements is a minor thing to be sure, but auto-loading of files based on a dependancy on the classes defined within it is a cool feature. Also, changing the paths of those files at runtime (without an ugly define) would be a nice feature - specifically for testing in different environments.

    Later,

    Matthew.

  12. #12
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The feeling I have with Dependency Injection is that it's too heavy weight for the bulk of most projects to the point that there is no real need for it - a bit like using a 16lb hammer to tap a tack in the wall; In effect you knock down a good portion of said wall

    Be it that, and the fact that to implement DI properly, and within a given environment, from the outside there are no real benifits for the shear complexity of what is DI; I certainly have no need for true DI at the moment and can't see the need for it in the medium future either...

    A Service Locator is more suitable for me, as my main concern is finding the better method of giving the client script, their class instances that they're interested in; Usually a Factory is enough but maintaining the creation of those Factories is a complete pain.

    With a Service Locator the problem is resolved, to the point I register the required Factories and forget about it, since the Service Locator creates the instances of the class(es) required, including constructor dependencies.

    For most people you won't be needing more than that.

  13. #13
    SitePoint Zealot DerelictMan's Avatar
    Join Date
    Oct 2005
    Posts
    123
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    Be it that, and the fact that to implement DI properly, and within a given environment, from the outside there are no real benifits for the shear complexity of what is DI; I certainly have no need for true DI at the moment and can't see the need for it in the medium future either...
    Don't DI containers theoretically make it easier to create classes that are more easily unit tested (especially with mock objects)? I ask this as someone who currently doesn't do much unit testing and hasn't yet used mock objects (but intends to soon).

  14. #14
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I see DI as a natural outgrowth of an emphasis on unit testing. Classes built with DI in mind are more independent, easier to test and reuse. Sorry, no time for a longer post. I'll drop link and run...interesting links on the practical application of DI:

  15. #15
    SitePoint Member
    Join Date
    Sep 2005
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sorry to rescue this thread from obscurity, but it's an interesting question. I have been doing a bit of development with J2EE and specifically Spring which provides a simple framework for implementing business and data layers inside an inversion of control container.

    I find it so handy when writing Unit tests with JUnit and JMock and have been desperately searching for something that would integrate PHP code as nicely with simpletest.

    I have looked into the Pico port, but development there seems to have tailed off, and in general it seems as if PHP hasn't really taken to IoC in any big way.

    Am I missing anything obvious, or is this another instance where in PHP if you want to adopt a good pattern you have to roll an implementation out yourself?

    Cheers,

    Aaron.

  16. #16
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi.

    I am about to make Phemto it's own project (as soon as Sourceforge gets it's CVS back up). Pavel, who ported Pico, is interested. Are you? The project deperately needs people with practical DI experience.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  17. #17
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm still finding DI an overkill in PHP environment -- the plain old Registry seems much easier. Having said that, perhaps I haven't yet ran into the real problems that might require DI; until then, YAGNI is at work.

  18. #18
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi.

    One of the design goals is not to compete with Pico. The Phemto tutorial (the part I want to write first) should progress from using it as a Registry, to using it as a ServiceLocator/Factory to full DI. If I can keep the use cases clean, then it should be pretty close to YAGNI.

    Of course the real interest will be with framework authors.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  19. #19
    SitePoint Addict
    Join Date
    May 2003
    Location
    The Netherlands
    Posts
    391
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    The Phemto tutorial (the part I want to write first) should progress from using it as a Registry, to using it as a ServiceLocator/Factory to full DI.
    For what is worth ... I love the idea of the progression.
    There’s more than one way to skin a cat.

  20. #20
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Is svn down too? Why not use that? I'm very interested in this.

  21. #21
    SitePoint Enthusiast silicate's Avatar
    Join Date
    Nov 2004
    Location
    Toronto
    Posts
    43
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey there,

    I am very interested in this as well.

    I think that there is a lot of potential in a ServiceLocator/Factory for what I want to do. It would be cool if the Application Controller was able to dynamically plug in framework components depending on what it needed for it's environment. I'd like to see a framework that can deal with different access methods such as cli or browser or a SVN hook. If you access the application from CLI you do not need an HTML template parser. If you are accessing the app from a SVN hook you do not need a Session handler. I guess a SL/F that is configured by the Input Controller is what I am thinking.

    Just rough thoughts at the moment.

    Later,

    Matthew Purdon
    later,

    Matthew.

  22. #22
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    I have a script working that is more like a ServiceLocator but it needs to be tidied up first, before I post it to the forum, since that appears to be what everyone else is doing at the moment

    Hell, here it is, in it's complete uglyness...
    Intriguingly, that is exactly what I had thought of doing - an actually implemented some time ago. [Edit: Mine didn't do any reflection, though. Missed that.] I think the solution is interestingly simple, yet allowing an increased amount of sophistication via different kinds of factories. What I got stuck with was whether to separate class loading from the Locator/Factory symbiosis to an external autoloader. I'm always thinking "yes", then followed by some what-ifs, and never getting anywhere. At some point I was also about to create a thread on the naming of those two - the factories could be locators as well, so it doesn't feel accurate.

    (After that I started building a very plain MVC framework for demonstration purposes - which, needless to say, didn't remain plain at all simply because I kept throwing cases at it that it wasn't capable of clearing just yet. This iteration used a simple, container-like ServiceLocator instead of a Locator/Factory-combo.)

    Was the ugly-part a joke, or do you really find the solution unsatisfactory? What do others think?

    lastcraft: Looking forward to the next version of Phemto!

  23. #23
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Selkirk
    Is svn down too? Why not use that? I'm very interested in this.
    SVN at sourceforge is currently working, and it's a better choice (IMO) than cvs anyway.

  24. #24
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by Selkirk
    Is svn down too? Why not use that? I'm very interested in this.
    I'll probably set Phemto up as SVN. The other part of the site that is having problems is their approval process. Jeff, do you want to be added as a committer? Phemto should never creep beyond a hundred lines of code.

    CVS outtage is holding up SimpleTest. I have aload of stuff stuck on a home machine waiting to be checked in. I cannot even fix people's bugs right now. Grrr...

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  25. #25
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    Jeff, do you want to be added as a committer? Phemto should never creep beyond a hundred lines of code.
    I'll help out as much as I can, but I'm not sure we're looking for the same things. I'd like to see a tight and light, immutable and abstract DI kernel that could be extended for various implementations. 100 lines might be optimistic.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •