Is it considered wrong to pass a variable to a function where the variable passed has the same name as the variable in the function itself? I never see anyone do this, but wondered if there was a reason why (other than readability). Example:
$variable = "value";
function myFunction($variable) {
return $variable;
}
No there is not problem with doing this except some naming confusion. Because,
$variable = "value"; // this declaration belong to a global scope
// but $variable passing through as argument, makes it scope within that function declaration only
function myFunction($variable) {
return $variable;
}
You might have expect that if you call the function like myFunction() i.e. without any parameter, it will return you "value", but absolutely not, cause $variable passed as argument is not the global one.
But if you try to use the global $variable within the myFunction, then it will cause some conflict, that is why no one do this.
Aside from making variables a bit confusing to track, there is nothing wrong with this. They exist in different scopes.
It is up to you but vice versa, if you want to pass intentionally a variable into a function.. then you have to use this:
$variable = "value";
function myFunction($variable) {
global $variable;
return $variable;
}
echo myFunction('another value');
One more point. When creating functions you may set a default value for your params to avoid errors:
function myFunction($variable="default value") {
return $variable;
}
echo myFunction();
There is nothing wrong with it at all, and I would have thought it's quite common.
However, you should always be choosing the best name for a variable, or a parameter, in each situation, not applying one rule to your whole code.
For instance, in a database lookup function, it might be obvious what $id refers to, so it would be a sensible parameter name; but where you are calling it, you will likely have lots of IDs of various sorts, so a more descriptive variable name should be used. On the other hand, each time you build an SQL string, it's probably the only such variable in scope, so giving it a consistent name keeps your code tidy and easy to read.
A common observation is that all code is read more often than it is written (yes, even your personal website that you wouldn't dare share with the world). Variable names should be chosen with that in mind: what makes this code easy to read, understand, and maintain?
You can use global and add default value in param variable.
$variable = "value";
function myFunction($variable = '') {
global $variable;
return $variable;
}
Related
This is not a duplicate, as my requirements are that the eval() statement MUST be in the function. Also, I do not require that the function “set_myvar” return anything at all.
Say I have this code (ignore how silly it is; it's just hypothetical):
$myvar = null;
function set_myvar(){
eval("$myvar = 'Hello world';");
}
set_myvar();
echo $myvar;
Can I force eval() to be called in the global scope, so that the program echoes "Hello world"?
Mandatory disclaimer: in my self-inflated opinion, eval() is a code smell. If you need it
for something other than a quick&dirty hack, somehow, somewhere, you're doing something wrong.
That said... as I see it, you need two runs of eval().
Your current code is, say:
$program = '...';
eval($program);
And program will set some variables, have some side effects, and maybe be slow as well.
We don't want to run it twice; we just need to discover how it affects the scope, to replicate it at leisure.
What you can do is add to $program a small piece which will use get_defined_vars() or var_export() to provide a representation of the environment that is ordered and machine parsable, and return that:
$program .= "return get_defined_vars();"
Once you have it, you can have an assignment that has no more side effects than setting the variables you need. All you need to do now is execute it in the global scope.
But with this method you also have a list of the names of the variables in that environment:
$names = array_keys($returnedVars);
You can then extract those names, and add a "global" at the start:
$program2
is now "global $var1, $var2, $var3...\n extract($returnedVars);" with environment coming from the return value of the first eval().
And by eval()'ing that second program, the variables should be injected into the global scope
with a minimum of fuss.
An important note: $GLOBALS are dirty and evil. Don't use them. Ever. Never ever ever.
Please focus on the fact that it doesn't work and not why you would be doing this in the first place, it is purely a theoretical question about a technical exercise.
This is a rather weird one. I'm attempting to construct a variable variable using a string named $GLOBALS.
From the global scope
Let's see what we get when var_dump()ing this in the global scope.
$g = sprintf('%s%s%s%s%s%s%s', chr(71), chr(76), chr(79), chr(66), chr(65), chr(76), chr(83));
var_dump($$g);
The result is an array of global variables, which you can see here. Great! So, let's try this in a function.
From a function scope
First, let's just make sure that we can actually run an $GLOBALS check within a function.
function globalAllTheThings()
{
var_dump($GLOBALS);
}
globalAllTheThings();
The result is: it works!! You can see this here.
Now, let's try the first test that we used in the global scope, within the function, and see what happens.
function globalAllTheThings()
{
$g = sprintf('%s%s%s%s%s%s%s', chr(71), chr(76), chr(79), chr(66), chr(65), chr(76), chr(83));
var_dump($$g);
}
globalAllTheThings();
For simplicity's sake
You can also try this without the weird obfuscation (don't ask).
function globalAllTheThings()
{
$g = 'GLOBALS';
var_dump($$g);
}
globalAllTheThings();
It returns NULL. What's that about?? Why does it return NULL, and what can I do to get this working. Why, you ask? For educational purposes of course, and for science!
Because the manual says so:
Warning
Please note that variable variables cannot be used with PHP's Superglobal arrays within functions or class methods. The variable $this is also a special variable that cannot be referenced dynamically.
http://php.net/manual/en/language.variables.variable.php
It's simply "special". PHP is "special". Superglobals don't play by the same rules as regular variables to begin with. Someone forgot to or decided against making them compatible with variable variables in functions. Period.
Could some one please explain to me what the difference in the following is:
$var = 'something';
function myFunc(){
global $var;
// do something
}
and (note: the reference sign &)
$var = 'something';
function myFunc(&$var){
// do something
}
I can't understand the difference between these two methods.
Update
Hmmm... I think i'm getting alittle confused here :)
$var = 1;
$var2 = 2;
function myFunction(){
global $var, $var2;
$var = $var + $var2;
}
// echo $var would return 3 here.
$var = 1;
$var2 = 2;
function myFunction(&$a, &$b){
$a = $a + $b;
}
// echo $var would return 3 here aswell.
I understand those part already, But what i don't understand is the difference between these two approaches, am i wrong to assume that these two approaches are technically the same thing, with different concept of how they are wrote by the coder and also how they are handled by PHP?
If i'm wrong to assume this, then it would really help if you could provide better examples, maybe something that can be accomplished using only one of the above approaches?
ok, i noticed one difference while writing This Update, which is that when doing references i can chose new variable names while keeping the pointer to the variable in the functions scope.
In the second code block, the external $var and the internal $var are the same element. On the other hand, the third code block behaves a lot more like the first -- but you can access and modify the variable from the sending function; in the first code block, any edits you make to the variable internally are not available outside of the scope of the function.
EDIT to match the edits to the question.
The & means we are passing the variable by reference. The best way to describe it is by example.
function test2(&$var) { $var = 2; }
function test() {
$abc = 1;
test2($abc);
echo $abc;
}
test();
This code will print a 2 to the screen.
$var = 0;
function test()
{
global $var;
$var = 1;
}
test();
echo $var;
This will print 1;
In the first example, the local $var variable inside myFunc() will be assigned by reference to the variable with the same name that exists in the global scope (accessible through the superglobal $GLOBALS). PHP translates that to something like:
$var = 'something';
$GLOBALS['var'] = &$var;
function myFunc(){
$var = &$GLOBALS['var'];
// do something
}
In the second example, you pass the variable explicitly to the function, thus it is not taken from the global scope.
$var = 'something';
$GLOBALS['var'] = &$var;
function myFunc(&$var){
// do something
}
myFunc($var);
Both examples will reference the exact same variable, but using different mechanisms.
There is no technical difference at all between your two examples; they will always behave in an identical manner.
That leaves us looking for other types of differences, and there is a pretty significant code quality difference here: In the first version, looking at the call site will not tell you that the function depends on the global. In the second one it will (it's being passed in as a parameter). So the second form is, in my book at least, superior.
In addition, another difference (although one that does not apply to this example) is that the first form can only be used if your variable is in the global scope to begin with; the second will work everywhere.
You should also take into account that both these methods have an in/out argument. Normally you would not be writing code like this if it were just one argument (since you can return the out value instead) so it's interesting to consider the case where more than one arguments are being given. This is a pretty rare, and it can be argued that it's better to just return an array with multiple values rather than take multiple arguments by reference to make the code even easier to follow.
So in conclusion:
They do the same thing
If you are going to use one of them, prefer the second form (clearer, more flexible)
Consider using none of them and doing things otherwise if it doesn't require writing a substantial amount of additional code
One passes by value and one passes by reference:
By value:
$var = 'something';
function myFunc($var){
$var = 'hello';
}
echo $var; //something
By reference:
$var = 'something';
function myFunc(&$var){
$var = 'hello';
}
echo $var; //hello
For more information, the PHP manual has a page on passing by reference: http://php.net/manual/en/language.references.pass.php
In the case of globals, you are essentially pulling a variable from the global scope and using it inside of the function. It's like implicitly passing by reference.
This page, in particular the global section explains: http://us.php.net/manual/en/language.variables.scope.php
Please note that globals should typically be avoided. The short version of why is because they make knowing the state of a program difficult, and later changes can cause unexpected side effects.
func(CONST_A) should return 'CONST_A', func($name) should return $name
How to implement this func in PHP?
This doesn't seem possible easily.
You can use reflection to determine the parameters of the function, but that returns the variable names that the function expects, and if you're already inside the function, you kind of already know those.
debug_backtrace is the usual way of peeking at what called you, but it returns the values of the passed arguments, not the variable names or constants that the caller used when making the call.
However, what it does give you is the file name and line number of the caller, so you could open up the file and seek to that line and parse it out, but that would be very silly and you should not do this. I am not going to give you example code for this, as it is so utterly silly that you should not consider doing it ever.
The get_defined_vars thing is a hack and is not guaranteed to work either, and definitely won't work for constants, as get_defined_constants does that.
Try this:
<?php
function getVarConst($var)
{
if (isset($GLOBALS[$var]) // check if there is a variable by the name of $var
{
return $GLOBALS[$var]; // return the variable, as it exists
}
else if (defined($var)) // the variable didn't exist, check if there's a constant called $var
{
return constant($var); // return the constant, as it exists
}
else
{
return false; // return false, as neither a constant nor a variable by the name of $var exists
}
}
?>
This isn't possible.
You literally want the following right?
define('CONST_A', 'THIS COULD BE ANYTHING');
$name = 'who cares';
func(CONST_A); //returns 'CONST_A'
func($name); //returns '$name'
The function can't know that.
I suppose that reading the source code like Charles describes could get you this, but why?
Sorry for such a lame title, but I just had no idea what to put there, hope you understand it. Plus, I have no idea if similar question has been asked before, because I don't know the proper keywords for it - therefore couldn't google it too.
Basicly... When looking at preg_match_all();, they got this matches parameter that will create new array defined in function, and give us the ability to access it after function execution.
And the question is.. How can I implement such a feature in my own function? But that it could create single variable and/or array.
Thanks in advance!
preg_match_all() accepts a reference to an array, which in its own scope is called $matches. As seen in the function prototype:
array &$matches
If you call the function and pass in a variable, if it does not already exist in the calling scope it will be created. So in your user-defined function, you accept a parameter by reference using &, then work with it inside your function. Create your outer-scope variable by simply declaring it in your function call, like you the way you call preg_match_all() with $matches.
An example:
function foo(&$bar) {
$bar = 'baz';
}
// Declare a variable and pass it to foo()
foo($variable);
echo $variable; // baz
I think you are referring to function parameters passed by reference, are you not?
function putValInVar(&$myVar, $myVal){
$myVar = $myVal;
}
$myVar = 1;
putValInVar($myVar, 2);
echo $myVar; // outputs '2', but will output '1' if we remove the '&' //
By default function arguments in PHP are passed by value. This means that new variables are created at each function call and those variables will exist only inside the function, not affecting anything outside it.
To specify that an argument should be used by reference the syntax is to append an & before declaring it in the function header. This will instruct PHP to use the passed variable inside the function rather than creating a copy of it.
Exception: Objects are always passed by reference. (Well... Not really, but it's complicated. See the comment thread for more info.)
I think what you are asking for is passing-by-reference. What preg_match_all basically does to "create" an array variable outside its scope is:
function preg_match_all($foo, $bar, & $new_var) {
$new_var = array(1,2,3);
}
The crucial point here is & in the function definition. This allows you to overwrite variables in the outer scope when passed.
Stylistically this should be used with care. Try to return arrays or results instead of doing it via reference passing.
Like this:
$myvariable = runfunction();
function runfunction() {
//do some code assign result to variable (ie $result)
return $result;
}
Or
global $result;
function runfunction() {
global $result;
$result = 'something';
}