仅变量应通过引用传递


246
// Other variables
$MAX_FILENAME_LENGTH = 260;
$file_name = $_FILES[$upload_name]['name'];
//echo "testing-".$file_name."<br>";
//$file_name = strtolower($file_name);
$file_extension = end(explode('.', $file_name)); //ERROR ON THIS LINE
$uploadErrors = array(
    0=>'There is no error, the file uploaded with success',
    1=>'The uploaded file exceeds the upload max filesize allowed.',
    2=>'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
    3=>'The uploaded file was only partially uploaded',
    4=>'No file was uploaded',
    6=>'Missing a temporary folder'
);

有任何想法吗?2天后仍然卡住。


Answers:


515

将的结果分配explode给变量,然后将该变量传递给end

$tmp = explode('.', $file_name);
$file_extension = end($tmp);

问题是,这end需要引用,因为它修改了数组的内部表示(即,它使当前元素指针指向最后一个元素)。

的结果explode('.', $file_name)无法转换为参考。这是PHP语言的一种限制,出于简化的原因可能存在。


12
非常感谢 解决了我的问题。
Frank Nwoko

1
@Oswald,我们可以使用关闭警告error_reporting。这样做安全吗?
Pacerier,2014年

9
关闭是安全的error_reporting。盲目地忽略错误是不安全的。关闭error_reporting是朝盲目忽略错误迈出的重要一步。在生产环境中,请关闭电源display_errors,然后将错误写入日志文件。
奥斯瓦尔德2014年

不工作 下面的答案-双括号-有效。
2013年

谢谢,为我节省了很多时间!
simon

52

PHP 7兼容正确用法:

$fileName      = 'long.file.name.jpg';
$tmp           = explode('.', $fileName);
$fileExtension = end($tmp);

echo $fileExtension;
// jpg

3
奇怪的。那行得通,但是如何呢?它是否会抑制警告,类似于@前缀呢?
奈杰尔·奥尔德顿

6
那么,为什么要添加额外的括号来消除错误呢?
Nigel Alderton 2014年

8
我研究了这个怪癖,这似乎是一个错误吗?使用php解析器,其中双括号 “(())”导致引用转换为纯值。有关此链接的更多信息。
Callistino'4

26
我喜欢这个..但我不同时喜欢。感谢您破坏我的一天:-)
billynoah

4
在php7中仍然会发出警告。php.net/manual/en/…–
kosta

49

其他人已经给了您您出错的原因,但是这是做您想做的最好的方法: $file_extension = pathinfo($file_name, PATHINFO_EXTENSION);


1
我同意。如果有适当的API,使用字符串操作来解析文件路径毫无意义。
gd1 2014年

18

将数组从explode()保存到一个变量,然后在该变量上调用end():

$tmp = explode('.', $file_name);
$file_extension = end($tmp);

顺便说一句:我使用此代码来获取文件扩展名:

$ext = substr( strrchr($file_name, '.'), 1);

strrchr最后一个字符串之后提取字符串.substr切断.


9

试试这个:

$parts = explode('.', $file_name);
$file_extension = end($parts);

原因是for的参数end是通过引用传递的,因为end它通过将其内部指针前进到最后一个元素来修改数组。如果您没有传入变量,则没有指向该变量的引用。

有关end更多信息,请参见PHP手册。


8

PHP抱怨是因为end()期望引用要更改的内容(只能是变量)。但是,您explode()直接将的结果传递给end()而不先将其保存到变量中。而此时的时刻explode()返回自己的价值,它的存在只是在内存中,没有变量指向它。您无法创建不存在的对某个内容(或内存中未知内容)的引用。

换句话说:PHP不知道,您给他的值是直接值还是仅仅是指向该值的指针(指针也是变量(整数),它存储内存的偏移量,即实际值)居住)。因此,PHP总是期望这里有一个指针(引用)。

但是,由于这仍然只是PHP 7中的一个通知(甚至不建议弃用),因此您可以轻松地忽略通知,并使用ignore-operator而不是完全取消激活通知的错误报告:

$file_extension = @end(explode('.', $file_name));

3
@OskarCalvo这也是我的理念。但这不是错误-PHP将其视为“通知”。这是这里其他答案的替代“解决方案”,没有人直接提及。更好的方法是将的值保存explode到一个临时变量中,就像其他人在这里写的一样。但是再次:这不是错误,因此可以使用此运算符。PHP通常不好处理错误。因此,我建议使用,set_error_handler并将其set_exception_handler用于错误处理和最干净的解决方案。
向导

4

正如您无法立即为数组建立索引一样,您也无法对其调用end。首先将其分配给变量,然后调用结束。

$basenameAndExtension = explode('.', $file_name);
$ext = end($basenameAndExtension);

4

end(...[explode('.', $file_name)])自PHP 5.6起一直有效。RFC中对此进行了记录,尽管PHP文档本身中没有。


2

由于它会升旗超过10年,但是可以正常工作并返回期望值,因此,一个stfu运算符是您一直在寻找的最好的坏习惯:

$file_extension = @end(explode('.', $file_name));

0

PHP官方手册:end()

参量

array

数组。此数组通过引用传递,因为它已由函数修改。这意味着您必须为它传递一个实变量,而不是一个返回数组的函数,因为只能通过引用传递实际变量。


3
请从官方手册中引用报价,请勿自行重写。另外,请考虑使您的答案比现有答案更好。
维克托·波勒沃


-3

$ file_extension = end(explode('。',$ file_name)); //此行错误

将此行更改为

$ file_extension = end((explode('。',$ file_name))); //没有错误

技术很简单,请再放一个括号进行爆炸,

(explode()),那么只有它才能独立执行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.