// 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天,还是卡住了。


当前回答

答案在别处给出了,

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

是正确有效的。它能完成你想要做的事情。

Why?

end()函数做的事情与您想象的不太一样。这与PHP数组数据结构的工作方式有关。您通常不会看到它,但PHP中的数组包含一个指向当前元素的指针,用于迭代(如foreach)。

为了使用end(),必须有一个实际的数组,该数组附加了当前元素指针(通常是不可见的)。end()函数对该指针进行物理修改。

爆炸()的输出不是一个实际的数组。它是一个函数输出。因此,您不能运行end(explosion()),因为您违反了语言要求。

只需在变量中设置爆炸()的输出,就可以创建您正在寻找的数组。创建的数组有一个当前元素指针。现在,世界又恢复了正常。

那么括号呢?

这不是一个bug。再说一次,这是语言要求。

额外的括号(如end((explosion())))))不仅仅是分组。它们创建一个内联实例变量,就像将函数输出设置为变量一样。您可以认为它是一个立即执行的lambda函数。

这是另一个正确有效的解。这也许是一个更好的解决方案,因为它占用更少的空间。优秀的审查人员或维护者在看到额外的括号时应该明白您要做什么。

如果您使用linter或像PHPCS这样的SCA程序,可能不喜欢额外的括号,这取决于您正在使用的linting配置文件。这是你的绒毛,告诉它你想让它为你做什么。

其他一些答案还列出了诸如展开运算符或array_key_last()之类的东西,这也是合理的解决方案。它们可能完全有效,但使用和阅读起来更复杂。

我将使用@前缀

这个解决方案是有效的,但不正确。它是有效的,因为它解决了问题。这差不多就是它的优点了。

抑制错误总是不好的做法。原因有很多。一个非常大的错误是,您试图抑制一个特定的错误条件(您已经创建的错误条件),但是错误抑制前缀抑制了所有错误。

在这种情况下,您可能会侥幸逃脱。然而,养成坏的编程习惯就是作弊,而且很可能导致你在未来作弊次数更多、更大。你将为糟糕的代码负责。但我不是密码警察,这是你的密码。它是有效的,因为它解决了问题。

好的,那么最好的答案是什么?

按照@ryeguy的建议去做。不要使用字符串操作来解决平台已经为您解决的定义良好的问题。使用pathinfo()。

这有一个额外的好处,它实际上是您想要的,即查找文件名的扩展名。有一个微妙的区别。

你所做的就是获取最后一个点后面的文本。这与查找文件扩展名不同。考虑一下文件名。gitignore。PHP知道如何处理这个问题。你的代码呢?

再说一遍,我不是密码警察。做最适合你的事。

其他回答

PHP抱怨是因为end()期望对它想要更改的内容(只能是变量)的引用。但是,您可以直接将爆炸()的结果传递给end(),而不需要先将其保存到变量中。当explosion()返回您的值时,它只存在于内存中,没有变量指向它。不能创建对不存在的东西(或内存中未知的东西)的引用。

或者换句话说:PHP不知道你给他的值是直接的值还是指向值的指针(指针也是一个变量(整数),它存储了内存的偏移量,也就是实际值所在的位置)。PHP希望这里总是有一个指针(引用)。

但是因为这在PHP 7中仍然只是一个通知(甚至没有被弃用),你可以保存忽略通知并使用忽略操作符,而不是完全取消激活通知的错误报告:

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

其他所有人都已经给出了出错的原因,但这里是完成您想要做的事情的最佳方式: $file_extension = pathinfo($file_name, PATHINFO_EXTENSION);

就像你不能立即索引数组一样,你也不能对它调用end。首先将它赋值给一个变量,然后调用end。

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

试试这个:

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

原因是end的参数是通过引用传递的,因为end通过将其内部指针前进到final元素来修改数组。如果没有传入变量,则没有引用可以指向的对象。

更多信息请参见PHP手册的末尾。

Php 7兼容的正确用法:

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

echo $fileExtension;
// jpg