I have a weird problem trying to use closures in PHP. When assigning a closure to a variable, I get a null value. But when displaying the closure with var_dump(), everything is alright.
Here is a source code that summarizes the problem:
$f = function() {};
var_dump($f); // 'null'
var_dump(function() {}); // 'object(Closure)[1]'
I'm using PHP 5.3.1.
Edit: I forgot to mention, I have this problem only when I'm using PHP via Apache. I don't have issues when using PHP CLI.
A colleague found the answer to the problem: the responsible is eAccelerator! Apparently it's not compatible with PHP 5.3 closures... (source)
Disabling it solved the problem.
Thanks for your help!
It's either a very rare (and already fixed) bug or you're not showing the exact same usage that gives you a NULL. My guess is that you're doing this with the first var_dump():
var_dump($f());
Note the parenthesis, they cause the function to be run and therefore you get its return value.
Related
I upgraded from php 5 to 7.2, and there is no problem at local (some changes needed, but it solved).
One of my function not working in production server.
The code looks like this:
$someBool = in_array($some, array("asd", "fgh", "etc"));
If I make a var_dump on this, the result is UNKNOWN:0, but if I make a vardump exactly below this (there is no any if station before dump), the function works correctly, end the dump result will be bool (true) or bool (false).
(I don't overwrite this variable)
Again if I comment the var_dump line, the function works incorrectly.
There is anybody who has idea what can cause this behaviour?
Thanks for your help.
In the original function:
$needCmdText = in_array($fieldName,array(
'cmdpreid','cmdpostid','cmdskipid',
'cmdfixid','cmdexpid','cmdsysid'
));
Where the $fieldName always 'cmdexpid' from the client. (at my test cases)
And a funny news, a simple echo solve the problem too, but it should be under this.
I changed the php 7.2 to 7.1, which solved the problem without any code changing. (No need to dump, to solve).
I think there is a strange bug in php 7.2, which doesn't occure in windows environment.
Before anyone mark my question as duplicate, I wish to clarify that my case is unique and specific to PHP 7 (I use PHP 7.1.1 in UniformServer). I have seen all other similar questions here and they did not work for me.
I had a working code as below:
In class constructor:
$this->fldSection = "header";
down below in another function:
$_ENV['validate'][$this->fldSection][$this->name] = $params;
This is working fine in PHP 5.6. However this gives the infamous "Cannot use string offset as an array.." error in PHP 7.1.1 for $this->fldSection = 'header' when it is set in the $_ENV variable
All my variables are dynamically filled. Is there a different/better way to accomplish this in PHP 7.1.1?
I finally cracked the reason for this issue. I'm using the super-global $_ENV to store my values and trying to assign variable-variables to it. However from PHP documentation I find that variable-variables are not supported on super-globals. I changed the variable to $GLOBAL instead of $_ENV (like below) and it worked.
$GLOBAL['validate'][$this->fldSection][$this->name] = $params;
I'm not sure why it worked on 5.6 and not on 7.1. I guess PHP has probably started enforcing those rules strictly only from v7.
Is there any way to easily fix this issue or do I really need to rewrite all the legacy code?
PHP Fatal error: Call-time pass-by-reference has been removed in ... on line 30
This happens everywhere as variables are passed into functions as references throughout the code.
You should be denoting the call by reference in the function definition, not the actual call. Since PHP started showing the deprecation errors in version 5.3, I would say it would be a good idea to rewrite the code.
From the documentation:
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);.
For example, instead of using:
// Wrong way!
myFunc(&$arg); # Deprecated pass-by-reference argument
function myFunc($arg) { }
Use:
// Right way!
myFunc($var); # pass-by-value argument
function myFunc(&$arg) { }
For anyone who, like me, reads this because they need to update a giant legacy project to 5.6: as the answers here point out, there is no quick fix: you really do need to find each occurrence of the problem manually, and fix it.
The most convenient way I found to find all problematic lines in a project (short of using a full-blown static code analyzer, which is very accurate but I don't know any that take you to the correct position in the editor right away) was using Visual Studio Code, which has a nice PHP linter built in, and its search feature which allows searching by Regex. (Of course, you can use any IDE/Code editor for this that does PHP linting and Regex searches.)
Using this regex:
^(?!.*function).*(\&\$)
it is possible to search project-wide for the occurrence of &$ only in lines that are not a function definition.
This still turns up a lot of false positives, but it does make the job easier.
VSCode's search results browser makes walking through and finding the offending lines super easy: you just click through each result, and look out for those that the linter underlines red. Those you need to fix.
PHP and references are somewhat unintuitive. If used appropriately references in the right places can provide large performance improvements or avoid very ugly workarounds and unusual code.
The following will produce an error:
function f(&$v){$v = true;}
f(&$v);
function f($v){$v = true;}
f(&$v);
None of these have to fail as they could follow the rules below but have no doubt been removed or disabled to prevent a lot of legacy confusion.
If they did work, both involve a redundant conversion to reference and the second also involves a redundant conversion back to a scoped contained variable.
The second one used to be possible allowing a reference to be passed to code that wasn't intended to work with references. This is extremely ugly for maintainability.
This will do nothing:
function f($v){$v = true;}
$r = &$v;
f($r);
More specifically, it turns the reference back into a normal variable as you have not asked for a reference.
This will work:
function f(&$v){$v = true;}
f($v);
This sees that you are passing a non-reference but want a reference so turns it into a reference.
What this means is that you can't pass a reference to a function where a reference is not explicitly asked for making it one of the few areas where PHP is strict on passing types or in this case more of a meta type.
If you need more dynamic behaviour this will work:
function f(&$v){$v = true;}
$v = array(false,false,false);
$r = &$v[1];
f($r);
Here it sees that you want a reference and already have a reference so leaves it alone. It may also chain the reference but I doubt this.
So i have an Api call where i get a json array:
When i do the following:
$data = $this->HasOffers->get_full_detail_report()['data']['data'];
$this->set('data',$data);
i get an error saying an internal error has occoured
However if i do:
$data = $this->HasOffers->get_full_detail_report();
$data2 = $data['data']['data'];
$this->set('data',$data2);
everything is working correctly.
Now my question is why is this happening? and how can i fix it?
The syntax you are using in the first example is only available in PHP >= 5.4. See relevant section of PHP manual: http://php.net/manual/en/language.types.array.php#example-88
You can see an example running in different versions of PHP at: http://3v4l.org/XhCKH
Your CakePHP site likely has error reporting turned off so, rather than displaying the syntax error, it is displaying an Internal Error.
I'm guessing you have debug < 2, so the description of the error is not very detailed. However, that behaviour is known to be a PHP < 5.4 issue (post regarding that subject).
To "fix" it, you need to upgrade PHP to 5.4 at least. Or, just use an intermediary variable for those cases, it's not that bad.
This is happening because the array you are referencing in the first example only exists after the function get_full_detail_report() is called. PHP does not like this. PHP wants your array to exists before you reference it. I assume that it attempts to locate any variables within your statement before performing any operations, which would mean it is searching for an array that does not exist until it performs those operations.
If anyone has any more insight into this, I would welcome their revisions / comments.
My site has a deprecated error at this line:
$obj =& new $class($table,$primkeyArr,$this);
it is because of &. It gives this error:
Deprecated: Assigning the return value of new by reference is deprecated in ....
It is a issue in php 5.3.
If I remove the & from this line, the error does away. But I don't know if it causes any problem if I put my site on a server with lower PHP version (5.2) or not.
Will removing the & work ok both in PHP 5.2 and in PHP 5.3?
In PHP 5, objects are handled in a reference-like manner by default. So removing the & probably won't change anything.
But as assigning by reference breaks old references, there might still be a difference.
It's not deprecated to return a reference but to not reflect that in your functions oder methods signature. There has to be an & before the name as well as when assigning the returned value.
public function &getValue()
{
return $this->value;
}
...
$myValue = &$obj->getValue();
The manual will tell you more.
http://php.net/manual/en/language.references.pass.php
It's a mere warning. You don't really need it, but the short answer is that it will only throw warnings. Depending on the level of error_handling in your php config will depend on if you see it on other 5.3 systems.