只应通过引用传递变量

时间:2011-01-08 21:10:39

标签: php

// 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天后仍然卡住了。

13 个答案:

答案 0 :(得分:419)

explode的结果分配给变量并将该变量传递给end

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

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

explode('.', $file_name)的结果无法转换为引用。这是PHP语言中的限制,可能出于简单原因而存在。

答案 1 :(得分:50)

Php 7兼容正确用法:

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

echo $fileExtension;
// jpg

答案 2 :(得分:41)

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

答案 3 :(得分:15)

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

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

btw:我使用此代码获取文件扩展名:

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

其中strrchr在最后.substr切断.之后提取字符串

答案 4 :(得分:9)

试试这个:

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

原因是end的参数是通过引用传递的,因为end通过将其内部指针提升到最终元素来修改数组。如果您没有传入变量,则没有任何参考指向。

有关详细信息,请参阅PHP手册中的end

答案 5 :(得分:5)

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

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

但是,由于这只是PHP 7中的通知(甚至不推荐),您可以保存忽略通知并使用ignore-operator而不是完全停用通知的错误报告:

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

答案 6 :(得分:4)

就像你不能立即索引数组一样,你也不能在它上面调用end。首先将其分配给变量,然后调用end。

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

答案 7 :(得分:0)

PHP官方手册: 端()

参数

array

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

答案 8 :(得分:0)

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

答案 9 :(得分:0)

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

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

答案 10 :(得分:0)

别处给出的答案,

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

正确且有效。它可以完成您想要做的事情。

为什么?

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

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

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

只需在变量中设置 explode() 的输出创建您正在寻找的数组。创建的数组有一个当前元素指针。现在,世界上的一切又是正确的。

那么括号呢?

这不是错误。再说一次,这是语言要求。

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

这是另一个正确且有效的解决方案。这可能是一个更好的解决方案,因为它占用的空间更少。一个好的审阅者或维护者应该会在看到额外的括号时理解您正在尝试做什么。

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

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

我将只使用 @ 前缀

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

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

在这种情况下,您可能会侥幸逃脱。但是,养成不良的编程习惯就是作弊,将来可能会导致您作弊越来越多。您将对不良代码负责。但我不是代码警察,这是你的代码。它是有效的,因为它解决了问题。

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

做什么@ryeguy suggests。不要为了解决平台已经为您解决的明确定义的问题而进行字符串操作。使用 pathinfo()

这有一个额外的好处,它实际上可以执行您想要的操作,即在文件名上查找扩展名。有细微的差别。

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

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

答案 11 :(得分:-1)

首先,您必须将值存储在这样的变量中

$value = explode("/", $string);

然后您可以使用end函数从这样的数组中获取最后一个索引

echo end($value);

我希望它对您有用。

答案 12 :(得分:-3)

  

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

     

将此行更改为,

     

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

     

技术很简单,请再放一个括号以便爆炸,

     

(explode()),然后才能独立执行..