Strange behavior with unconventional passing of arguments - php

I accidentally copied the function header when calling a function in my code, and for some reason the code still works. Why is this?
$data = Utilities::multi_curl($substance_year_combo_groups, $files = false, $download_folder = null, $file_name = null, $pop = false, $handle_key = 'results');
Obviously, it's supposed to be written like this:
$data = Utilities::multi_curl($substance_year_combo_groups, false, null, null, false, 'results');
But I can see in my debugging that the last parameter indeed is 'results'. Shouldn't a pure variable assignment just be evaluated as true?
The $handle_key is null by default in the function header.

Already answered, but to include a reference from PHP: Assignment Operators Manual
The value of an assignment expression is the value assigned. That is, the value of "$a = 3" is 3.

The arguments get evaluated, and the results of those evaluations are passed in.
Remember that in PHP assignments have a "return value", which is the value that was assigned.
$foo = 'bar';
echo $foo;
$result = some_function($foo = 'blah');
echo $foo;
This code will echo out barblah, and pass blah into some_function as the argument.
This is the exact same mechanism that allows:
$a = $b = $c = $d = 42;
to work, and assigns 42 to all four variables.

The result of the assignment operation is the value being assigned. For instance, I can do this:
if($result = do_something_that_may_fail()) {}
Whatever the do_something_that_may_fail() method returns will be assigned to $result and, if that anything that doesn't evaluate to false, the if block will be executed. A byproduct of this is that you can still reference $result inside of the if block.
The same thing is happening in your method call, the values are being assigned and the value itself is being sent to the method.

Related

Using Ternary Operator without the Else statement PHP

Can you use the Ternary Operator in PHP without the closing 'else' statement? I've tried it and it's returning errors. Google search isn't yielding anything, so I think the answer is probably no. I just wanted to double check here. For instance:
if ( isset($testing) {
$new_variable = $testing;
}
Will only set $new_variable if $testing exists. Now I can do
$new_variable = (isset($testing) ? $testing : "");
but that returns an empty variable for $new_variable if $testing isn't set. I don't want an empty variable if it's not set, I want the $new_variable to not be created.
I tried
$new_variable = (isset($testing) ? $testing);
and it returned errors. I also tried
$new_variable = (isset($testing) ? $testing : );
and it also returned errors. Is there a way to use the Ternary Operator without the attached else statement, or am I stuck writing it out longhand?
EDIT: Following Rizier123's advice, I tried setting the 'else' part of the equation to NULL, but it still ends up appending a key to an array. The value isn't there, but the key is, which messes up my plans. Please allow me to explain further.
The code is going to take a bunch of $_POST variables from a form and use them for parameters in a stdClass which is then used for API method calls. Some of form variables will not exist, as they all get applied to the same variable for the API call, but the user can only select one. As an example, maybe you can select 3 items, whichever item you select gets passed to the stdClass and the other 2 don't exist.
I tried this:
$yes_this_test = "IDK";
$setforsure = "for sure";
$list = new stdClass;
$list->DefinitelySet = $setforsure;
$list->MaybeSet = (isset($yes_this_test) ? $yes_this_test : NULL);
$list->MaybeSet = (isset($testing) ? $testing : NULL);
print_r($list);
But obviously MaybeSet gets set to NULL because (isset($testing) comes after (isset($yes_this_test) and it returns
stdClass Object ( [DefinitelySet] => for sure [MaybeSet] => )
I won't know what order the $_POST variables are coming in, so I can't really structure it in such a way to make sure the list gets processed in the correct order.
Now I know I can do something like
if ( isset($yes_this_test ) {
$list->MaybeSet = $yes_this_test;
}
elseif ( isset($testing) ) {
$list->MaybeSet = $testing;
}
But I was hoping there was a shorthand for this type of logic, as I have to write dozens of these. Is there an operator similar to the Ternary Operator used for if/elseif statements?
Since PHP 5.3 you can do this:
!isset($testing) ?: $new_variable = $testing;
As you can see, it only uses the part if the condition is false, so you have to negate the isset expression.
UPDATE
Since PHP 7.0 you can do this:
$new_variable = $testing ?? null;
As you can see, it returns its first operand if it exists and is not NULL; otherwise it returns its second operand.
UPDATE
Since PHP 7.4 you can do this:
$new_variable ??= $testing;
It leaves $new_variable alone if it isset and assigns $testing to it otherwise.
Just set it to NULL like this:
$new_variable = (isset($testing) ? $testing : NULL);
The you variable would return false with a isset() check.
You can read more about NULL in the manual.
And a quote from there:
The special NULL value represents a variable with no value. NULL is the only possible value of type null.
A variable is considered to be null if:
it has been assigned the constant NULL.
it has not been set to any value yet.
it has been unset().
Since PHP 7.0 you can do the following, without getting an ErrorException "Trying to get property 'roomNumber' of non-object":
$house = new House();
$nr = $house->tenthFloor->roomNumbers ?? 0
Assuming the property "tenthFloor" does not exist in the Class "House", the code above will not throw an Error.
Whereas the code below will throw an ErrorException:
$nr = $house->tenthFloor->roomNumbers ? $house->tenthFloor->roomNumbers : 0
You can also do this (short form):
isset($testing) ? $new_variable = $testing : NULL;
JUST USE NULL TO SKIP STATEMENTS WHEN IT WRITTEN IN SHORTHAND
$a == $b? $a = 20 : NULL;

PHP - Assigning a value in IF statement - false if null

I'm trying to simplify some code. I've found that if you assign a value within an if statement, but the value ends up being null, then the evaluated if is FALSE.
Example:
if($myvar = doSomething()) {
echo '$myvar = '.$myvar;
}
else {
echo "was null";
}
function doSomething() {
$a = null;
return $a;
}
The script above will display "was null". However, if $a = 1, then it will display "myvar = 1".
I've tried to find some documentation around this behaviour but haven't been successful. All of my sources are close, but don't describe it well.
My question: Is this expected behaviour? If doSomething() returns null, is what I'm doing equivalent to if(null) {...?
EDIT: YES I mean '=' not '==' in the if statement. What I'm asking is it expected that this should always return false: if($a = null) whereas this returns true if($a = 1)
What you're doing is fully expected. The value of the assignment expression $a=b is the assigned value b. So,
if($myvar = doSomething()) { ...
is equivalent to
$myvar = doSomething();
if ($myvar) { ...
This behavior is completely unrelated to the if statement. The documentation clearly states, in the second paragraph:
The value of an assignment expression is the value assigned. That is, the value of "$a = 3" is 3.
Try to call function in variable.
$getvar = doSomething();
if($myvar == $getvar) {
// stuff
}

PHP help - only need a simple explanation

Alright, I'm trying to understand how this PHP code works.
<?php
$test = "success";
$primary = "test";
$id = ${$primary};
echo $id;
?>
I know the output is "success" but I don't understand how it works.
What i understand so far:
test variable has the string "success",
primary variable has the string "test",
'id' variable has the string of the first variable in the list (the test variable),
print the string in the 'id' variable.
I'm confused because i don't know what the primary variable is doing in the braces within the id variable.
A simple explanation would be appreciated.
This is a concept called variable variables.
It means that at runtime, if multiple variable indicators $ are present, PHP will attempt to associate them in a cascading manner.
For example, take the following:
$a = "b";
$b = "c";
$c = "d";
echo $$$a;
PHP will systematically go through the echo statement to determine what the actual value is, as such:
$$$a is equivalent to $$("b") (because $a is "b")
...which is equivalent to $("c") (because $b is "c")
...which is finally equivalent to "d"
In your example, you're given a variable assignment to something that, in essence, is like ${$a}. In PHP, braces are used to isolate variables within strings, but can be used on their own to denote a variable explicitly, so ${$a} is exactly equivalent to $$a in this case.
$id = ${$primary};
try to parse from right to left $primary = 'test'
so ${$primary} is now $test
so equation becomes $id = $test;
$id = $test = success
Know more about variables variables on the link provided by other users
This is a variable variable.
$test = "success";
$primary = "test";
//${$primary} means $test here, because value of $primary is "test".
//It is equal to $$primary
$id = ${$primary};
echo $id; //Prints "success"
http://php.net/manual/en/language.variables.variable.php

Default argument value is overriding provided argument?

I have a function in PHP, which has some arguments default to null, so that I can easily call it with less than the full number of arguments.
The problem is, that when I use a null-defaulted argument directly, I get the given argument, but when I try to copy that value to another variable, the variable only gets the default value of null.
It looks like this:
// inside my MySQLI wrapper class...
public function bind(&$stmt, $types = "", &$arg1, &$arg2 = null, &$arg3 = null /* this goes up to 20; it's auto-generated by another script */)
{
echo "dumping...";
var_dump($arg1); // var_dump shows value from function call (string(0))
var_dump($arg2); // ditto
echo "...dumped";
if ($arg2 != null) $foo = $arg2; var_dump($foo); echo "foo"; // var_dump shows that $foo is NULL
/* ... */
}
I call the function like this, from another script:
(It's a dummy script dealing with trucks and cars.)
$make = "";
$model = "";
$year = 0;
$license = "";
list($error, $message) = $mysql->bind($stmt, "", $make, $model, $year, $license);
My bind() function is a wrapper to MySQLI's bind_param() and bind_result() functions.
I've only included the top couple lines, because it's failing at that point already, before it even gets to the actual logic.
Right now, it just looks like it's a bug in PHP, because this doesn't follow what I know about how variables, arguments, default arguments, and references work.
Furthermore, this problem only appears to manifest itself in my real code, and doesn't appear in my simple php file that I coded up to test this.
Further info:
$foo gets assigned NULL, when $arg2 is an empty string, "", and properly gets assigned when it is a non-empty string. Empty strings are still valid strings, so why is PHP doing this?
The problem is the != comparison. What happens is that PHP type-juggles at least one of your variables, and as such, "" != null evaluates to false. The table part-way down this page shows what will happen for comparisons between different types. A type-strict form !== is needed:
if ($arg2 !== null)
$foo = $arg2;

PHP pass default argument to function

I have a PHP function, like this:
function($foo = 12345, $bar = false){}
What I want to do, is call this function with the default argument of $foo passed, but $bar set to true, like this (more or less)
function(DEFAULT_VALUE, true);
How do I do it? How do I pass an argument as a function's default value without knowing that value?
Thanks in advance!
This is not natively possible in PHP. There are workarounds like using arrays to pass all parameters instead of a row of arguments, but they have massive downsides.
The best manual workaround that I can think of is defining a constant with an arbitrary value that can't collide with a real value. For example, for a parameter that can never be -1:
define("DEFAULT_ARGUMENT", -1);
and test for that:
function($foo = DEFAULT_ARGUMENT, $bar = false){}
put them the other way round:
function($bar = false, $foo = 12345){}
function(true);
The usual approach to this is that if (is_null($foo)) the function replaces it with the default. Use null, empty string, etc. to "skip" arguments. This is how most built-in PHP functions that need to skip arguments do it.
<?php
function($foo = null, $bar = false)
{
if (is_null($foo))
{
$foo = 12345;
}
}
?>
PHP can't do exactly that, so you'll have to work around it. Since you already need the function in its current form, just define another:
function blah_foo($bar)
{
blah(12345, $bar);
}
function blah($foo = 12345, $bar = false) { }
i think, it's better sorted based on the argument that the most frequently changed, $bar for example, we put it first,
function foo( $bar = false, $foo = 12345){
// blah blah...
}
so when you want to pass $bar to true, and $foo to 12345, you do this,
foo(true);

Categories