Php 错误消息";严格标准:只能通过引用传递变量”;

Php 错误消息";严格标准:只能通过引用传递变量”;,php,reference,strict,Php,Reference,Strict,上述代码以某种方式报告了严格标准警告,但这不会: $el = array_shift($instance->find(..)) 那么它什么时候会报告警告呢?$instance->find()返回对变量的引用 当您试图将此引用用作函数的参数时,您会得到报告,而不必先将其存储在变量中 这有助于防止内存泄漏,并可能在下一个PHP版本中成为错误 如果您的第二个代码块写得像(请注意函数签名中的&),它将抛出一个错误: 因此,一个快速(但不是很好)的解决方案是: function &get_

上述代码以某种方式报告了严格标准警告,但这不会:

$el = array_shift($instance->find(..))
那么它什么时候会报告警告呢?

$instance->find()返回对变量的引用

当您试图将此引用用作函数的参数时,您会得到报告,而不必先将其存储在变量中

这有助于防止内存泄漏,并可能在下一个PHP版本中成为错误

如果您的第二个代码块写得像(请注意函数签名中的
&
),它将抛出一个错误:

因此,一个快速(但不是很好)的解决方案是:

function &get_arr(){
    return array(1, 2);
}
$el = array_shift(get_arr());

基本上,您首先对临时变量赋值,然后将该变量作为参数发送。

考虑以下代码:

$el = array_shift($tmp = $instance->find(..));
这将生成以下输出:

error_reporting(E_STRICT);
class test {
    function test_arr(&$a) {
        var_dump($a);
    }
    function get_arr() {
        return array(1, 2);
    }
}

$t = new test;
$t->test_arr($t->get_arr());
原因是什么?
test::get_arr()
方法不是变量,在严格模式下,这将生成警告。这种行为非常不直观,因为
get\u arr()
方法返回数组值

要在严格模式下绕过此错误,请更改方法的签名,使其不使用引用:

Strict Standards: Only variables should be passed by reference in `test.php` on line 14
array(2) {
  [0]=>
  int(1)
  [1]=>
  int(2)
}
由于无法更改
数组\u shift
的签名,因此还可以使用中间变量:

function test_arr($a) {
    var_dump($a);
}

第二个片段也不起作用,这就是为什么


array\u shift
是一个修改函数,用于更改其参数。因此,它希望其参数是一个引用,而您不能引用非变量的内容。请参见此处的Rasmus解释:

错误的原因是使用了内部PHP编程数据结构函数array_shift()[PHP.net/end]

该函数将数组作为参数。尽管手册中的
array\u shift()
原型中指示了一个与符号,但在该函数的扩展定义中没有任何警告文档,也没有任何明显的解释说明该参数实际上是通过引用传递的

也许这是/理解的/。但是,我不理解,因此很难检测错误的原因

复制代码:

$inter = get_arr();
$el = array_shift($inter);
此代码:

function get_arr()
{
    return array(1, 2);
}
$array = get_arr();
$el = array_shift($array);
需要更改为:

$monthly_index = array_shift(unpack('H*', date('m/Y')));

在这种明显的情况下,您可以告诉PHP在函数前面使用“@”来抑制消息

$date_time = date('m/Y');
$unpack = unpack('H*', $date_time);
array_shift($unpack);
以这种方式抑制所有错误可能不是最佳编程实践之一,但在某些情况下(如本例),它很方便,是可以接受的


因此,我相信您的朋友“系统管理员”会对污染较少的
错误感到满意。log

$instance->find(…)返回什么?解决方案如下:我认为示例(或逻辑)可能是问题的错误方向,因为第二个示例(
get_arr()
函数)确实产生了严格的标准声明(经过测试的PHP5.2和PHP5.5)。它现在应该可以工作了(已检查)。为了返回引用,您必须在方法签名处声明它,而不是在返回语句处声明它(我的错).不,我不能更改签名。@pygorex1的中间变量可以解决这个问题,但它看起来是多余的,不是吗?我知道你不能更改签名,只是解释了它是如何发生的。你必须使用临时(=中间变量)变量,但您可以在同一行中执行。请看我的第二个代码段。我尝试了您的第二个代码段,但不起作用。它实际上只在单独的行中起作用。赋值返回赋值。
array\u shift($tmp=$instance->find(…)
赋值
$instance->find(…)
$tmp
,然后将赋值值传递到
数组_shift()
——这与传递
$tmp
本身不同,因此并不比没有赋值的原始情况好。@user198729:我也在寻找解释或修复方法,发现您可以使用current()对于第一项,由于end()将内部指针前进到最后一个元素,因此它对最后一项不起作用。current(array_reverse(somefunction())可以工作(是的,它很愚蠢)使用
current
可以假设数组指针位于第一个元素。在大多数情况下,这可能是一个有效的假设,但需要注意。@leepowers当然,那么就会出现与
array\u shift()相同的问题
因为它需要修改引用:-)@user198729您可以使用额外的一对括号来避免
$intermediate
值。
$el=array\u shift((get\u arr())
。请看@Chloe这是我见过的最出色的解决方案,它可以保持代码的简单性!!谢谢!我不知道是谁否决了这个答案,但给出的解决方案确实有效,而且是PHP标准技术。真的很令人失望…下次我可能再也回答不了问题了…:(我认为这是因为抑制错误消息并不能解决代码的问题。在未来的PHP版本中,当这种类型的错误从E_STRICT变为E_error,并且您的代码现在没有运行,也不会产生任何错误/输出时,您会怎么做?@TinoDidriksen,我理解并同意建议您不要这样做的原因一些“坏习惯”,特别是对新一代而言。然而,当(并且如果)使用安全且适用于提议的上下文时,就可以使用资源。如果错误抑制器“@”被废除,它将从语言本身中删除。与“eval”相同(它可能是邪恶的,但有其目的)。我反对的不是使用某些资源,而是对建议的概括。具体地说,对于提议的情况,使用它不会有任何伤害,即使是为了调试目的。
$date_time = date('m/Y');
$unpack = unpack('H*', $date_time);
array_shift($unpack);
$monthly_index = @array_shift(unpack('H*', date('m/Y')));