I just installed xampp, to run some old program (created 2 or more years ago) and I'm getting 3 errors I can't figure out.
Strict Standards: Only variables should be passed by reference in C:\xampp\htdocs\2010\web\core\route\route.php on line 117
public function loadClass($address,$ext='') {
$this->extname = preg_replace('/_/','/',$address,3);
line:117> $this->classname = end(explode('_',$address)).($e= $ext!='' ? '('.$ext.')' : '');
include_once(ROOT_ROUTE.'/'.$this->extname.'.php');
$this->newclass = new $this->classname;
return $this->newclass;
}
the line 117 i can't understand, it is not using passed by reference, why there is a error?
Because end() expects an argument passed by reference, you can't use it with a non-variable such as the direct result of another function call or construct.
Quoting from the argument definition in the manual:
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.
Change
$this->classname = end(explode('_',$address)).($e= $ext!='' ? '('.$ext.')' : '');
to
$addressTemp = explode('_',$address);
$this->classname = end($addressTemp) . ($e= $ext!='' ? '('.$ext.')' : '');
Related
I have a PHP class where one of the private member is a callback to my log function (i.e. in PHP land, a function pointer is simply a string containing the name of the function to call).
self::$logferr = "msgfunc";
self::$logferr($res);
I get this error:
Fatal error: Function name must be a string
self::$logferr is equal to "msgfunc" which is my log function.
If I rewrite the code like this (on the same very class method):
$tmp = "msgfunc";
$tmp($res);
It works, the log function get called
Just wrap your variable in parenthesis, let PHP resolve the value first:
(self::$logferr)($res);
Proof of concept
You can use call_user_func. ref: this
call_user_func(self::$logferr, $res);
You should call it by using
self::{self::$logferr}($req)
Working example : https://3v4l.org/CYURS
Let's build a reproducible example:
class Foo {
private static $_loggerCallback;
static function setLogCallback(callable $loggerCallback) {
self::$_loggerCallback = $loggerCallback;
}
static function log(...$arguments) {
if (NULL !== self::$_loggerCallback) {
return self::$_loggerCallback(...$arguments);
}
return NULL;
}
}
Foo::setLogCallback(function() { echo 'success'; } );
Foo::log();
Output:
Notice: Undefined variable: _loggerCallback in /in/f3stL on line 13
Fatal error: Uncaught Error: Function name must be a string in /in/f3stL:13
The notice reports the actual mistake in this case. If you do not get something like it, you should check your error reporting configuration.
The notice shows that PHP looks for a local variable $_loggerCallback. It tries to execute $_loggerCallback(...$arguments). Here are different possibilities to make the call explicit.
Use parenthesis (PHP >= 7.0):
return (self::$_loggerCallback)(...$arguments);
Use a local variable (as you did):
$callback = self::$_loggerCallback;
return $callback(...$arguments);
A small advise. PHP support anonymous functions. You do not need a (global) function for a callback. This avoids calling to the function by name as well.
I am a bit stuck with question why in PHP 7 dropped functionality of accesing object methods using array elements as method name.
E.g.:
$carObj = new Car();
$array = ['method'=>'getMilage', 'object'=>$carObj];
// FATAL HERE:
$mileage = $array['object']->$array['method']();
// WORKS OK:
$objName = $array['object'];
$metName = $array['method'];
$mileage = $objName->$metName();
This code works on PHP 5.6 for sure, however when switched to PHP 7.1 it throws now fatal. Failed to find anything re this in release notes and SO topics.
P.S. Originally found this in Magento 1.14.2.0 version upon PHP upgrade, as Varien library uses this code:
File: Varien/File/Uploader.php
//run validate callbacks
foreach ($this->_validateCallbacks as $params) {
if (is_object($params['object']) && method_exists($params['object'], $params['method'])) {
$params['object']->$params['method']($this->_file['tmp_name']);
}
}
Gives this:
Fatal error: Uncaught Error: Function name must be a string in
/var/www/html/lib/Varien/File/Uploader.php on line 274
--
EDIT #1:
You can TEST it here:
http://sandbox.onlinephpfunctions.com/code/d1d2d36f96a1b66ed7d740db328cd1f14cc2d7d8
(Note: I'm assuming the 'object'=>'carObj' declaration is supposed to be 'object'=>$carObj here - there's no way this code works in any version of PHP otherwise.)
The clue is in the Notice: Array to string conversion in... notice raised before the fatal error.
In PHP 5, the following statement:
$array['object']->$array['method']();
is evaluated like this:
$array['object']->{$array['method']}();
where $array['method'] is evaluated before calling it on the object.
In PHP 7, it's evaluated like this
($array['object']->$array)['method']();
where the $array property is looked up on the object first. Since it doesn't exist (obviously, since it's an array), a notice is thrown, and then a subsequent fatal error when the method itself can't be called.
If you want to preserve the PHP 5 behaviour, wrap some {} around the method name lookup:
$carObj = new Car();
$array = ['method'=>'getMilage', 'object'=>$carObj];
$mileage = $array['object']->{$array['method']}();
See https://3v4l.org/Is5lX
This is explained in a bit more detail here: http://php.net/manual/en/migration70.incompatible.php
Your code works for sure not in PHP5.6
The content of $array['object'] is an string and using the -> member operator on an string always throws an error
Call to a member function getMilage() on string in [...][...] on line [...]
The only way to get this to work is resolve the var with $ or - even better store the object inside the array and not simply the var.
$mileage = ${$array['object']}->$array['method']();
better solution
$array = ['method' => 'getMilage', 'object' => $carObj];
$mileage = $array['object']->{$array['method']}();
Sidenote: in php7 they changed the evaluation order in case of ambiguities - so you have to add explicitly {} around $array['method']. To prevent this, one would normaly extract first the object and method and then simply call it without the array dereferencing.
Btw. the Magento Varien code you posted also expects $params['object'] to be an array. There is even a is_object test to ensure, you couldn't pass just var names.
//run validate callbacks - even in php7
foreach ($this->_validateCallbacks as $params) {
if (is_object($params['object']) && method_exists($params['object'], $params['method'])) {
$object = $params['object'];
$method = $params['method'];
$object->$method($this->_file['tmp_name']);
}
}
You must add $ before the object variable
$carObj = new Car();
$array = ['method'=>'getMilage', 'object'=>'carObj'];
$object = $array['object'];
$method = $array['method'];
// FATAL HERE:
$mileage = $$object->$method();
// WORKS OK:
$objName = $array['object'];
$metName = $array['method'];
$mileage = $$objName->$metName();
I have this function in PHP 5:
function myPHPFunction($shows) {
foreach($shows as &$show) {
$showData = $this->Api->getID(null, $show->showId, false);
$show->Id = $showData->Id;
}
return $shows;
}
the $shows array has empty id, I am able to get the id with an Api call and when I return $shows at the end, the id field is populated. If I move this code to PHP 4:
function myPHPFunction($shows) {
foreach($shows as $show) {
$showData = $this->Api->getID(null, $show->showId, false);
$show->Id = $showData->Id;
}
return $shows;
}
The $shows array still has an empty id field when I return is. Does it have something to with &$ because the & does not work in PHP 4
Yes pass by reference was available only after PHP 4.0.4
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.
Source
I am recieving the following error
Strict Standards: Only variables should be passed by reference in C:\wamp\www\dragdrop\newhotel\reservation\ajax\tips.php on line 8
Line 8 is
$img=mysql_real_escape_string(end(explode('/',$_POST['img'])));
I'm a newbie please help me..
Explode is a function so you can't pass it to end. Use an intermediate variable.
$List = explode('/',$_POST['img']);
$img=mysql_real_escape_string(end($List));
Should work
You are not passing a variable, you are passing an array directly.
http://php.net/manual/de/function.end.php
$var = explode('/',$_POST['img']);
$var = end($var);
$img = mysql_real_escape_string($var);
I have a class:
class Validator {
private $validationArray;
private $cleanedValues;
public function __construct($arg1, $arg2=NULL) {
if(empty($arg2)) {
$this->LoadValidatorByName($arg1);
} else {
$this->LoadValidatorFromLeadType($arg1, $arg2);
}
}
private function LoadValidatorFromLeadType($lead_type, $vocabulary) {
$ErrorReporter = new ErrorReporter;
$taxonomy_term = reset(taxonomy_get_term_by_name($lead_type, $vocabulary));
...some more stuff
The function taxonomy_get_term_by_name is a Drupal function but the issue I am experiencing is a PHP one.
When this method is called PHP complains with:
Strict warning: Only variables should be passed by reference in Validator->LoadValidatorFromLeadType() (line 32 of [path to my file])
Line 32 is ths line with:
$taxonomy_term = reset(taxonomy_get_term_by_name($lead_type, $vocabulary));
I've looked in to the error and I'm pretty sure I know what it means, but I can't understand what is wrong with my code that causes this warning.
reset is waiting for a variable reference. You are passing it a function result...
$taxonomy_term = taxonomy_get_term_by_name($lead_type, $vocabulary);
$taxonomy_term = reset($taxonomy_term );
This mean that only variable should be passed by reference, not an expression.
reset($array_variable); // correct
and
reset(some_function_that_returns_array()); // incorrect
If you take a second and think about it more - you would find that reset() with expression (not a variable) makes no sense, because you've rewind the array pointer to the beginning, but you don't have the ability to access that array anymore.
You should only reset a variable (which is passed by reference), not a return value of a function.
see: http://www.php.net/reset