Functions by reference or by variable, which to use when? - php

Well, I read in my handy PHP book that it's very important to be able to distinguish between reference and variable parameters. The book says that the original value of parameterized variables are preserved when the variable is changed, and the original values of parameterized references change when the reference is changed. It says that's the key difference, if I am reading right.
Well, I'm wondering when each is more useful than the other. How do I know when to use variables and when to use references when I create my own functions?

It's pretty straightforward. Use references when you need to modify the value of the variable passed in to the function. Use variables when you don't need to or want to modify the value.
So, for example, if you're writing a function that takes an array and changes that array, you'd be better off using a reference for that array rather than returning a new array from the function.

"References" (variable aliases) make your code harder to understand and could be a source of hard to follow errors. There are no valid reasons to use references in php and to be on the safer side try to avoid them altogether.
And no, objects in php5 have nothing to do with "references".
"References" as implemented in php is a strange concept. Normally, in programming languages variables are independent of each other so that changing one variable doesn't affect others. Php "references" allow several variables to share the same value and to be dependent of each other. Basically, you change one variable, and suddenly another one, which you think is totally unrelated, is getting changed too. It's no good thing and often leads to much confusion.
Objects in php (do I need to add 'five'?) have nothing to do with "references" in the above sense. They behave much like C pointers (actually, this is what they are under the hood) - when you pass an object to a function, you actually pass a pointer, and the function can use this pointer to manipulate the object contents, but there's no way for the function to change the passed variable itself, for example, make it point to another object.
This "objects are references" misunderstanding is probably because people confuse php "references" (ampersand syntax) with the generic CS term , which also applies to pointers, handles etc.

Related

How does PHP access properties internally?

Following up on this documentation: https://www.php.net/manual/en/language.oop5.references.php
One of the key-points of PHP OOP that is often mentioned is that "objects are passed by references by default". This is not completely true.
In PHP, an object variable doesn't contain the object itself as value. It only contains an object identifier which allows object accessors to find the actual object.
How does this actually work? In C++ for example it seems that the arrow operator implicitly dereferences the pointer and then accesses the properties like when accessing them on the object variable itself.
Here's what I mean:
obj->prop
(*obj).prop // equivalent to line above
This seems pretty clean. The property is called as the sum of the object-variable-address and the property-offset in both cases.
But how does that work in PHP?
The documentation suggests that the pointer does not store the memory address but rather an "object-identifier". Is accessing properties in PHP a highly abstracted process or does it resolve the object-identifier for the memory address and then access it in a similar way to C++ / Java / etc.?
It's a highly abstracted process, similarity in syntax does not indicate that the code "falls through" to working like C/C++. You can dive into the code to see how it works under the covers.

why not use arrays instead of many parameters

I may sound stupid to some but I want to know if there is some benefit of passing arguments to a function as an array,rather than passing each arguments or some downsides?
Unwritten rule for good programming practice is that function should not have more than 3-5 arguments.
Usually arrays or even objects are used to pass in the logical complete data structures.
I think this is due more transparent and readable code rather than any performance benefits.
Sure it might look nicer if you pass an array to a method, but what does it mean?
Arrays usually signify that you have a collection of the same thing, whilst method parameters are usually different things.
If you want to pass a list of things to a method and do the same action on all of them, then it makes perfect sense to use some type of array/collection object.
If however you want to make it tidier and avoid passing around lots of objects together, consider refactoring your code to use some kind of wrapper object that you can pass around more easily.
Also if you have so many arguments that you would consider using an array to hold them, it's a sure sign that you need to refactor your code ;-)
Mostly it just requires more typing to create an array and pass it, rather than just passing individual arguments.
Other than that there's no particular specific advantage to separate parameters.
Parameter list much more clear when you read function signature. Array is just one variable, say, $args. But what there in args?
if you have this array already, it is surely better to use it.
if you don't have this array already, using parameters will save you typing of array keyword and a couple of braces.
that's all.
Use whatever you feel more suitable for the case.
I think that when you have a few parameters or less than 5 (subjectively) then more useful is passing arguments as parameters. If you have a big count of arguments then using array is more useful that function/method with 15 parameters.

pass array by reference

when using arrays as parameters in functions, should I pass them by reference or by value? Or there is not that much significance?
Normally you should pass by value.
You should only pass be reference if you need to modify the array in place, rather than returning a new one.
There's no performance benefit to passing by reference when reading from an array because PHP uses copy-on-write,
If you're interested in maximising performance, do a speed test. Due to PHP optimisations, passing by reference is usually faster than passing by value only if you modify the array (however note the behaviour is also different!).
Passing by value helps reduce the side-effects of a function (side-effects are a common source of code complexity and bugs) and for this and other reasins, it is "better style".
So, pass by reference only if there is a good reason to do so.

Naming conventions for function parameter variables?

Is there a naming convention or maybe some guideline on how to name function parameters?
Since forever, I have been doing it like this:
function divide( $pDividend, $pDivisor )
{ ... }
That way I'll always know which variables were passed as parameters.
(This one's PHP, but it should be applicable to most programming languages)
Is there one major reason against this?
Is there a better way to do this or is it probably best to just avoid such naming schemes?
If :
your functions/methods are well written and short (as they should be)
the variable names are descriptive enough
This practice is not needed.
If you need this, it means that the code written is not readable enough (functions/methods too long), cryptic variable/function names, bad OO practices, shortcuts, code debts, etc. :)
So it would be a signal that the code needs to be refactored/improved.
I think taking the advice of Code Complete regarding naming -anything- would be justified it's whole chapter 11 is on naming variables properly):
Don't name it j, k, i, m, n (unless it's just for an iteration) or "placeholder" or "test". When the "test" works, I often don't take the time to rename the variable wherever it's been listed.
Call it a descriptive name that's separate from the code's function ie "EmployeeComments" not "XMLEmp_Comment_File" because a lot of that information (XML, external file) could change, but that the program's working with "Employee Comments" won't
Keep it as broad and human readable as possible so you're coding in English (or your language) not $j=$k/sqrt($pi); or something equally unintelligible.
As for parameters specifically, I've never used the P notation. I like the idea, but if you named them right wouldn't it be clear they were the parameters for the function?
I've heard that some people will keep their function parameters one style, with the type of data a the first part of the variable (array = arr), and then capitalize the following words:
$arrFormData
where the rest of their variables are in a different style, where the words are all lower case, no type definition, and the words are separated by underscores.
$form_data
Personally, I tend to keep my variables the same as the rest of my variables, purely because on the first two lines of a function, I'm making sure that they are what I expect, or throwing an exception. After that, there shouldn't really be a difference between local variables and variables passed in. But, if it keeps your code clearer to type it one way, by all means.
You should follow general guidelines for how to name parameters as you would for other variables (names should be clear, accurate, specific, consistent, and usually 8-20 characters long).
As for the prefix, I would recommend the opposite: leave the parameter unmarked, and mark anything that you do with the parameter in the function as a separate variable. For example:
function upperCase($title) {
$upTitle = ucfirst($title);
return $upTitle;
}
In my example, I use a bare parameter, $title. After I transform the input, I call it something else to indicate that it is now in a transformed state, $upTitle. That way I know that it is no longer just the function parameter. Merely calling your parameter $pTitle does not give you quite the same advantage as this consistent approach.
If you think about it, your method marks all the parameters on the interface, which is not the best level. If you look at the API of your program, all your function parameters are marked with $p meaning parameter, which is redundant. You are saying, all of my parameters are parameters, which we already know since they are part of the API. So I would recommend dropping the prefix for the parameter and instead using a series of semantic prefixes that denote what you have done to the parameter to transform it within the function, as in my example.
I disagree with the previous suggestion that you should just make your code more clear. Having clear code does not remove the need for having clear naming conventions.
I have naming conventions for some variables, like member fields or static fields, because the declaration of the variable may be far away from the code where I use it. For parameters or local variables I do not use anything, as usually the variable definition is about ten lines away.
Especially in the all IDE camp people seem to get more and more to dislike any prefix or suffix, as "the IDE provides highlighting". Well, it doesn't help me, and I dislike having semantic information only available as color. However, I can see there point, as the variable name should make the most important information clear, and if it doesn't, nothing helps.
So, this is more about style. Good naming is more important than good prefixes. For the schemes: pick one, stick to it. This will help the poor maintenance developer. Yes, those are the people who usually also prefer { } around single statement blocks and so on, but it helps.
The greatest chance for confusion for me is in member functions. If possible, I like to see differences in naming between:
local variables: index
class member variables: m_index
class static variables: ClassIndex
global variables: INDEX
This can make it easier to track down what's happening where. However, I agree with Toto that it's best to make your functions short enough so that these conventions don't make or break your ability to figure out what's going on.
You can follow the PHP Coding Standards or Coding standard for php which is suggested to contribute in core php.
So after looking at all this, I decided to go with:
ClassName
methodName
propertyName
function_name (meant for global functions)
$variable_name
There are many ways to name variables (as you can see from the answers)
But as a general rule, they should be named such, that it is clear from just looking at the variable itself, what it does and what it is used for, right there and not have to go through thousands of lines of code to find out - and not just for who else might have to troubleshoot later but if your code is thousands of lines long for your own good if you yourself have to troubleshoot later
AND WHATEVER NAMING CONVENTIONS YOU CHOOSE BE CONSISTENT THROUGHOUT YOUR CODE - this cannot be iterated enough :)
Personally I use the following:
first part of the variable is for what it is
second part is for what it does/is used for
and for variables needed outside the function, class, etc. the third part is for the function, class, etc. it comes from
Ex:
I want to name the variable for a video thumbnail on the front page:
so i start with what it is (lower_case) - thumbnail
then I add on what it is used for (first letter upper_case) - Video
and since I need it on the front page outside the function I finish off with the function it came from (seperated by under_score) - getVideoAll
Giving me $thumbnailVideo_getVideoAll
That way no matter where I look at the variable in any part of the code (HTML, PHP, etc.) I know...
ah this is the thumbnail for the video I'm trying to show and if it for some reason doesn't work I firstly don't need to go anywhere to spell-check and secondly I know exactly what function, class it was called for (getVideoAll) and can just go there to troubleshoot
If I instead just had named it $tnVid I might personally have a vague notion of what it is but someone else looking at will have no idea that tn stands for (t)humb(n)ail, etc.
so to troubleshoot they would have to first look at the surrounding code to maybe infer that it is probable a variable for a thumbnail and second go through thousands of lines of code to find what function, class, etc. it came from - and that's hours of work just finding what you need to even start troubleshooting - instead of the 5 seconds it takes seeing $thumbnailVideo_getVideoAll and going -
ah this is the thumbnail for the video and I need to go to the function getVideoAll to troubleshoot

Are primitive data types in PHP passed by reference?

In PHP, I'm frequently doing lots of string manipulation. Is it alright to split my code into multiple functions, because if primitive types like strings are passed by value I would be significantly affecting performance.
Only objects are passed by reference.
That doesn't mean you'll get a performance boost by changing to references though - PHP uses copy-on-write, so a copy is only made if you modify the variable.
Splitting your code into functions won't slow it down from that point of view.
There is a small overhead for calling a function, but unless your in a loop calling 10,000s of them it's probably not something you need to worry about.
Objects are passed by reference. Everything else is passed by value unless you explicitly use pass-by-reference with the & operator.
That being said, PHP also uses copy-on-write to avoid unnecessary copying.
Yes, primitives are passed by value unless you explicitly define the function to pass by reference (by using an ampersand & in front of the parameter) or invoke the function with an ampersand in front of the argument. (The latter of which is deprecated)
See this part of the documentation for more.
EDIT
Also, the statement that "objects are passed by reference" in PHP is a bit of a simplification, though it can often be thought of that way for most purposes. This chapter of the documentation explains the differences.
Passing by reference is actually slower than passing by value in PHP. I can't find the correct citation for this claim; it's somewhere in the "References" section of the PHP manual.
By default, everything is passed by value. If you want to pass something by reference you have to explicitly state it as so.
Here is the php documentation that explicitly states this behavior.

Categories