I have been looking for an error in my code since an hour. This was the error:
Writing:
if(isset(($_POST['to'])))
instead of
if(isset($_POST['to']))
I don't get why is this extra pair of brackets causing an Internal Server Error.
I don't think putting brackets around a variable never changes its value. I mean,
$a = $b;
$c = ($b);
$a==$c; //True
I am curious as to know why is it an error?
Thank you.
EDIT:
The above error was occurring for normal variable also.
This is because isset is not a function but a language construct; as such, its definition can be found in the language parser.
T_ISSET '(' isset_variables ')' { $$ = $3; }
It only expects one pair of braces; passing another pair will cause a parse error.
Im pretty sure it has something to do with the fact that isset can not take a function in parameter. You have to pass it a value. Your extra pair of parenthesis may be evaluated as a 'function' or something that need to be evaluated.
Normally, when you try to pass a function to isset, you get this error :
Can't use method return value in write context
isset:
Warning
isset() only works with variables as passing anything else will result in a parse error. For checking if constants are set use the defined() function.
Information can be passed to functions through arguments. An argument is just like a variable.
Arguments are specified after the function name, inside the parentheses. You can add as many arguments as you want, just seperate them with a comma.
The following example has a function with one argument ($fname). When the familyName() function is called, we also pass along a name (e.g. Jani), and the name is used inside the function, which outputs several different first names, but an equal last name:
<?php
function familyName($fname)
{
echo "$fname Refsnes.<br>";
}
familyName("Jani");
familyName("Hege");
familyName("Stale");
familyName("Kai Jim");
familyName("Borge");
?>
Related
I have the following code:
$family = cis_resempty(wp_get_post_terms($post->ID,'family'),0);
I get the following error:
Notice: Only variables should be passed by reference in
C:\xampp.....xxx.php on line 18
If I do the following:
$family = cis_resempty(array('a'),0);
I even get
Fatal error: Only variables can be passed by reference in
C:\xampp...xxx.php on line 16
The function cis_resempty is like this (but its from a library):
function cis_resempty(&$var,$key) { ... }
Found out that if I remove the & reference sign within the parameter list of cis_resempty there are no errors.
If I do this:
$family = #cis_resempty(wp_get_post_terms($post->ID,'family'),0);
There is no notice and everything works - but Netbeans says:
Misuse of the error control operator
But if I do this:
$family = #cis_resempty(array('a'),0);
The fatal error continues to exist.
Why can I pass a function by reference and suppress the notice with the error control operator but if I pass an array I get a fatal error?
Why is it bad to pass a non variable by reference?
NOTE: never use '#' for suppressing.
Why can I pass a function by reference and suppress the notice with
the error control operator but if I pass an array I get a fatal error?
Read here Passing by Reference first note:
There is no reference sign on a function call - only on function definitions. Function definitions alone are enough to correctly pass the argument by reference. As of PHP 5.3.0, you will get a warning saying that "call-time pass-by-reference" is deprecated when you use & in foo(&$a);. And as of PHP 5.4.0, call-time pass-by-reference was removed, so using it will raise a fatal error.
PHP doesn't "support" it since 5.4.0 => you get E_FATAL in any case. With # or without #. For function - you get E_STRICT. All right. Then, read about # work more here Error Control Operators. Again, first note:
Note: The #-operator works only on expressions. A simple rule of thumb is: if you can take the value of something, you can prepend the # operator to it. For instance, you can prepend it to variables, function and include calls, constants, and so forth. You cannot prepend it to function or class definitions, or conditional structures such as if and foreach, and so forth.
Try this code ( it will shed light) :
error_reporting(E_ALL);
$arr = [1,2,3,4,5,];
$a_closure = function(){
return [1,2,3,4,5];
};
function a(){
return [1,2,3,4,5];
}
function ref_func(&$input){
foreach($input as &$in){
$in++;
}
}
ref_func($a); // #ref_func($a);
ref_func(a()); // #ref_func($a());
ref_func($a_closure); // #ref_func($a_closure);
// Fatals in both
ref_func([1,2,3,4,5]); // #ref_func([1,2,3,4,5]);
The term "non-variable" refers to any variable which the programmer cannot reference by name. These are temporary variables allocated by the executor at runtime: The result of a function call or some other expression, that is not assigned to a named variable.
To pass something by reference only makes sense if the variable being passed by reference is named, so that when the call is over, the caller can access that which was passed by reference to the callee.
When PHP comes across a function call at compile time, the space for the result of the function call, and parameters of the function call are reserved, and then allocated at execution time relative to the execution frame. When you pass the result of a function call by reference, the executor is able to force by-reference behaviour for the variable, because there is space on the heap and it can just ignore that the variable has no name ... it doesn't usually make sense to do that, but remains for backward compatibility reasons.
When PHP comes across a literal (array) at compile time, it allocates the space for the data relative to the op array (function) itself. Because of that difference forcing by-reference behaviour of literals would be dangerous and cause very unexpected behaviour: Consider what would happen when the function is re-entered, concurrently or otherwise.
If i use
strtolower(end(explode('.',$_FILES['file']['name'])));
it give me error
PHP Strict Standards: Only variables should be passed by reference in
I thought ok I just store the values in a variables first, and then use explode
$filename = $_FILES['file']['name'];
$filearray = explode('.',$filename);
and it works fine
But i have another line
strtolower(end($filearray));
I thought it should give me the same error , i mean i should first have to store end($filearray) in a variable then use that variable in strtolower(),
But this is not giving me any error ,So why strtolower() accepting a function as parameter , and not giving an error , can someone explain why ?
It's not strtolower that gives you the warning - but end function. Quoting the docs:
end() advances array's internal pointer to the last element, and
returns its value. [...] The array is passed by reference because it
is modified by the function. This means you must pass it a real
variable and not a function returning an array because only actual
variables may be passed by reference.
In your first example you attempt to end the result of explode call - i.e., not a real variable. While it's possible for PHP to ignore such a use case, it usually means that you've done something by mistake - and E_STRICT warning attempts to notify you about it.
Your third example works fine, because:
1) strtolower actually doesn't care about the reference. It returns a string with all alphabetic characters converted to lowercase instead of modifying the string in place.
2) end has a variable - array - passed in. It returns its last element, while advancing the internal pointer of that array to, well, its end. Have you attempted to employ this internal pointer (with current or some other means), you'd see the difference.
As a sidenote (already mentioned in comments by #DoktorOSwaldo), you can replace the all explode(end() stuff with simple pathinfo call:
$ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
Because some functions in php are passed as a reference. end is one of those functions. see doc : http://php.net/manual/en/function.end.php
But the strtolower function gets just a normal parameter.
So why does the end function gets a reference? End will not just return the last element, but will also move the array's internal pointer to the last element. so if you call current function after the end function you will get the last element.
So basically end function will modify the array passed in parameter. And therefore it needs to be a variable that it can modify get as a reference.
I am fairly new to PHP and just had a learning experience that I am sharing here to help others who, like me, may need help to find the cause of this error and also because I still don't know what the solution is and am sure there is simply a syntax that I just haven't found yet to do what I need to do.
So, the problem can be demonstrated with something like this:
class Sample {
protected $foo = array();
public function magicSampleSetFunc($property, $key, $value) {
$this->$property[$key] = $value;
}
}
...
$s = new Sample();
$s->magicSampleSetFunc('foo', 'someKey', 'someVal');
Obviously, this isn't my real code (nor have I run it) this is just a minimal example to explain my situation. Here we have a member variable foo that is clearly an array and a generic function that is going to try to set a key and value into it. I can var_dump $this->$property and see that it is an array, but on the $this->$property[$key] line I get the error message: "Warning: Illegal string offset 'someKey' in ...".
At first I though it was saying that 'someKey' was an illegal string to use as an array offset, which didn't make sense. And, even if I wrap it in an isset it complains. The first thing I learned is that if you have a string in php, you can use the array access operator to get a character out of that string. So the warning message is actually complaining that 'someKey' is not a valid offset into a string (because it is not an integer offset). Okay, but I just var_dumped $this->$property and see that it is an array, so what gives? The second lesson was one of operator precedence. The array operator "[]" binds tighter than the indirection operator "->". So, the binding of that statement is actually something like: ( $this-> ( $property[$key] ) ). So, it is illegally trying to offset the string in $property by the index in $key. What I wanted was to offset the array in $this->$property by the index in $key.
So, now we come to my question. The third lesson I need to learn, and haven't figured out yet is how do I override this operator precedence issue? I tried ($this->$property)[$key] but that appears to be a sytax error. Is there some other syntax I can use to get the interpreter to understand what I meant to do? Or, do I have to assign $this->$property to a temporary variable first? If I do, wouldn't that mean that my actual member variable array is not updated? Do I need a temp reference or something? What's the right syntax for my situation here? Thanks!
this is the way to do it:
Your variable name is basically {$property} so when you do $this->$property[$key] I think PHP parser gets confused. I usually make sure that to explicitly state it to the parser that my variable name is $property which is done by using curly braces around variable.
Curly braces are used to explicitly specify the end of a variable name
class Sample {
protected $foo = array();
public function magicSampleSetFunc($property, $key, $value) {
$this->{$property}[$key] = $value;
}
}
...
$s = new Sample();
$s->magicSampleSetFunc('foo', 'someKey', 'someVal');
I'm just starting to learn PHP and am using the W3 Schools tut. In the error handling section there is this code:
<?php
function customError($errno,$errstr) {
echo '<b>Error:</b> [$errno] $errstr<br />';
}
set_error_handler('customError');
echo($test);
?>
Why is the customError() function being passed as a string? Is this a mistake in the tut?
Also, why isnt $test defined?
Why is the customError() function being passed as a string?
For the same reason that usort or ob_start take strings for function specifiers. PHP just needs the name of the function. A function name not enclosed in quotes with either try being executed as a constant or (if followed by parenthesis) will be executed and the result passed to the function.
Because of the way PHP parses documents for execution, you have to work within the means of the language (use strings instead of "pointers" to function calls).
Also, why isnt $test defined?
This is a purposeful call to trigger an error. They are trying to get you to work with an undefined variable so an error occurs and the code you just wrote (with the custom handling) catches the error.
No, it's not an error. It's not so common, but some standard PHP functions accept functions name as parameter when you have to pass a function for same reason. set-error-handler is one of these function.
If you are curios about that, you can read here:
http://it2.php.net/manual/en/language.pseudo-types.php#language.types.callback(dead link)
The set_error_handler method takes a string as its first parameter -> http://php.net/manual/en/function.set-error-handler.php this is the function invoked for errors
The echo($test) causes an error to be thrown thus invoking the customError function
Because customError is not actually being passed as a string, per se, but rather its name is being passed as a string to PHP. See http://php.net/manual/en/function.set-error-handler.php , it allows you to specify a custom error handler function to PHP.
This finds what it is supposed to:
if(!preg_match($match="/^http\/[0-9]+\\.[0-9]+[ \t]+[ \t]*(.*)\$/i",$line,$matches))
But this does not:
if(!preg_match("/^http\/[0-9]+\\.[0-9]+[ \t]+[ \t]*(.*)\$/i",$line,$matches))
The function reference for preg_match says that the first argument passed should be:
The pattern to search for, as a
string.
But the working example I give above assigns the pattern to a variable: $match=...
What is going on here? I have never seen a variable used with preg_match like that. I thought it should be:
preg_match(string $regexpattern, string $thingtosearch, array $matches)
Can anyone explain what's happening here?
The first example saves the pattern to a local variable.
if(!preg_match($match="/^http\/[0-9]+\\.[0-9]+[ \t]+[ \t]*(.*)\$/i",$line,$matches))
It is equivalent to writing it like that:
$match="/^http\/[0-9]+\\.[0-9]+[ \t]+[ \t]*(.*)\$/i";
if(!preg_match($match,$line,$matches))
The preg_match function doesn't "see" that the parameter was assigned to a variable, it only ever receives the value - because there are no named function parameters in PHP. It's hence unimportant how you name the local variables, and the $param definition in the manual has zero influence over functionality.
A probable explanation for this code structure is that the regex pattern $match might be reused later on. Sometimes this notation is just used for readability. (It's garbaging up the local variable scope, yet adds some minor clarity.)
An assignment expression returns the value that was assigned. So in your case the assignment expression $match="…" returns the assigned value "…" that results in the same parameter for the function as without that assignment.
Doing it that way is useful in some cases like in a condition of while:
while ($row = mysql_fetch_array($result))
Here $row = mysql_fetch_array($result) returns the same value that was returned by mysql_fetch_array($result) but it’s also assigned to $row.