SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    SitePoint Enthusiast dgx's Avatar
    Join Date
    Aug 2005
    Location
    The Czech Republic
    Posts
    25
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Lightbulb New way how to emulate PHP5's object model in PHP4

    (sorry for my poor english)

    I spent a lot of time thinking, how to emulate some PHP5's object model features in older PHP4. How get rid tons of ampersands in my source codes. How force objects to not copy itself every time.

    (latest version is here: http://www.dgx.cz/trine/item/the-amp...-mania-is-over)

    Look at this example:

    PHP Code:
    <?php 
    class MyClass 
        var 
    $parent
        var 
    $children = array(); 

        
    // this is PHP5 constructor 
        
    function __construct($parent null
        { 
            if (
    $parent !== null) { 
                
    $this->parent $parent
                
    $parent->addChild($this); 
            } 
        } 


        function 
    addChild($child
        { 
            
    $this->children[] = $child
        } 



    $parent = new MyClass(); 
    $child1 = new MyClass($parent); 
    $child2 = new MyClass($parent); 
    ?>
    In PHP5 it results in:

    Code:
    $parent = MyClass Object
    (
        [parent] => NULL
        [children] => Array (
                [0] => MyClass Object
                    (
                        [parent] => MyClass Object *RECURSION*
                        [children] => Array ()
                    )
    
                [1] => MyClass Object
                    (
                        [parent] => MyClass Object *RECURSION*
                        [children] => Array ()
                    )
            )
    )
    But in PHP4 $parent->children will remain empty. Because of „copying“ object model and PHP5-like constructor.

    Code:
    $parent = MyClass Object
    (
        [parent] => NULL
        [children] => Array ()
    )
    The trick:

    Ladies and gentlemen, now I'll force this example to work in PHP4. And it is very easy!

    PHP Code:
    <?php
    require_once 'php4compat.php';

    class 
    MyClass extends compatClass4 {
    .....
    }
    ?>
    All the magic is hidden in php4compat.php file. You can download it.

    How it works? Php4Compat checks PHP version. For PHP5 it creates empty class compatClass4, with no methods or variables, just for compatibility purposes. But in PHP4 it creates „magic“ class compatClass4 and function clone().

    Class compatClass4 declares PHP4 constructor compatClass4(). Its task is turn each object's variables into references and call PHP5-like constructor __construct().

    It uses this princip:

    PHP Code:
    <?php
    // notice, this argument is not passed by reference
    function changeFirst($arr) {
    ****
    $arr[0] = 'CHANGED';
    }

    // array stay unchanged:
    $arr = array('first''second');
    changeFirst($arr);
    // $arr = array('first', 'second')


    // and now array will be changed
    $arr = array('first''second');
    $x 'test';
    $arr[0] = &$x;
    changeFirst($arr);
    // $arr = array('CHANGED', 'second')


    // now too
    $arr = array('first''second');
    $x = & $arr[0];
    changeFirst($arr);
    // $arr = array('CHANGED', 'second')


    // (in this example you can replace arrays by objects)
    ?>
    Object clonning:

    PHP4 & PHP5 compatible way is:

    PHP Code:
    <?php
    ....
    $parent = new MyClass();
    $dolly = clone ($parent);
    $child1 = new MyClass($parent);
    $child2 = new MyClass($dolly);
    ....
    ?>
    PHP5 has clone keyword, PHP4 has function clone() – therefore we must use parentheses.

    Known limitations:

    1) It is not possible to unset or creates non-declared object's variables

    2) It is not possible to assign references into object's variables

    ad 1)

    will not work:

    PHP Code:
    <?php
    class MyClass extends compatClass4 {
    }
    $object = new MyClass()
    $object->var 10// $var is not declared!
    ?>
    correct:

    PHP Code:
    <?php
    class MyClass extends compatClass4 {
    **var 
    $var;
    }
    $object = new MyClass()
    $object->var 10;
    ?>
    Notice: I think it is not serious limitation, because good programmers use only declared variables

    ad 2)

    will not work:

    PHP Code:
    <?php
    $object 
    = new MyClass()
    $b 'La Trine';
    $object->var = & $b;
    ?>
    correct:

    PHP Code:
    <?php
    $object 
    = new MyClass()
    $b = & $object->var;
    $b 'La Trine';
    ?>
    or:

    PHP Code:
    <?php
    $object 
    = new MyClass()
    $b 'La Trine';
    $object->var = array( &$b );
    ?>

    That's all folks :-)

    Author: David Grudl, developer of GPL project Texy!

  2. #2
    SitePoint Evangelist ghurtado's Avatar
    Join Date
    Sep 2003
    Location
    Wixom, Michigan
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have to say that if all of my classes had to subclass a common parent only for the benefit of getting rid of ampersands in referenced parameters, well, to me that's a definite example of the cost heavily outweighing the benefits.

    It would require changes to many more files to change every single class in your project (for the benefit of only a few) than it would to simply use ampersands where you need them and then remove them once you upgrade to PHP 5 (or not, as I understand it you can leave them there without a problem).
    Garcia

  3. #3
    SitePoint Enthusiast dgx's Avatar
    Join Date
    Aug 2005
    Location
    The Czech Republic
    Posts
    25
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ghurtado
    I have to say that if all of my classes had to subclass a common parent only for the benefit of getting rid of ampersands in referenced parameters, well, to me that's a definite example of the cost heavily outweighing the benefits.
    Let's summarize where ampersands are needed:
    - creating objects: $object = &new MyClass()
    - assignments: $objectB = & $objectA
    - passing to functions: function doIt(& $object)
    - returning from functions (part 1): function &getInstance()
    - returning from functions (part 2): $object = &getInstance()
    and one missing ampersand = hardly-discovered bug :-(

    this structures couldn't be used:
    - foreach ($objects => $object)
    - list($object1, $object2) = $objects;
    - function defaultParam(&$object = null)

    and - in PHP 4.4.0 this leads to error message (E_NOTICE):
    function &factory() { return new myclass() }

    It can become a thing of the past - the only modification you need to do is extends base classes. And you can use PHP5-like constructors!

    Quote Originally Posted by ghurtado
    It would require changes to many more files to change every single class in your project (for the benefit of only a few) than it would to simply use ampersands where you need them and then remove them once you upgrade to PHP 5 (or not, as I understand it you can leave them there without a problem).
    It is not so easy to upgrade scripts to PHP5. You cannot automatically remove all ampersands. But with this method you can write batch script to convert between PHP4 <--> PHP5.

    I develop text-2-html converter Texy! in PHP5. And PHP4 version is automatically generated by batch script. It removes all keywords as public, protected, etc. and replace 'class XYZ {' to 'class XYZ extends compatClass4 {'.

    (I dream about the world, where PHP4 is over and every hostings use PHP5 :-)

  4. #4
    SitePoint Addict
    Join Date
    May 2005
    Posts
    255
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wouldn't it be less effort to just upgrade to PHP5? If your host doesn't support it, find a new host. I can name you 2 really great ones off the top of my head that have it ready to go: Dreamhost & Nexcess.

  5. #5
    SitePoint Enthusiast dgx's Avatar
    Join Date
    Aug 2005
    Location
    The Czech Republic
    Posts
    25
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Etnu
    Wouldn't it be less effort to just upgrade to PHP5? If your host doesn't support it, find a new host. I can name you 2 really great ones off the top of my head that have it ready to go: Dreamhost & Nexcess.
    It is not answer. Sometimes you can't change host, for whatever cause. And when you develop open source software which should run nearly everywhere? One year after releasing PHP5, there are major part of hosts with PHP4 only. I mind it, but it is reality.

    Etnu, I am using PHP5. My solution is only (original) way, how to emulate PHP5 OOP in PHP4. Nothing more. I believe it will be useless in a year, because every host will have PHP 5.5 :-)

  6. #6
    SitePoint Member
    Join Date
    Apr 2005
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    good idea.

  7. #7
    SitePoint Addict
    Join Date
    May 2005
    Posts
    255
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dgx
    It is not answer. Sometimes you can't change host, for whatever cause. And when you develop open source software which should run nearly everywhere? One year after releasing PHP5, there are major part of hosts with PHP4 only. I mind it, but it is reality.

    Etnu, I am using PHP5. My solution is only (original) way, how to emulate PHP5 OOP in PHP4. Nothing more. I believe it will be useless in a year, because every host will have PHP 5.5 :-)
    Open source is actually where we need to put the most pressure on people to upgrade. Let users of proprietary code have stagnation all they want. Lord knows there isn't enough of that already.

    I'm continually baffled by the number of people who complain about the slow rate of technology improvements over the last few years who refuse to install Apache 2 until it's got a .1 release (it's been out for 5 years, people...).


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
  •