Только переменные должны быть переданы по ссылке

247
// 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 дня все еще застрял.

Фрэнк Нвоко
источник
2
Лучшее объяснение причины vijayasankarn.wordpress.com/2017/08/28/…
Анант,

Ответы:

516

Присвойте результат explodeпеременной и передайте эту переменную end:

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

Проблема в том, что endтребуется ссылка, потому что она изменяет внутреннее представление массива (т. Е. Делает текущий указатель элемента на последний элемент).

Результат explode('.', $file_name)не может быть превращен в ссылку. Это ограничение в языке PHP, которое, вероятно, существует по причинам простоты.

Освальд
источник
12
Большое спасибо. Решил мою проблему.
Фрэнк Нвоко
1
@ Освальд, мы можем отключить предупреждение с помощью error_reporting. Насколько это безопасно?
Pacerier
9
Это безопасно выключить error_reporting. Небезопасно слепо игнорировать ошибки. Отключение error_reporting- это важный шаг к слепому игнорированию ошибок. В производственной среде display_errorsвместо этого отключите и запишите ошибки в файл журнала.
Освальд
Не работает. Ответ ниже - двойные скобки - работает.
bbe
Спасибо, сэкономьте мне много времени!
симон
52

Php 7-совместимое правильное использование:

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

echo $fileExtension;
// jpg
Синан Элдем
источник
3
Weird. Это работает, но как? Подавляет ли оно предупреждение, аналогично тому, что @делает префикс?
Найджел Олдертон
6
Так почему же добавление дополнительных скобок удаляет ошибку?
Найджел Олдертон
8
Я исследовал эту причуду, и это, кажется, ошибка? с парсером php, где двойные скобки "(())" приводят к преобразованию ссылки в простое значение. Подробнее по этой ссылке .
Callistino
26
Мне нравится это .. но мне не нравится это в то же время. Спасибо за то, что испортили мой день :-)
billynoah
4
В php7 все равно будет выдано предупреждение. php.net/manual/en/…
Коста
49

Все остальные уже сообщили вам причину, по которой вы получаете ошибку, но вот лучший способ сделать то, что вы хотите сделать: $file_extension = pathinfo($file_name, PATHINFO_EXTENSION);

ryeguy
источник
1
Я согласен. Нет смысла использовать строковые манипуляции для анализа путей к файлам, когда у вас есть соответствующие API для этого.
gd1
18

сохранить массив из explode () в переменную, а затем вызвать end () для этой переменной:

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

кстати: я использую этот код, чтобы получить расширение файла:

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

где strrchrизвлекает строку после последней .и substrобрезает.

Floern
источник
9

Попробуй это:

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

Причина в том, что аргумент для endпередается по ссылке, так как endмодифицирует массив путем перемещения его внутреннего указателя на последний элемент. Если вы не передаете переменную, нет ничего для ссылки, на которую можно указать.

Смотрите endв руководстве PHP для получения дополнительной информации.

Уилл Вусден
источник
8

PHP жалуется, потому что end()ожидает ссылку на что-то, что он хочет изменить (который может быть только переменной). Однако вы передаете результат explode()напрямую, end()не сохраняя его сначала в переменной. В тот момент, когдаexplode() возвращается ваше значение, оно существует только в памяти и ни одна переменная не указывает на него. Вы не можете создать ссылку на что-то (или что-то неизвестное в памяти), которое не существует.

Или другими словами: PHP не знает, является ли значение, которое вы ему даете, является прямым значением или просто указателем на значение (указатель также является переменной (целым числом), в которой хранится смещение памяти, где находится фактическое значение проживает). Так что PHP ожидает здесь указатель (ссылку) всегда.

Но поскольку в PHP 7 это все еще просто уведомление (даже не рекомендуется), вы можете спокойно игнорировать уведомления и использовать оператор игнорирования вместо полной деактивации отчетов об ошибках для уведомлений:

$file_extension = @end(explode('.', $file_name));
волшебник
источник
3
@OskarCalvo Это тоже моя философия. Но это не ошибка - PHP воспринимает это как «уведомление». И это было альтернативное «решение» других ответов здесь, о которых никто прямо не упомянул. Лучшим способом было бы сохранить значение explodeво временной переменной, как написали здесь другие. Но опять же: это не ошибка, поэтому можно использовать этот оператор. PHP обычно плохо обрабатывает ошибки. Поэтому я бы предложил использовать set_error_handlerи set_exception_handlerдля обработки ошибок и как самое чистое решение.
Волшебник
4

Так же, как вы не можете сразу индексировать массив, вы также не можете вызвать end для него. Сначала назначьте его переменной, затем вызовите end.

$basenameAndExtension = explode('.', $file_name);
$ext = end($basenameAndExtension);
jon_darkstar
источник
4

end(...[explode('.', $file_name)])работает с PHP 5.6. Это задокументировано в RFC, но не в самих документах PHP.

Tgr
источник
2

Поскольку он поднимает флаг более 10 лет, но работает просто отлично и возвращает ожидаемое значение, маленький оператор stfu - это самая плохая практика, которую вы все ищете:

$file_extension = @end(explode('.', $file_name));
NVRM
источник
0

Официальное руководство по PHP: end ()

параметры

array

Массив. Этот массив передается по ссылке, потому что он модифицируется функцией. Это означает, что вы должны передавать ей реальную переменную, а не функцию, возвращающую массив, потому что только реальные переменные могут быть переданы по ссылке.

evenvi
источник
3
Сделайте цитату из официального руководства, не переписывайте своими руками. Кроме того, постарайтесь сделать свой ответ лучше, чем существующий.
Виктор Полевой
-1

Во-первых, вам нужно будет сохранить значение в такой переменной, как эта

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

Затем вы можете использовать функцию конца, чтобы получить последний индекс из массива, как это

echo end($value);

Я надеюсь, что это будет работать для вас.

Джайлендра Раджават
источник
-3

$ file_extension = end (explode ('.', $ file_name)); // ОШИБКА НА ЭТОЙ ЛИНИИ

изменить эту строку как,

$ file_extension = end ( (взорваться ('.', $ file_name)) ); // нет ошибок

Техника проста, пожалуйста, поставьте еще одну скобку для взрыва,

(Взрываются ()) , тогда только он может выполнять самостоятельно ..

Ману РС
источник