SitePoint Sponsor

User Tag List

Results 1 to 22 of 22
  1. #1
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Object composition by Proxy

    Standard PHP has a mechanism for specifying a reference to an object and a method to call it:

    PHP Code:
    $ref = array(&$obj"methodName");
    $params = array("hello""world");
    call_user_object_array($ref$params); 
    In PHP 5, the overloading method could be used with this to create a proxy object which re-routed method calls:

    PHP Code:
    // Untested
    class ProxyReference {

        var 
    $Obj;
        var 
    $Ref;
        var 
    $File;
        var 
    $Class;
        var 
    $Method;

        function 
    Proxy($File$Class$Method) {
            
    $this->File $File;
            
    $this->Class $Class;
            
    $this->Method $Method;
        }

        function 
    __call($method$params, &$return) {
            if (!
    is_object($this->Obj)) {
                require_once 
    $this->File;
                
    $this->Obj =& new $this->Class(); //syntax correct?
                
    $this->Ref = array(&$this->Obj$this->Method);
            }
            
    call_user_object_array($this->Ref$params);
        }

    This ProxyReference class has the feature of not instantiating the object called unless a call is actually made. This is almost like a generic decorator.

    This could be used to transparently compose objects:

    PHP Code:
    class SomeClass {
        var 
    $Obj
        
    function SomeClass($ReferenceObj) {
            
    $this->Obj =& $ReferenceObj;
        }

        function 
    RarelyCalledMethod($Parameter) {
            
    $this->Obj->DoSomething($Parameter);
        }

    So, correct me if I am wrong, but it is possible in PHP5 for the SomeClass Object to be completely unaware of the fact that the object it is using is a proxy for another object. The SomeClass object is complete unaware that the real object it is communicating with has not been loaded.

    SomeClass makes a normal method call. The call_user_object_array business is encapsulated in the ProxyReference class.

    My question is, Is it possible to do this in PHP 4? If not, how close can you get?

    One use I see for this is in creating a GenericDecorator class. This might only be possible in PHP 5. The advantage of a GenericDecorator (performance considerations aside for a moment) is that you could decorate any object without having to declare its entire interface. Only the part you wished to decorate. Thus, when you changed the object being decorated, you might not necessarily have to change the decorator classes. A good dependency limiter, resulting is less code for the same thing.

    The use that I am interested in is creating on demand references in PHP 4. I want to minimize the effort involved with invoking an on-demand reference by encapsulating the call as much as possible. In other words, I should not have to copy/paste/modify a block of code like the implementation of the __call method in the ProxyReference object for every method invocation on the object in the RarelyCalledMethod invocation.

    The context is creating objects that persist across several HTTP requests. I would like to construct the object as if it were going to persist across several requests. This object is composed of several other objects. Only a small subset of the objects in the assembly will actually be called on each HTTP requests. Over the course of the sequence of requests, most of the objects will be called. Since the object assembly can't persist across requests, I want to limit the cost of re-instantiating it each time, by not actually instantiating the portions of the assembly which are not not used. Yet, I want my construction code to be unaware of which portions of the assembly will or won't be used during each request. (The same construction code should get executed for each request.)

    I am not sure if I have been very clear about what I am looking for, but I was hoping for some ideas.

  2. #2
    SitePoint Member
    Join Date
    Dec 2003
    Location
    ---
    Posts
    22
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi!

    Quote Originally Posted by Selkirk
    My question is, Is it possible to do this in PHP 4? If not, how close can you get?
    http://hu.php.net/manual/en/ref.overload.php
    This is not good for you?

    Felho

  3. #3
    SitePoint Evangelist ghurtado's Avatar
    Join Date
    Sep 2003
    Location
    Wixom, Michigan
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you dont want to use the overloading extension, lastcraft posted this possible implementation for Decorators in PHP4, not too long ago:
    http://www.sitepoint.com/forums/show...ight=decorator

  4. #4
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Think I can see what you're trying to do and very powerful it would be if it can be done - suddenly it's worth persisting large numbers of objects.

    Off the top of my head, one way to do it (and perhaps the only way) is to generate proxy classes (active generation) although a factory will be needed to get references to them. Something like;

    PHP Code:
    <?php
    class ProxyFactory {
        function & 
    getProxy($Class,$File) {
            
    $this->Class $Class;
            
    $this->File $File;

            
    $this->checkProxyExists();

            include_once 
    $File_Proxy;

            
    $ProxyClass $Class."_Proxy";
            return new 
    $ProxyClass();
        }

        function 
    checkProxyExists() {
            
    // Something cleverer needed here, to check times / versions
            
    if (!file_exists($this->File) ) {
                
    $this->generateProxy();
            }
        }

        function 
    generateProxy() {
            include_once 
    $this->File;
            
    $Methods get_class_methods($this->Class);

            
    // Insert code here the creates class and defines stub methods
        
    }
    }
    ?>
    PHP Code:
    <?php
    // Here's the generated proxy code
    class SomeClass_Proxy {
        var 
    $__realInstance NULL;
        function & 
    __getRealInstance() {
           include_once 
    "SomeClass.php";
           if ( ! 
    $this->__realInstance ) {
               
    $this->__realInstance = & new SomeClass();
           }
           return 
    $this->__realInstance;
        }

        function 
    RarelyCalledMethod() {
           
    $args = & func_get_args();
           
    $obj =  & $this->__getRealInstance();
           
    $ref = array(&$obj,'RarelyCalledMethod');
           return 
    call_user_func_array($ref,$args);
        }
    }
    ?>
    Not 100% sure that meets all the requirements but getting there perhaps. The first time a proxy is ever needed, it will have the overhead of included the real class. After that, it should be a fairly lightweight class and "lazy instantiates" the real class it's proxying for.

    One issue might be whether the proxy RarelyUsedMethod should return a reference or copy of the result it gets from calling the real RarelyUsedMethod. For that I don't know.

  5. #5
    ********* 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
    My question is, Is it possible to do this in PHP 4? If not, how close can you get?
    This works on PHP 4.3.0 (my current home version)...
    PHP Code:
    <?php
    class LazyProxy {
        var 
    $_wrapped;
        var 
    $_parameters;
        var 
    $_class;
        
        function 
    LazyProxy() {
            
    $this->_wrapped false;
            
    $this->_parameters func_get_args();
            
    $this->_class array_shift($this->_parameters);
        }
        
        function &
    _instantiate() {
            
    $parameter_names = array();
            for (
    $i 0$i count($this->_parameters); $i++) {
                
    $parameter_names[$i] = "\$this->_parameters[$i]";
            }
            
    $parameter_code implode(', '$parameter_names);
            
    $code "\$instance = &new " $this->_class "($parameter_code);";
            eval(
    $code);
            return 
    $instance;
        }
        
        function 
    __call($method$parameters, &$result) {
            if (
    $this->_wrapped === false) {
                
    $this->_wrapped = &$this->_instantiate();
            }
            if (
    method_exists($this->_wrapped$method)) {
                
    $result call_user_func_array(
                        array(
    $this->_wrapped$method),
                        
    $parameters);
                return 
    true;
            }
            return 
    false;
        }
    }
    overload('LazyProxy');
    ?>
    Here is the rather messy test case...
    PHP Code:
    <?php
    define
    ('SIMPLE_TEST''simpletest/');
    require_once(
    SIMPLE_TEST 'unit_tester.php');
    require_once(
    SIMPLE_TEST 'reporter.php');
    require_once(
    'lazy_proxy.php');

    class 
    Prefixer {
        var 
    $_prefix;
        
        function 
    Prefixer($prefix) {
            
    $this->_prefix $prefix;
            
    $this->countInstances(true);
        }
        function 
    prefix($message) {
            return 
    $this->_prefix $message;
        }
        function 
    countInstances($another false) {
            static 
    $count 0;
            if (
    $another) {
                
    $count++;
            }
            return 
    $count;
        }
    }

    class 
    TestOfLazyProxy extends UnitTestCase {
        function 
    TestOfLazyProxy() {
            
    $this->UnitTestCase();
        }
        function 
    testProxyWrapsClass() {
            
    $start Prefixer::countInstances();
            
    $proxy = &new LazyProxy('Prefixer''Hello ');
            
    $this->assertEqual($startPrefixer::countInstances());
            
    $this->assertEqual($proxy->prefix('Jeff'), 'Hello Jeff');
            
    $this->assertEqual($start 1Prefixer::countInstances());
            
    $this->assertEqual($proxy->prefix('Harry'), 'Hello Harry');
            
    $this->assertEqual($start 1Prefixer::countInstances());
        }
    }

    $test = &new TestOfLazyProxy();
    $test->run(new HtmlReporter());
    ?>
    I am dropping references all over the place here. Without proper reflection I have the same problem as with code generation. i.e. func_get_args() copies parameters.

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

  6. #6
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    I am dropping references all over the place here. Without proper reflection I have the same problem as with code generation. i.e. func_get_args() copies parameters.
    Well...it is ugly but the:
    PHP Code:
    $decorated_object->method( array(&$object) ); 
    should be a way around that.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  7. #7
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Think the problem there is the "overload extension" only became a default part of PHP with 4.3.0 (I think).

    Also there was a weird bug with __call() - if you declare it, suddenly your own class methods cease to be able to return values. For example;

    PHP Code:
    <?php
    class Test {
        var 
    $test;
        function 
    Test () {
            
    $this->test='Hello World';
        }

        function 
    getTest () {
            return 
    $this->test;
        }

        function 
    __call () {

        }
    }

    // Declare the class as overloaded
    overload ("Test");

    $test=new Test;

    echo ( 
    $test->getTest() ); // This returns nothing
    echo ( $test->test ); // This works.
    ?>
    Can't say I'd want to rely on the PHP4 implementation.

  8. #8
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Before I lose the link, there's a nice article here: An introduction to object prevalence, and Prevayler. Only vaguely related, as implementing it in PHP would probably only be worthwhile if you're using Shared memory.

  9. #9
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, after some thought, I realized another way to express what I am looking to do. I want to be able to reference a class and have that reference include the information for finding that class. (similar to autoload) This is like in Java where a class name in com.x.x.x.classname format combined with a class path is sufficient for loading that class.

    I need to have a solution that works in PHP 4.1 or better.

    Here is what I have so far:

    PHP Code:
    function ResolveReference(&$Reference) {
        if (!
    is_object($Reference) && !is_null($Reference)) {
            if (
    is_string($Reference)) {
                if (
    is_integer($Pos strpos($Reference':'))) {
                    
    $File substr($Reference0$Pos);
                    
    $Class substr($Reference$Pos 1);
                    require_once 
    $File;
                } else {
                    
    $Class $Reference;
                }
            }
            
    $Reference = new $Class();  // =& doesn't work here.  Why?
        
    }
    }

    class 
    SomeClass {
        var 
    $Ref;
        function 
    registerReference(&$Ref) {
            
    $this->Ref =& $Ref;
        }
        function 
    someMethod() {
            
    ResolveReference($this->Ref);
            
    $this->Ref->someOtherMethod();
        }

    To Create a SomeClass and use a SomeOtherClass with it:

    PHP Code:
    $Some =& new SomeClass();

    // Alternatives
    $Some->RegisterReference('SomeOtherClass');
    $Some->RegisterReference('/path/file.php:SomeOtherClass');  
    $Some->RegisterReference(new SomeOtherClass()); 
    I have tested the ResolveReference function, not the SomeClass part of this.

    The advantage of this method is that I can pass an object or a PHP 4.3+ LazyProxy, or a simple classname, or a classname with a file specification.

    The disadvantage is that the ResolveReference helper function has to be called on any variable holding a reference before that reference can be used.

    I love to find a better way to do this.

    Next up, I would like to expand the concept of the reference to include parameters to the constructor. The problem I have is that there is no call_user_function_array equivalent that can create an object. Unless I am missing something.

    Here is what I want to do. (Not sure which syntax is best, yet)

    PHP Code:
    class SomeOtherClass {
        
    SomeOtherClass($templateFile) {
        ...
        }
    }

    $Some =& new SomeClass();

    // Alternatives
    $Some->RegisterReference(array('SomeOtherClass''template.html'));
    $Some->RegisterReference(array('SomeOtherClass', array('template.html'))); 

  10. #10
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    On the second problem; passing a variable number of arguments to a constructor, here's a tip off from the PHP manual under eval();

    PHP Code:
    <?php
    function classFactory($classname)
    {
       
    $code "return new {$classname}(";
       if (
    func_num_args() > 1) {
           
    $params array_slice(func_get_args(),1);
           
    $c count($params);
           for(
    $i=0;$i<$c;++$i) {
               if (
    $i>0) {
                   
    $code .= ',';
               }
               
    $code .= '$params[' $i ']';
           }
       }
       
    $code .= ');';
       return eval(
    $code);
    }

    class 
    Foo
    {
       function 
    Foo($arg1,$arg2,$arg3)
       {
           echo 
    "I am Foo, I expect 3 arguments...\n";
           echo 
    "arg1 = $arg1\n";
           echo 
    "arg2 = $arg2\n";
           echo 
    "arg3 = $arg3\n\n";
       }
    }

    class 
    Bar
    {
       function 
    Bar($arg1)
       {
           echo 
    "I am Bar, I expect 1 argument...\n";
           echo 
    "arg1 = $arg1\n\n";
       }
    }

    $myFoo classFactory('Foo',100,'moose',array(1,2,3));
    $myBar classFactory('Bar',4564);
    ?>
    [/php]

  11. #11
    ********* 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 HarryF
    On the second problem; passing a variable number of arguments to a constructor, here's a tip off from the PHP manual
    I used that in the LazyProxy::_instantiate() method above .

    Jeff, can you express what you want as a test case? It sounds like a fun problem, but I am not exactly sure I understand everything.

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

  12. #12
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am prejudiced against eval.

    Here is my Test case for the ResolveReference Function:

    PHP Code:
    class UnaffectedObject {
        var 
    $testVar 'default';
    }

    class 
    DeclaredInSameFile {
        var 
    $testVar 'default';
        function 
    DeclaredInSameFile($Var 'constructionDefault') {
            
    $this->testVar $Var;
        }
    }

    class 
    ReferenceTestCase extends UnitTestCase {
        function 
    ReferenceTestCase($name 'ReferenceTestCase') {
            
    $this->UnitTestCase($name);
        }

        function 
    testNullReference() {
            
    $Ref NULL;
            
    ResolveReference($Ref);
            
    $this->assertNull($Ref);
        }

        function 
    testObjectUnaffected() {
            
    $Ref =& new UnaffectedObject();
            
    $Obj =& $Ref;
            
    $Obj->testVar 'Changed';
            
    ResolveReference($Ref);
            
    $this->assertIsA($Ref'UnaffectedObject');
            
    $this->assertIdentical($Ref$Obj);
            
    $this->assertEqual($Ref->testVar'Changed');
        }

        function 
    testClassDeclaredInSameFile() {
            
    $Ref 'DeclaredInSameFile';
            
    ResolveReference($Ref);
            
    $this->assertIsA($Ref'DeclaredInSameFile');
        }

        function 
    testLoadClassFile() {
            
    $this->assertFalse(class_exists('LoadedReferenceClass'));
            
    $Ref dirname(__FILE__) . '/reference.inc.php:LoadedReferenceClass';
            
    ResolveReference($Ref);
            
    $this->assertIsA($Ref'LoadedReferenceClass');
            
    $this->assertTrue(class_exists('LoadedReferenceClass'));
        }
        
        function 
    testConstructor() {
            
    $Ref = array('DeclaredInSameFile''ConstructionParameter');
            
    ResolveReference($Ref);
            
    $this->assertIsA($Ref'DeclaredInSameFile');
            
    $this->assertEqual($Ref->testVar'ConstructionParameter');
        }
        

    Here is Reference.inc.php (part of the test case):

    PHP Code:
    class LoadedReferenceClass {
        var 
    $testVar 'default';


  13. #13
    SitePoint Zealot
    Join Date
    Feb 2003
    Location
    Virginia
    Posts
    143
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok. As promised, Ghost.

    PHP Code:
     <?php 
    class Ghost
    {
     private 
    $object;
     private 
    $filterList = array();
     private 
    $observerList = array(); //Exercise for you
     
    private $decoratorList = array(); //Exercise for you
     
     
    function Ghost($objectName)
     {
      
    $this -> object = new $objectName();
     }
     
     function 
    __call($function$args)
     {
      
    $data $this -> object -> $function ($args);
      
      foreach (
    $this -> filterList[$function] as $objName => $obj)
      {
       echo 
    "<BR>I am a filter named ".$obj -> filter($objName);
       
    $data $obj -> filter($data);
      }
      return 
    $data;
     }
     
     function 
    addFilter($function$obj)
     {
      
    $this -> filterList[$function][get_class($obj)] = $obj;
     }
    }
    //End Ghost class
     
     
    class Secret
    {
     private 
    $secret "Cows really CAN jump over the moon!";
     
     function 
    getSecret()
     {
      return 
    $this -> secret;
     }
    }
    //End Secret class
     
     
    class ItalicFilter
    {
     function 
    filter($data)
     {
      return (
    "<I> $data </I>");
     }
    }
    //End ItalicFilter class
     
     
    class BoldFilter
    {
     function 
    filter($data)
     {
      return(
    "<B> $data </B>");
     }
    }
    //End BoldFilter class
     
     
     
    $test = new Ghost('Secret');
    $test -> addFilter("getSecret", new BoldFilter);
    $test -> addFilter("getSecret", new ItalicFilter);
    echo (
    "<BR>".$test -> getSecret());
    ?>

    The neat thing about this "proxy"/"factory" pattern I call Ghost is that it can be very flexable. The class objects that were passed in can be lazy loaded or added as objects. One could also add observers and decorators just as easily!

    This class might proove to be a great test root as well since Secret has no idea its being shadowed - though I would suggest adding a few safe guards in case the output is error code or not of same type as expected to be output. I would also suggest adding an interface to the Filters.. Ok, you could see that one right?

    Anyhow, its strange I got this idea/concept while reading this post. I read up on Slots and Signals , AOP and AspectJ - took a nap woke up a few hours later with the idea you now see before you.

    So, does this solution seem to help or did I just make yet another wheel?

    Cheers,
    Res

  14. #14
    SitePoint Zealot
    Join Date
    Feb 2003
    Location
    Virginia
    Posts
    143
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's the output...

    I am a filter named boldfilter
    I am a filter named italicfilter
    Cows really CAN jump over the moon!

  15. #15
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Upon further testing, I've run into an unfortunate snag.

    Earlier I had a list of alternative ways to call my RegisterReference function:

    PHP Code:
    // Alternatives
    $Some->RegisterReference('SomeOtherClass');
    $Some->RegisterReference('/path/file.php:SomeOtherClass');  
    $Some->RegisterReference(new SomeOtherClass()); 
    It turns out that this cannot work based on my definition of RegisterReference:

    PHP Code:
        function registerReference(&$Ref) {
            
    $this->Ref =& $Ref;
        } 
    Since the RegisterReference takes has a reference parameter, you cannot pass a constant value to this function.

    It seems that I am forced to choose between taking a constant and loosing the ability to pass an already instantiated object (or Proxy Object) OR taking only an object and loosing the simplicity of being able to pass in a class name as a string. (which has some backward compatibillity issues for my purposes.)

    Here is an example of how I wanted to use this capability in WACT:
    PHP Code:
    require '../configure.inc.php';
    require_once 
    WACT_ROOT '/controller/formpage.inc.php';

    define('LOCAL_PATH'dirname(__FILE__));

    $Form = new FormPage();
    $Form->registerView(LOCAL_PATH '/formview.inc.php:CategoryFormView');
    $Form->registerValidator(LOCAL_PATH '/validator.inc.php:CategoryValidator');
    $Form->registerSubmitAction('preview'WACT_ROOT '/controller/noaction.inc.php:NoAction');
    $Form->registerSubmitAction('add'LOCAL_PATH '/add.inc.php:AddCategory'PRE_VALID);
    $Form->registerDefaultSubmitAction(LOCAL_PATH '/add.inc.php:AddCategory'PRE_VALID); 
    $Form->Run(); 
    I also wanted to be able to support something like this alternative usage of the same thing (or the ability to mix and match from either style):

    PHP Code:
    require '../configure.inc.php';
    require_once 
    WACT_ROOT '/controller/formpage.inc.php';

    require 
    'formview.inc.php';
    require 
    'validator.inc.php';
    require 
    'add.inc.php';

    require 
    WACT_ROOT '/controller/noaction.inc.php';

    $Form = new FormPage();
    $Form->registerView(new CategoryFormView());
    $Form->registerValidator(new CategoryValidator());
    $Form->registerSubmitAction('preview', new NoAction());
    $Form->registerSubmitAction('add',new AddCategory(), PRE_VALID);
    $Form->registerDefaultSubmitAction(new AddCategory(), PRE_VALID); 
    $Form->Run(); 
    However, it seems that I can only have one or the other because of the reference parameter on the register functions. I don't like to remove the reference because then any objects that get passed in will get cloned, potentially leading to subtle bugs. I would almost rather remove the capability to pass in objects altogether.

  16. #16
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here was a thread on using the array(&$obj) wrapper to allow for either a constant (simple string declaration) or a object by ref. It was not pretty, but it did seem functional

  17. #17
    Non-Member
    Join Date
    Jan 2004
    Location
    Planet Earth
    Posts
    1,764
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Do you mean the following, where by PHP throws up an error ?

    PHP Code:

    $hello 
    = &new Hello'Hello World' );
    ...

    class 
    Hello {
    function 
    Hello( &$variable ) {
    ... } 

    Just wondering really, as if this is the case, does the function you mention in the link actually work okay ?

    Thanks.

  18. #18
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Widow Maker
    Just wondering really, as if this is the case, does the function you mention in the link actually work okay?
    In instances where I have needed it, it has worked fine. Consider:
    PHP Code:
    class foo {
      var 
    $p;
      function 
    foo ($parm) {
        
    $this->$parm;
      }
    }

    class 
    bar {
      var 
    $foo;
      function 
    bar ($foo_in) {
        if (!
    $foo =& obj_from_envelope($foo_in)) {
          
    $foo =& new foo($foo_in);
        }
        
    $this->foo =& $foo;
      }

    Now for bar, I can pass either a string to use as the parameter for creating a new foo, or an array containing a reference to an already created foo.

    HTH

  19. #19
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for finding that, sweatje. The envelope technique has eased my mind a bit about removing the reference from the parameter. There is no perfect solution in PHP 4, but at this this should be forward compatible with PHP 5.

    I ran across this related blog entry today and now I wish I had used the same title for this thread:

    Lazy Evaluation and Object Composition

  20. #20
    Non-Member
    Join Date
    Jan 2004
    Location
    Planet Earth
    Posts
    1,764
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So it works then ? That is really cool - Okay for me to use the function SweatJe - Sure to find a use for it

  21. #21
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Widow Maker
    Okay for me to use the function SweatJe
    I pretty much consider anything I put up on the boards fair game. Perhaps you could leave in a comment of
    Code:
     * @author    Jason E. Sweat
    in the function doc block, and I would be interested in hearing about any use in a open source project.

  22. #22
    Non-Member
    Join Date
    Jan 2004
    Location
    Planet Earth
    Posts
    1,764
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No problem


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
  •