SitePoint Sponsor

User Tag List

Page 3 of 3 FirstFirst 123
Results 51 to 54 of 54
  1. #51
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Welcome back from the dead! Spooky...

    Quote Originally Posted by Selkirk View Post
    PHP Code:
    $config->define('Connection')
        ->
    asClass('MySqlConnection')
        ->
    parameterValue('dsn''mysql:dbname=testdb;host=127.0.0.1'); 
    Nice. Going fluent is an obvious (in retrospect) choice for configuration. You are almost inspiring me to go back to Phemto.

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

  2. #52
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks. It feels good to be alive. And spooky seems appropriate for October.

    I've made some syntax changes.

    Assigning a singleton value to the container:
    PHP Code:
    $registry->key 'value';
    $registry->set('key''value'); 
    Reading a value from the container
    PHP Code:
    $value $registry->StdClass;
    $value $registry->get('StdClass');
    $value $registry->ifsetor('StdClass'FALSE); 
    The first two forms will return a previous instance of the specified class, or create a new instance.
    The Third form does not create new values, but rather returns a default value if the key does not exist.

    You can also use the registry to create new instances of objects.
    PHP Code:
    $value $registry->create('MyClass', array('param1'));
    $value $registry->createMyClass('param1'); 
    Both of these forms allow you to pass a list of parameters to the constructor of the class. If a required parameter is not specified, the container attempts to locate it.

    Another hybrid form will return a singleton if it exists, or attempt to create the new instance if not, using the specified parameters.
    PHP Code:
    $value $registry->get('MyClass', array('param1')); 
    Normally, the registry would use reflection to attempt to inject required dependencies into any object you request. By default, only required constructor parameters are injected. If the parameter has a typehint, the registry looks for an instance matching the specified type. If there is no typehint, the registry looks at the docblock to determine the type. When both the docblock and typehint exist, the docblock takes precidence.

    You can also define a factory for creating instances using the define method and a fluent interface. Parameters specified this way take precedence over any declared on the class.

    There are three forms of define. The first is roughly equivalant to the simple set scenario above.

    PHP Code:
    $registry->define('foo')->asValue('bar');
    echo 
    $registry->foo// bar 
    The second, more complicated form allows you to specify constructor parameters and can inject public property values and call setter methods. Additionally, there are three forms for each type of injection: Value, Type, and Required. Here are all nine methods:

    PHP Code:
    $registry->define('foo')->asClass('bar')
        ->
    parameterValue('name''value')
        ->
    parameterType('name''class')
        ->
    parameterRequired('name')
        ->
    propertyValue('name''value')
        ->
    propertyType('name''class')
        ->
    propertyRequired('name')
        ->
    setterValue('setName''value')
        ->
    setterType('setName''class')
        ->
    setterRequired('setName'); 
    When a class is constructed, the xxxValue form injects a simple value. The xxxType form injects an instance of the specified type, if available. The container prefers to re-use existing values. the xxxRequired form simply indicates that the container must attempt to inject the parameter but that it should determine the type based on reflection.

    Setters also have a shortcut form. The following are equivalanet

    PHP Code:
        ->setterValue('setName''value');
        ->
    setName('value'); 
    This demonstrates the third form of the define method:

    PHP Code:
    $registry->bar 'baz';
    $registry->define('foo')->asAliasToType('bar');
    echo 
    $registry->foo// baz 
    the current state of the code:
    wact/config

    future directions
    • Currently, you define the lifecycle of an object by how you call the container. Might we enforce that an object must be a singleton or a new prototype on each call? In this case, we might be able to merge the create() and get() methods.
      I made a stab at lifecycle support, but things turned ugly fast. I'm going to hold off on this until I have more experience using the class.
    • Performance optimization & caching. I'm leaving this one for later.
    • More support around child containers and fallback. I just have no idea how the use cases for this will play out. I intend to delay.
    • I could add @inject doc comments to properties and setters to force them to be treated as required parameters by the container and to allow that definition on the class level.
    • Reading config files
    • There is currently no support for class inheritance when attempting to satisfy a dependency. The container only attempts to inject exactly the type specified as defined in the container. Should there be more leeway?


    Any comments?

  3. #53
    ********* 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 View Post
    Currently, you define the lifecycle of an object by how you call the container. Might we enforce that an object must be a singleton or a new prototype on each call? In this case, we might be able to merge the create() and get() methods.
    What about session based (sort of semi-persistent) objects? This kind of stuff pushes me to make the internal factory classes visible/overridable/extendable.

    Quote Originally Posted by Selkirk View Post
    I made a stab at lifecycle support, but things turned ugly fast. I'm going to hold off on this until I have more experience using the class.
    My current plan is to dive head first down this particular rabbit hole. What problems did you have in mind?

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

  4. #54
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As much as I like the createClass syntax, I think I might consolidate down to just the get() syntax in the name of simplicity. If I really need separate operations, it seems like a use case will come up and I can add it back then.

    If I do that, defining lifecycles will probably be easier. My problems before were just that the interface became too complex. The code also ended up with alot of special cases depending on lifecycle. I need to think more about a way to generalize it.

    I think that rather than have the factories or the container manage lifecycles, they may need to delegate that to another type of object. Is there a need for any other lifecycles beyond prototype, singleton, or session?

    I did some investigation of real production code and how it did configuration and object construction. This was not easy, with a few late nights. I think I've identified five basic access patterns:
    1. getInstanceRequirePriorDefinition
      PHP Code:
      $instance $container->var
    2. getInstanceIfDefined
      PHP Code:
      if (isset($container->var)) {
          
      $instance $container->var;

    3. getInstanceOrDefineIfNotDefined
      PHP Code:
      if (isset($container->var)) {
          
      $instance $container->var;
      } else {
          
      $instance 'value';
          
      $container->var $instance;

    4. defineOrReplaceExistingDefinition
      PHP Code:
      $container->var 'value';
      // don't need instance right now. 
    5. defineIfNotDefined
      PHP Code:
      if (empty($container->var)) {
          
      $container->var 'value';
      }
      // don't need instance right now. 

    Now I just need more concise method names to match.

    I've used a simple php value here, but the concept of "define" can get very complex, as the prior factory examples show.


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
  •