I'm working with some old PHP code that has a lot of the following:
$someVar =& new SomeClass();
Did the new operator ever return a value, um, not by reference? (That feels strange to type. I feel like I'm losing my mind.)
It was one of those sort of optimization techniques taught in a lot of older books on OOP in PHP 4.
Basically, the initial object created in memory is one the application can't access unless you return the instance by reference. Otherwise you get a copy of the object - the only catch is that the original exists without a symbol. Kinda dumb.
But ya, object creating and passing and references in PHP 4 is a monumental mess.
Thats PHP4 code.
From the documentation: (now removed)
"new" does not return a reference by
default, instead it returns a copy.
[1]: http://no.php.net/manual/en/language.oop.newref.php
See also my answer here which includes a simple code sample to illustrate the issue.
Related
What exactly does the following line of code doing:
$config = &get_config();
Is & operator passing by reference? Also is get_config() a CodeIgniter helper? I couldn't Google the explanation.
As Konrad Rudolph said here: https://stackoverflow.com/a/3957588/837765
The & operator tells PHP not to copy the array when passing it to the
function. Instead, a reference to the array is passed into the
function, thus the function modifies the original array instead of a
copy.
get_config() loads the main config.php file in an array and you modify the returns array directly with the & operator.
It's not a helper. Take a look here (to find the get_config() function) :
http://www.8tiny.com/source/codeigniter/nav.html?_functions/index.html
Is & operator passing by reference?
Yes, it is passed by reference so that you can change config array.
Also is get_config() a CodeIgniter helper?
No, it's a core CodeIgniter method which loads the config array defined in application/config/config.php.
You can look at the source here.
The & operator is PHP's reference operator.
CodeIgniter is a rather old framework. In older versions of PHP objects used to be passed by value. This meant that PHP was quite wasteful when it came to stuff like memory allocation, which made things slower than they needed to be. To prevent PHP from allocating memory every time you wanted to access an object you would instead use references.
In newer versions of PHP objects and arrays are automatically passed by reference. When it comes to arrays, new memory is only allocated if you change the array.
99 per cent of the time using references is not necessary. PHP will optimize the code for you in a way that makes sense. You should only use references if you understand what they do, and you have a legit reason to use them.
You can find the get_config() function by searching for it in the source code on GitHub.
Derick Rethans has an old article that says:
Please do note that it is harmful not to accept a reference from a
function that returns a reference. In some cases, PHP will get
confused and cause memory corruptions which are very hard to find and
debug. It is also not a good idea to return a static value as
reference, as the PHP engine has problems with that too. In PHP 4.3,
both cases can lead to very hard to reproduce bugs and crashes of PHP
and the web server. In PHP 5, this works all a little bit better. Here
you can expect a warning and it will behave “properly”.
Does it mean that in PHP 5 we are allowed to ignore the returned reference from a function?
By that, I mean this:
function &GetRef(&$array){
$item =& $array[0];
return $item;
}
$array = array(0, 1, 2);
$item =& GetRef($array); /* Normal usage of the function using assign by reference
also known as "accepting" the reference. */
$item = GetRef($array); /* Notice that here we didn't assign by reference.
Are we allowed to ignore the returned reference
and simply do normal assignment? */
The PHP Manual states:
Unlike parameter passing, here [return by reference] you have to use &
in both places - to indicate that you want to return by reference, not
a copy, and to indicate that reference binding, rather than usual
assignment, should be done for $myValue.
It doesn't explicitly say that we must accept the returned reference.
Does it mean that we are free to ignore returned references?
As discussed in the comments, you should generally ignore at least that section in the linked article, if not the entire thing.
The article talks about references in the context of PHP 4.3, released in December, 2002 and EOL'd at the end of 2007. PHP 4 should never be used today. As a general rule, when it comes to learning about working with PHP, you should not trust any article that targets PHP versions older than 5.2 (as of mid-2013).
PHP 5.0 features Zend Engine 2, a new virtual machine on which PHP runs. This is where references are implemented. 5.1 introduces some backwards-incompatible changes with regard to manipulation of return values. 5.3 introduces real garbage collection and deprecates both call-time pass-by-reference and assigning new by reference. These important changes are not addressed by that prehistoric article.
Does it mean that in PHP 5 we are allowed to ignore the returned reference from a function?
Yes. Modern PHP versions have no problem with discarding the return value of any function, reference or not. If you encounter behavior that seems to contradict this expectation, create a reduced test case and file a bug with the PHP maintainers.
Also, think twice before using references in your code. Passing around references will not save time, will not save memory and will not increase performance except in rare cases. Use them sparingly to keep complexity under control.
I've read about this interesting syntax in PHP:
$value = (new MyClass)->attribute1;
Is it ok to use it? I've never seen anything like this in any code I've analyzed. Any pros and cons?
Why can't I set the attribute using this syntax? Structures like this:
(new MyClass)->attribute1 = 'value1';
throw errors at '=' sign, no matter if the attribute exists in the class already.
Well i don't see the point of using it since you loose your reference to the object, you cannot use it anymore, and it breaks the OO concept.
I think (new MyClass)->attribute1 is resolved first, so it is the same as writing something like 42 = 12
This may have a sense, if the class MyClass supports internal static list (or hashmap) of all existing instances. This way you can create new object and get its unique ID or index in the list for future references (for example, by sending it via cookies to a client).
As for assignment, you'd post exact error message for this case. I can guess, that the error is about assigning something to a temporary value which is about to be destroyed.
I am getting a deprecated warning because of a library I am using. The statement is the following :
$this->_ole =& new OLERead();
The thing is I don't see why one would want to use & new in an instantiation.
If I am not mistaken, the & operator tells PHP to copy the reference to the instance, and not the instance itself. But in that case, isn't it pointless to ask for a copy of a reference that isn't stored ?
But since I don't exactly know how new exactly works, maybe this was supposed to save some obscure garbage collection, or something like that.
What do you think about that ?
From the documentation:
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.
The library you use was probably developed for PHP 4.
Helpful information about why this was used can also be found in the migration guide:
In PHP 5 there is a new Object Model. PHP's handling of objects has been completely rewritten, allowing for better performance and more features. In previous versions of PHP, objects were handled like primitive types (for instance integers and strings). The drawback of this method was that semantically the whole object was copied when a variable was assigned, or passed as a parameter to a method. In the new approach, objects are referenced by handle, and not by value (one can think of a handle as an object's identifier).
That's an idiom for PHP4 compatibility. Objects were passed as copies per default there, and this is a workaround to always have references to an instance.
In PHP4, new returned a value and not a reference.
This is not the case in PHP5.
If you write $this->_old =& new OLERead(); a changement of _ole in any object will updates all references to the new object.
This is not the case without & .
EDIT: And yes, in previous versions of PHP, object were passed by copy. At the end, this is quite hard to have a consistent behaviour accross versions.
when I was looking for some MVC framework, I got the website:
http://www.phppatterns.com/docs/design/archive/model_view_controller_pattern
however, like the code listed there makes me confused about references.
For example:
$dao=& new DataAccess ('localhost','user','pass','dbname');
$productModel=& new ProductModel($dao);
each instance it makes, it adds '&' before the new operator, what does it exactly mean? the reference to the instance? Actually, I removed all the '&' before all these kind of instances and the code still works perfectly.
Another, codes like :
function ProductView (&$model) {
$this->model=& $model;
}
I really think it could be revised like:
function ProductView (&$model) {
$this->model=$model;
}
Am I right? what's the differences between these two? Actually, like the MVC code example listed above? if you revise the code like I did, the code still works.
Then, I got this post somewhere else:
http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html
does it make sense? any suggestions about this would be helpful.
Prior to PHP version 5 objects were passed by value and you had to explicitly specify the ampersand to get the object by reference.*
In PHP 5+, all objects are passed by reference and thus using ampersand is redundant.
Furthermore, as of PHP 5.3.0, code like the above will generate a STRICT error of "Assigning the return value of new by reference is deprecated".
If you're curious about the historical use (PHP 4 or before) of "$o =& new Object()" code see php-by-reference (in particular, the accepted answer there provides a good explanation).
To summarise:
in PHP 5 or above, it makes no difference. The code will work as expected with no memory or other differences.
In PHP 5.3 you might get some STRICT notices complaining about this usage (assuming you have STRICT notices turned on).
In PHP 4.x (or earlier) this method was used to prevent unnecessary duplication of objects.
(*) Passing references around is a good thing - no need to create copies of objects when you only need the one instance.