我遇到了一个"只有变量应该通过引用来传递"错误,因为在我使用的代码上有一行不会将explode()结果放入变量中。根据需要使用严格的PHP标准。
但是因为在While循环中使用了explode()函数,我无法想到一个合适的解决方案。
我的代码看起来像
function user_exists($username) {
rewind($this->fp);
while(!feof($this->fp) && trim($lusername = array_shift(explode(":",$line = rtrim(fgets($this->fp)))))) {
if($lusername == $username)
return 1;
}
return 0;
}
有关如何解决此问题的任何建议?
答案 0 :(得分:1)
我想也许你需要坐下来稍微分开你的代码并看看发生了什么。
首先,条件是!feof($this->fp)
来自manual:
feof - 测试文件指针上的文件结尾
您会注意到的一件事是feof()
只是一个返回true
或false
的测试。它在循环结束时不推进指针位置,所以在使用这个函数时,你的while循环中的其他地方需要有一些能够推进指针的东西,否则你将会有一个无限循环。
第二个条件是:
trim($lusername = array_shift(explode(":",$line = rtrim(fgets($this->fp)))))
从左到右的第一个函数是trim(),它返回string
。从我们方便的花花公子comparison table我们看到,在执行if ((String) $var)
时,当且仅当字符串为空(false
)或数字零作为字符串时,它才会计算为""
( "0"
),否则返回true
。我个人倾向于非常讨厌使用if ((String) $var)
(首先因为除非你很清楚你的比较表,否则对于新手来说有点不清楚,因为99%的人正在这样做,他们实际上是在检查字符串长度,在这种情况下我希望它为字符串true
返回"0"
。因此,假设您不需要它为false
返回"0"
,我们可以将其更改为strlen($var) > 0
,然后在循环内操作变量。这应该会大大简化这里的事情。
现在我们有:
while (!feof($this->fp) && strlen($var) > 0) { /*...*/ }
这将循环直到我们位于文件末尾或$var
是空行。其他所有东西都可以卸载到while
循环的主体中,因此更容易分开。
所以这就是我们现在所拥有的:
$line = rtrim(fgets($this->fp));
$lusername = array_shift(explode(":",$line)));
嗯,哦!那是“令人讨厌的”错误:
严格标准:只有变量应通过 /path/to/file.php 在 x 行上的引用传递。
因此我们可以从这里看到,产生错误的部分不是explode()
,而是array_shift()
。另见:Strict Standards: Only variables should be passed by reference
这意味着,由于array_shift()
修改了数组,因此需要引用它。由于您没有传递实际变量,而是传递函数的结果,因此PHP无法修改它。这类似于function($var) = 3;
这样的事情。当然你不能这样做。相反,您需要将值保存到临时变量。所以现在我们有:
$line = rtrim(fgets($this->fp));
$split = explode(":",$line);
$lusername = array_shift($split);
哇哇!没有更多警告信息。
所以把它放在一起,我们现在有:
while (!feof($this->fp) && strlen($lusername) > 0) {
$line = rtrim(fgets($this->fp));
$split = explode(":",$line);
$lusername = array_shift($split);
if($lusername == $username) {
return 1;
}
}
此外,如前所述,fgets()
会使指针前进,从而允许!feof($this->fp)
语句中的while
部分发生变化。