php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #66200 the new operator DON'T returns a reference automatically
Submitted: 2013-11-29 10:04 UTC Modified: 2013-12-02 11:10 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: erwan dot oger35 at gmail dot com Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: 5.4.22 OS:
Private report: No CVE-ID: None
 [2013-11-29 10:04 UTC] erwan dot oger35 at gmail dot com
Description:
------------
---
From manual page: http://www.php.net/language.operators.assignment
---

"As of PHP 5, the new operator returns a reference automatically, so assigning the result of new by reference results in an E_DEPRECATED message in PHP 5.3 and later, and an E_STRICT message in earlier versions."

Test script:
---------------
<?php

class A
{
	private $name;
	private $counter;

	public function __construct ( $name ) 
	{
		$this->name = $name;
		$this->counter = 0;
	}
	
	public function __destruct ()
	{
		echo __METHOD__. ' : '. $this->name . ' ('.(++$this->counter).')<br/><br/>'.PHP_EOL.PHP_EOL;
	}
}


class B
{
	private $name;
	private $counter;

	public function __construct ( $name ) 
	{
		$this->name = $name;
		$this->counter = 0;
		
		ObjHandler::link($this);
	}
	
	public function __destruct ()
	{
		echo __METHOD__. ' : '. $this->name . ' ('.(++$this->counter).')<br/><br/>'.PHP_EOL.PHP_EOL;
	}
}

class ObjHandler
{
	private static $objLinked = array();
	
	public static function link ( &$obj )
	{
		self::$objLinked[] = &$obj;
	}
}




$a = new A('a');
$a2 = &$a;
$a = null;


$b = new B('b');
$b = null;


Expected result:
----------------
A::__destruct : a (1)

B::__destruct : b (1)

FIN

Actual result:
--------------
A::__destruct : a (1)

FIN

B::__destruct : b (1)


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-11-29 10:25 UTC] erwan dot oger35 at gmail dot com
Note that even you change : "$a2 = &$a;"

by : "ObjHandler::link($a);"

it returns the same result !!
 [2013-11-29 13:25 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2013-11-29 13:25 UTC] requinix@php.net
Looks like the correct behavior to me: an object reference is not the same thing as a variable reference.
A variable has data associated with the variable itself, and one of those pieces of data is what the value is. An object reference is where the "what the value is" is the same for multiple variables, however the "data associated with the variable itself" is different for each. A variable reference will have both variables be using the same "data associated with the variable itself" (and thus the same "what the value is"). Shortest and simplest explanation I can come up with right now.

$a2 = &$a:
$a and $a2 are essentially the same variable, and setting $a=null destroys the only copy of the A instance (also affecting $a2 along the way). The assignment did not break the $a/$a2 link but rather changed the value that the two share.

$b versus $this:
Two variables, both referring to the same object. However while they have the same value the two are not the same variable like $a and $a2 were, so setting $b=null does not affect the "$this" that was passed to ObjHandler. A reference remains until the end of the script.

ObjHandler::link($a):
Because the method's $obj parameter is passed by-reference, you'll get the same behavior with that as you would with the $a2 = &$a you had before - except this time it's $obj = &$a.

I don't know the purpose of the ObjHandler but I'm sure that link()'s $obj should not be by-reference.
 [2013-12-02 09:55 UTC] erwan dot oger35 at gmail dot com
Hi thanks for your answer.

In first I'm agree with you : 

<< $b versus $this:
Two variables, both referring to the same object. However while they have the same value the two are not the same variable like $a and $a2 were, so setting $b=null does not affect the "$this" that was passed to ObjHandler. A reference remains until the end of the script. >>

However, it's my problems. When I read
<< "As of PHP 5, the new operator returns a reference automatically" >>,
I understand that the two ARE the same variable:
			 _______________ 	 _______________________
	$this	------->|	ID	|------>|	B OBJECT	|
	$b	------->|_______________|	|_______________________|

but in fact, it's this is :
			 _______________ 	 _______________________
	$this	------->|	ID_1	|------>|			|
			|_______________|	|			|
			 _______________ 	|	B OBJECT	|
	$b	------->|	ID_2	|------>|			|
			|_______________|	|_______________________|





And the goal of ObjHandler's goal it's to destruct all objects (update in db) in case of error (even fatale). So I need only one reference on this object when I want they'll be destructed only once.
Actually I need a binding structure, as this singleton example :

class MyClass
{
	private static $_instance = null;
	
	
	private $isDestructed;
	
	
	// *************************
	// BGN METHODES DE SINGLETON
		public static function &getInstance  ()
		{
			if ( is_null(self::$_instance) )
			{
				self::$_instance =& self::create();
			}
			
			return self::$_instance;
		}
		// *********************
		// BGN CONSTRUCT METHODS
			private static function &create ( )
			{
				$instance = new static();
				
				ObjHandler::link($instance);
				
				return $instance;
			}
			
			private function __construct ()
			{
				$this->temps_debut=microtime(true);
				
				$this->isDestructed = false;
			}
			
			private function __clone(){}
		// END CONSTRUCT METHODS
		// *********************
		
	// END METHODES DE SINGLETON
	// *************************
	
	// ********************
	// BGN DESTRUCT METHODS
		public static function kill ( self &$instance )
		{
			if ( ObjHandler::unlink($instance) )
			{
				$instance = null;
				
				return true;
			}

			return false;
		}
		
		private function __destruct ()
		{
			
			if ( !$this->isDestructed )
			{
				$this->isDestructed = true;

				// *** TODO : INSTRUCTIONS ***
				
			}
		}
	// END DESTRUCT METHODS
	// ********************
	
	// OTHER METHODS ...
}




So, even it's not a bug, I'll continue to believe it's not a good thing, which should be improved...

Thanks.
 [2013-12-02 11:10 UTC] requinix@php.net
I don't see what the improvement is supposed to be, but I assume the issue of "new not returning references" has been solved? A couple final comments:

1. Object references and variable references are two different things, both under the "references" umbrella. What you thought was supposed to happen is not the case, if for the very simple reason that new returns an object and not a variable and thus it's not possible to use variable references there.
2. I can't think of any way to guarantee that one object reference (of a particular instance) exists during execution. Variable references would do it but you'd have to make sure that all code uses them, which sounds like poor design, not to mention being a real pain.

If you need more help solving whatever your problem is, try a mailing list or forum. http://www.php.net/support.php
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Sun Aug 09 17:01:23 2020 UTC