Tylko zmienne powinny być przekazywane przez odniesienie

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'
);

Jakieś pomysły? Po 2 dniach wciąż utknąłem.

Frank Nwoko
źródło
2
Lepsze wyjaśnienie powodu vijayasankarn.wordpress.com/2017/08/28/…
Anant

Odpowiedzi:

515

Przypisz wynik explodedo zmiennej i przekaż tę zmienną do end:

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

Problem polega na tym, że endwymaga odwołania, ponieważ modyfikuje wewnętrzną reprezentację tablicy (tzn. Powoduje, że wskaźnik bieżącego elementu wskazuje na ostatni element).

Wynik explode('.', $file_name)nie może zostać przekształcony w odniesienie. Jest to ograniczenie w języku PHP, które prawdopodobnie istnieje ze względu na prostotę.

Oswald
źródło
12
Dziękuję bardzo. Rozwiązałem mój problem.
Frank Nwoko,
1
@Oswald, możemy wyłączyć ostrzeżenie za pomocą error_reporting. Czy to jest bezpieczne?
Pacerier,
9
Można bezpiecznie wyłączyć error_reporting. Ślepe ignorowanie błędów nie jest bezpieczne. Wyłączenie error_reportingto duży krok w kierunku ślepego ignorowania błędów. W środowisku produkcyjnym display_errorszamiast tego wyłącz i zapisz błędy w pliku dziennika.
Oswald,
Nie działa. Odpowiedź poniżej - podwójny nawias - działa.
bbe
Dziękuję, zaoszczędź mi dużo czasu!
simon
52

Właściwe użycie zgodne z php 7:

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

echo $fileExtension;
// jpg
Sinan Eldem
źródło
3
Dziwne. To działa, ale jak? Czy tłumi ostrzeżenie, podobnie jak @przedrostek?
Nigel Alderton
6
Dlaczego więc dodanie dodatkowego nawiasu usuwa błąd?
Nigel Alderton
8
Zbadałem to dziwactwo i wydaje się, że to błąd? z parserem php, w którym podwójne nawiasy „(())” powodują, że odniesienie jest konwertowane na zwykłą wartość. Więcej na ten link .
Callistino,
26
Lubię to .. ale nie lubię tego jednocześnie. Dzięki za zrujnowanie mojego dnia :-)
billynoah
4
W php7 ostrzeżenie będzie nadal wydawane. php.net/manual/en/…
kosta
49

Wszyscy inni podali już powód, dla którego wystąpił błąd, ale oto najlepszy sposób na zrobienie tego, co chcesz: $file_extension = pathinfo($file_name, PATHINFO_EXTENSION);

ryeguy
źródło
1
Zgadzam się. Nie ma sensu używać manipulacji ciągami do analizowania ścieżek plików, jeśli masz do tego odpowiednie interfejsy API.
gd1
18

zapisz tablicę z explode () do zmiennej, a następnie wywołaj end () na tej zmiennej:

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

btw: używam tego kodu, aby uzyskać rozszerzenie pliku:

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

gdzie strrchrwyodrębnia ciąg po ostatnim .i substrodcina.

Floern
źródło
9

Spróbuj tego:

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

Powodem jest to, że argument argumentu endjest przekazywany przez odwołanie, ponieważ endmodyfikuje tablicę, przesuwając jej wewnętrzny wskaźnik do końcowego elementu. Jeśli nie przekazujesz zmiennej, nic nie wskazuje na odniesienie.

Więcej informacji znajduje się endw podręczniku PHP.

Will Vousden
źródło
8

PHP narzeka, ponieważ end()oczekuje odniesienia do czegoś, co chce zmienić (może to być tylko zmienna). Jednak przekazujesz wynik explode()bezpośrednio do end()bez zapisywania go najpierw w zmiennej. W momencie, gdy explode()zwraca twoją wartość, istnieje ona tylko w pamięci i żadna zmienna na nią nie wskazuje. Nie można utworzyć odwołania do czegoś (lub do czegoś nieznanego w pamięci), co nie istnieje.

Innymi słowy: PHP nie wie, czy podana mu wartość jest wartością bezpośrednią, czy tylko wskaźnikiem do wartości (wskaźnik jest również zmienną (liczbą całkowitą), która przechowuje przesunięcie pamięci, gdzie rzeczywista wartość rezyduje). Więc PHP oczekuje tutaj wskaźnika (odwołania) zawsze.

Ponieważ jednak w PHP 7 jest to tylko powiadomienie (nawet przestarzałe), możesz spokojnie ignorować powiadomienia i używać operatora ignorowania zamiast całkowicie wyłączać raportowanie błędów dla powiadomień:

$file_extension = @end(explode('.', $file_name));
czarodziej
źródło
3
@OskarCalvo To także moja filozofia. Ale to nie jest błąd - PHP traktuje to jako „zawiadomienie”. Było to alternatywne „rozwiązanie” innych odpowiedzi tutaj, o których nikt nie wspomniał bezpośrednio. Lepszym sposobem byłoby zapisanie wartości explodezmiennej tymczasowej, jak napisali tutaj inni. Ale znowu: to nie jest błąd, więc można użyć tego operatora. PHP jest ogólnie kiepski w obsłudze błędów. Dlatego sugerowałbym użycie set_error_handleri set_exception_handlerdo obsługi błędów oraz jako najczystszego rozwiązania.
Czarodziej
4

Tak jak nie możesz od razu zindeksować tablicy, nie możesz również na niej wywoływać końca. Przypisz najpierw do zmiennej, a następnie wywołaj koniec.

$basenameAndExtension = explode('.', $file_name);
$ext = end($basenameAndExtension);
jon_darkstar
źródło
4

end(...[explode('.', $file_name)])działa od PHP 5.6. Jest to udokumentowane w RFC, choć nie w samych dokumentach PHP.

Tgr
źródło
2

Ponieważ podnosi flagę przez ponad 10 lat, ale działa dobrze i zwraca oczekiwaną wartość, mały operator stfu to najlepsza zła praktyka, jakiej wszyscy szukacie:

$file_extension = @end(explode('.', $file_name));
NVRM
źródło
0

Oficjalna instrukcja PHP: end ()

Parametry

array

Tablica Tablica jest przekazywana przez odwołanie, ponieważ jest modyfikowana przez funkcję. Oznacza to, że musisz przekazać mu rzeczywistą zmienną, a nie funkcję zwracającą tablicę, ponieważ tylko rzeczywiste zmienne mogą być przekazywane przez referencję.

evenvi
źródło
3
Zrób cytat z oficjalnej instrukcji, nie przepisuj go własnymi rękami. Zastanów się też, aby Twoja odpowiedź była lepsza niż istniejąca.
Victor Polevoy,
-1

Najpierw musisz zapisać wartość w takiej zmiennej

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

Następnie możesz użyć funkcji zakończenia, aby uzyskać ostatni indeks z tablicy takiej jak ta

echo end($value);

Mam nadzieję, że ci się uda.

Jailendra Rajawat
źródło
-3

$ file_extension = end (explode ('.', $ file_name)); // BŁĄD W TEJ LINII

zmień ten wiersz jako,

$ file_extension = end ( (explode ('.', $ file_name)) ); //bez błędów

Technika jest prosta, dodaj jeszcze jeden wspornik do eksplozji,

(explode ()) , wtedy tylko on może działać niezależnie ..

Manu RS
źródło