SitePoint Sponsor

User Tag List

Page 1 of 3 123 LastLast
Results 1 to 25 of 73

Hybrid View

  1. #1
    SitePoint Addict pachanga's Avatar
    Join Date
    Mar 2004
    Location
    Russia, Penza
    Posts
    265
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Upgrading scripts to conform to PHP 4.4 ref. implementation

    Folks, is there any PHP 4.4 upgrading paper? There's very nice PHP 5.1 upgrading manual but i couldn't find anything on PHP 4.4 while its new reference implementation breaks tons of existing scripts.

    Basically, all return/pass by reference calls should be changed. e.g the following code:

    PHP Code:
    function &Foo($id) {
       if(isset(
    $arr[$id]))
         return 
    $arr[$id];

    becomes:

    PHP Code:
    function &Foo($id) {
       if(isset(
    $arr[$id]))
         return 
    $arr[$id];

       
    $zref null;
       return 
    $zref;

    But i wonder why this triggers a notice then:

    PHP Code:
    function &Foo($id) {
       if(isset(
    $arr[$id]))
         return 
    $arr[$id];

       return 
    $zref null;

    At the same time the following code works just fine:
    PHP Code:
    function foo(&$arr) {
      
    $arr[] = 3;
    }

    foo($arr = array(12)); 
    And in the following case "return parent :: foo()" in Bar::foo() shouldn't be changed:
    PHP Code:
    class Foo {
      var 
    $ref 1;
      function & 
    foo() {
        return 
    $this->ref;
      }
    }

    class 
    Bar extends Foo {
      function & 
    foo() {
        return 
    parent :: foo();
      }

    Which means, i guess, that if the function declared with & and returns reference, there's no need in temporary variable when returning its result.

    Any other issues like those i mentioned?

  2. #2
    SitePoint Author silver trophybronze trophy

    Join Date
    Nov 2004
    Location
    Ankh-Morpork
    Posts
    12,159
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by pachanga
    Basically, all return/pass by reference calls should be changed. e.g the following code:

    PHP Code:
    function &Foo($id) {
       if(isset(
    $arr[$id]))
         return 
    $arr[$id];

    That is really poor programming style. If a function returns a reference, you really should have an unconditional 'return' statement.

    Quote Originally Posted by pachanga
    But i wonder why this triggers a notice then:

    PHP Code:
    function &Foo($id) {
       if(isset(
    $arr[$id]))
         return 
    $arr[$id];

       return 
    $zref null;

    The result of '$zref = null' is 'null', which allows you to do assignment chains like '$a=$b=$c=0'. Null is a value, and you cannot return a reference to a value.

    Quote Originally Posted by pachanga
    At the same time the following code works just fine:
    PHP Code:
    function foo(&$arr) {
      
    $arr[] = 3;
    }

    foo($arr = array(12)); 
    Yes, but you're passing a reference to an anonymous array ('array(1,2)'), not a reference to '$arr'.

    <edit>Or so I thought. A quick test shows that $arr actually contains three elements after the call. Odd.</edit>

    Quote Originally Posted by pachanga
    And in the following case "return parent :: foo()" in Bar::foo() shouldn't be changed:
    PHP Code:
    class Foo {
      var 
    $ref 1;
      function & 
    foo() {
        return 
    $this->ref;
      }
    }

    class 
    Bar extends Foo {
      function & 
    foo() {
        return 
    parent :: foo();
      }

    Which means, i guess, that if the function declared with & and returns reference, there's no need in temporary variable when returning its result.
    Foo::foo() returns a reference, so if Bar::foo() returns a reference, it can return the reference that Foo::foo() returns. Nothing odd about that.
    Birnam wood is come to Dunsinane

  3. #3
    SitePoint Addict pachanga's Avatar
    Join Date
    Mar 2004
    Location
    Russia, Penza
    Posts
    265
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by AutisticCuckoo
    <edit>Or so I thought. A quick test shows that $arr actually contains three elements after the call. Odd.</edit>
    Exactly

  4. #4
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    # this works
    function foo(&$x) {
        
    $x++;

    foo($a 1);
    echo 
    $a;

    # and even this
    function &bar() {
        
    $a 456;
        return 
    $zz = &$a;

    echo 
    bar();

    # but this doesn't
    function &baz() {
        return 
    $zz 123;

    echo 
    baz(); 

  5. #5
    SitePoint Enthusiast
    Join Date
    Nov 2005
    Location
    Norway
    Posts
    26
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's an excellent example:
    Quote Originally Posted by stereofrog
    PHP Code:

    # but this doesn't
    function &baz() {
        return 
    $zz 123;

    echo 
    baz(); 
    The result of $zz = 123 would be 123, a value, not a reference. That's just what AutisticCuckoo said, and that's the core of it.

  6. #6
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Why does the first one work then?

  7. #7
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by stereofrog
    Why does the first one work then?
    Because &$a is a reference, not a value.

    Basically, you can only reference a variable, not a value.

    PHP Code:
    //this:
        
    return $foo 'bar';

    //is the equivalent of
        
    $foo 'bar';
        return 
    'bar';

    // while this
        
    function foo(&$x) {}
        
    foo($a 1);

    // is the equivalent of this:
        
    function foo(&$x) {}
        
    $a 1;
        
    foo($a); 

  8. #8
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @Berislav: Yeah, thanks, it doesn't explain that much. What I am looking for is a trace of logic in this stuff.
    Quote Originally Posted by BerislavLopac
    //this:
    return $foo = 'bar';

    //is the equivalent of
    $foo = 'bar';
    return 'bar';
    Why not:
    PHP Code:
        $foo 'bar';
        return 
    $foo
    // while this
    function foo(&$x) {}
    foo($a = 1);

    // is the equivalent of this:
    function foo(&$x) {}
    $a = 1;
    foo($a);
    Why not:
    PHP Code:
        $a 1;
        
    foo(1); 
    How can the same operation (assignment) be treated in such different ways?

  9. #9
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by stereofrog
    How can the same operation (assignment) be treated in such different ways?
    Because you're assigning different things.

    Consider this: when you assign value 'bar' to a variable $foo, what really happens?

    PHP stores variables and their values separately, that's what happens. So when you state $foo = 'bar', you put 'baz' as the value of the variable $foo; however, when you state $foo =& $baz, you put as the value of $foo the *reference*, i.e. an internal pointer to the location of the *value* of $baz.

    On the other hand, the return statement -- probably for historical reasons -- work as the equivalent of chained assignments, i.e. $a = $b = $c = 1000, which creates variables $a, $b and $c and assign the same value to each of them. The only difference is that when you declare the function to return a reference, it *has* to be assigned a reference, not a value.

    It's actually quite simple once you get it. Not unlike the pointers in C.

  10. #10
    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)
    So return $foo = 'bar'; doesn't return $foo, but rather returns 'bar', whereas foo($a = 1); assigns 1 to $a, and calls foo() with $a as argument ?
    That's a bit confusing actually, that return doesn't evaluate the statement beforehand.

  11. #11
    SitePoint Addict pachanga's Avatar
    Join Date
    Mar 2004
    Location
    Russia, Penza
    Posts
    265
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Folks, maybe it's a bug?

  12. #12
    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)
    Damn, just when I thought I understood variables and references

    Code:
    $ php -d error_reporting=4095 -r 'function &foo() { return  $x = 1; } $r =& foo(); var_dump($r);'   
    Strict Standards: Only variable references should be returned by reference in Command line code on line 1
    int(1)
    
    $ php -d error_reporting=4095 -r 'function &foo() {  $x = 1; return $x; } $r =& foo(); var_dump($r);'
    int(1)
    which is so completly different from
    Code:
    $  php -d error_reporting=4095 -r 'function foo(&$x) { var_dump($x); } foo(1);'
    
    Fatal error: Only variables can be passed by reference in Command line code on line 1
    $  php -d error_reporting=4095 -r 'function foo(&$x) { var_dump($x); } foo($x = 1);'
    int(1)
    Last edited by sweatje; Nov 28, 2005 at 10:30. Reason: added inbound function parameter reference for comparison
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  13. #13
    SitePoint Wizard silver trophybronze trophy asp_funda's Avatar
    Join Date
    Jun 2003
    Location
    ether
    Posts
    4,479
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    Cool

    Quote Originally Posted by sweatje
    Damn, just when I thought I understood variables and references
    erm, reading this thread is making my head spin!! I feel like I don't even know what PHP is!!
    Our lives teach us who we are.
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Me - Photo Blog - Personal Blog - Dev Blog
    iG:Syntax Hiliter -- Colourize your code in WordPress!!

  14. #14
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's why I don't even do crazy stuff like return $foo = 'bar'; The behavior is unpredictable, in the sense that it is not well documented and people expect it to do different things

    Already this thread isn't very long and we have about 3 different interpretations over what it should be doing.

    As I read it, it should assign "bar" to $foo and return a boolean true... I mean after-all the result of assigning a value to a variable would be successful [true], would it not?

    The again, I am just guessing at what I *think* it would do, since I don't write code like that in the first place.

  15. #15
    SitePoint Addict pachanga's Avatar
    Join Date
    Mar 2004
    Location
    Russia, Penza
    Posts
    265
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As I read it, it should assign "bar" to $foo and return a boolean true... I mean after-all the result of assigning a value to a variable would be successful [true], would it not?
    In what case does assignment operator return false then?

    The again, I am just guessing at what I *think* it would do, since I don't write code like that in the first place.
    I wouldn't write such a code either if it wasn't for the new PHP 4.4 ref. implementation. What i'm trying to find is the easiest way to upgrade my code and i think the following code:

    PHP Code:
    class Container {
      function & 
    findObject($id) {
         if(isset(
    $this->items[id]))
           return 
    $this->items[id];
         else
           return 
    $zref null;
      }

    is more readable than:

    PHP Code:
    class Container {
      function & 
    findObject($id) {
         if(isset(
    $this->items[id]))
           return 
    $this->items[id];

         
    $zref null;
         return 
    $zref;
      }


  16. #16
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by pachanga
    In what case does assignment operator return false then?
    Nonono, you both got it wrong. When a function is declared to return a reference, it should never return a value. Get it?

    When your function declaration begins with a &, you *must* pass a reference to its return statement. A return in that case is an implicit =& operator -- so you can't return a literal value, as it hasn't been associated a reference yet.

    One more thing: assignment operator returns nothing -- it's an operator, not a function.

    And a side note: It makes no sense to return the value of a parameter that has been passed by a reference. Consider:

    PHP Code:
    <?php

    function &foo(&$bar)
    {
        
    $bar++;
        return 
    $bar;
    }

    $baz 10;
    $wazoo =& foo($baz);
    echo 
    $wazoo ' = ' $baz '<br/>';
    $baz++;
    echo 
    $wazoo ' = ' $baz '<br/>';

    /*
    it prints:
        11 = 11
        12 = 12
    */

  17. #17
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    what is wrong with this:

    PHP Code:
    class Container {
        function &
    findObject($id) {
            
    $return null;

            if(isset(
    $this->items[id])) {
                
    $return =& $this->items[id];
            }

            return 
    $return;
        }


  18. #18
    SitePoint Addict pachanga's Avatar
    Join Date
    Mar 2004
    Location
    Russia, Penza
    Posts
    265
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape
    what is wrong with this:...
    There's nothing wrong about it but it takes more time to make old scripts look like this way. Consider changing more than a hundred of returns, if "return $zref = null;" was supported i would only need to copy/paste "$zref =" part into every "return null". It would be also possible to write a small regex for sed to make automatic batch changes.

  19. #19
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by pachanga
    Consider changing more than a hundred of returns.
    Yes I've already changed all my scripts.

    Relatively speaking, it doesn't take all that long to do. You've just gotta buckle down and get it over with, whatever approach you decide to take.

    Consider that you've likely spent more time looking for an easy way to do it, than the amount of time it would take you to just sit down and do it

    Off Topic:

    I do the same thing. I will spend a good half hour searching for the remote before just walking up to the tv and switching the channel button. When we talk about stuff like this later, it really seems like irrational beahvior, but at the time, we were thinking very rationally

  20. #20
    SitePoint Addict
    Join Date
    Aug 2003
    Location
    Toronto
    Posts
    300
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Not helpful as a work around, but perhaps helpful to explain behaviour; consider this example:
    PHP Code:
    // throws a notice
      
    function &baz() {
          return 
    $zz 123;
      }
      echo 
    baz();
      
      
    // returns 123
       
    function &foobar(&$zz) {
           return 
    $zz 123;
       }
      echo 
    foobar($zz=321); 
    The point is that in foobar(), you are already passing $zz as a reference so the assignment in the return statement links to a reference rather than a value as it does in baz().

    IIR, some OOP languages don't allow statements to be used as expressions and in many cases, they really don't save very much typing and can hide / obscure important operations.

    BTW: if you really can't stand a temporary var and don't mind the overhead of a function call, use a wrapper funciton:
    PHP Code:
    function &SafeRet($value=null)
    {
        return 
    $value;
    }

    function &
    bar()
    {
        return 
    SafeRet();

    echo 
    bar(); 
    ...but, in my mind, if you are returning a reference you are really declaring the intention to return something -- ie: a true function as opposed to a non-value returning procedure. It may be old fashioned procedural habits but for those cases, starting the function with a $retvalue = ... stanza seems appropriate as does ensuring a single return point.
    Last edited by jayboots; Nov 28, 2005 at 13:36.

  21. #21
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I just wanted to suggest that instead of using meaningless variable names like $return, $ret, or $zval, that it might be better to use a name with meaning.

    PHP Code:
    class Container {
        function &
    findObject($id) {
            
    $object null;

            if(isset(
    $this->items[id])) {
                
    $object =& $this->items[id];
            }

            return 
    $object;
        }

    The key in this case is that the return statement should read like a php doc comment, not like a stutter:
    PHP Code:
                return $return

  22. #22
    SitePoint Addict
    Join Date
    Aug 2003
    Location
    Toronto
    Posts
    300
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Selkirk
    I just wanted to suggest that instead of using meaningless variable names like $return, $ret, or $zval, that it might be better to use a name with meaning.
    The sentiment is good but the example fails to convey it ($object has meaning?). $findObject seems more sensible in that example, not?

    I also agree with BerislavLopec concerning the merit of returing a reference to a parameter that was passed-by-reference. Earlier I had used that metaphor but only to demonstrate how refrences are treated differently than values in assignment. Don't Do what Donny Don't Does

  23. #23
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Selkirk
    I just wanted to suggest that instead of using meaningless variable names like $return, $ret, or $zval, that it might be better to use a name with meaning.
    $object has no more meaning than $return does.

    If you do HTML, you probably use DIV's alot. You know what a DIV means? It means absolutely nothing. It is a meaningless container.

    So you see, there is nothing wrong with using "meaningless" names.

  24. #24
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape
    $object has no more meaning than $return does.
    In the example I think $object is clearer. Names like $result, $sum, $divisor, $tmp can be the most meaningful term in some circumstances, but not usually.

    Quote Originally Posted by dreamscape
    If you do HTML, you probably use DIV's alot. You know what a DIV means? It means absolutely nothing. It is a meaningless container.

    So you see, there is nothing wrong with using "meaningless" names.
    Div is short for Division which is a typographic term for separations of sections larger than a paragraph but smaller than a chapter. I think it is apt.
    Christopher

  25. #25
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    $object has about as much meaning as you can extract in the context of a function called findObject. My point is that if your function were called findInvoice, then
    PHP Code:
    return $invoice
    is better than
    PHP Code:
    return $return


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
  •