Only variables should be passed by reference

Php

Php Problem Overview


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

Any ideas? After 2 days still stuck.

Php Solutions


Solution 1 - Php

Assign the result of explode to a variable and pass that variable to end:

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

The problem is, that end requires a reference, because it modifies the internal representation of the array (i.e. it makes the current element pointer point to the last element).

The result of explode('.', $file_name) cannot be turned into a reference. This is a restriction in the PHP language, that probably exists for simplicity reasons.

Solution 2 - Php

Php 7 compatible proper usage:

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

echo $fileExtension;
// jpg

Solution 3 - Php

Everyone else has already given you the reason you're getting an error, but here's the best way to do what you want to do: $file_extension = pathinfo($file_name, PATHINFO_EXTENSION);

Solution 4 - Php

save the array from explode() to a variable, and then call end() on this variable:

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

btw: I use this code to get the file extension:

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

where strrchr extracts the string after the last . and substr cuts off the .

Solution 5 - Php

Try this:

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

The reason is that the argument for end is passed by reference, since end modifies the array by advancing its internal pointer to the final element. If you're not passing a variable in, there's nothing for a reference to point to.

See end in the PHP manual for more info.

Solution 6 - Php

Since it raise a flag for over 10 years, but works just fine and return the expected value, a little stfu operator is the goodiest bad practice you are all looking for:

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

But warning, don't use in loops due to a performance hit. Newest version of php 7.3+ offer the method array_key_last() and array_key_first().

https://www.php.net/manual/en/function.array-key-last.php

                 uuuuuuu
             uu$$$$$$$$$$$uu
          uu$$$$$$$$$$$$$$$$$uu
         u$$$$$$$$$$$$$$$$$$$$$u
        u$$$$$$$$$$$$$$$$$$$$$$$u
       u$$$$$$$$$$$$$$$$$$$$$$$$$u
       u$$$$$$$$$$$$$$$$$$$$$$$$$u
       u$$$$$$"   "$$$"   "$$$$$$u
       "$$$$"      u$u       $$$$"
        $$$u       u$u       u$$$
        $$$u      u$$$u      u$$$
         "$$$$uu$$$   $$$uu$$$$"
          "$$$$$$$"   "$$$$$$$"
            u$$$$$$$u$$$$$$$u
             u$"$"$"$"$"$"$u
  uuu        $$u$ $ $ $ $u$$       uuu
 u$$$$        $$$$$u$u$u$$$       u$$$$
  $$$$$uu      "$$$$$$$$$"     uu$$$$$$
u$$$$$$$$$$$uu    """""    uuuu$$$$$$$$$$
$$$$"""$$$$$$$$$$uuu   uu$$$$$$$$$"""$$$"
 """      ""$$$$$$$$$$$uu ""$"""
           uuuu ""$$$$$$$$$$uuu
  u$$$uuu$$$$$$$$$uu ""$$$$$$$$$$$uuu$$$
  $$$$$$$$$$""""           ""$$$$$$$$$$$"
   "$$$$$"                      ""$$$$""
     $$$"                         $$$$"

Solution 7 - Php

PHP complains because end() expects a reference to something that it wants to change (which can be a variable only). You however pass the result of explode() directly to end() without saving it to a variable first. At the moment when explode() returns your value, it exists only in memory and no variable points to it. You cannot create a reference to something (or to something unknown in the memory), that does not exists.

Or in other words: PHP does not know, if the value you give him is the direct value or just a pointer to the value (a pointer is also a variable (integer), which stores the offset of the memory, where the actual value resides). So PHP expects here a pointer (reference) always.

But since this is still just a notice (not even deprecated) in PHP 7, you can savely ignore notices and use the ignore-operator instead of completely deactivating error reporting for notices:

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

Solution 8 - Php

end(...[explode('.', $file_name)]) has worked since PHP 5.6. This is documented in the RFC although not in PHP docs themselves.

Solution 9 - Php

The answer given elsewhere,

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

is correct and valid. It accomplishes what you are trying to do.

Why?

The end() function does not do quite what you think it does. This is related to how the PHP array data structure works. You don't normally see it, but arrays in PHP contain a pointer to a current element, which is used for iteration (like with foreach).

In order to use end(), you must have an actual array, which has attached to it (normally, invisibly), the current element pointer. The end() function physically modifies that pointer.

The output of explode() is not an actual array. It is a function output. Therefore, you cannot run end(explode()) because you violate language requirements.

Simply setting the output of explode() in a variable creates the array that you're looking for. That created array has a current element pointer. Now, all is once again right in the world.

So what about the parentheses?

This is not a bug. Once again, it's a language requirement.

The extra parentheses (like end((explode()))) do more than just grouping. They create an inline instance variable, just like setting the function output to a variable. You may think of it as a lambda function that is executed immediately.

This is another correct and valid solution. It is perhaps a better solution, as it takes less space. A good reviewer or maintainer should grok what you're trying to do when they see the extra parentheses.

If you use a linter or SCA program like PHPCS, that may dislike the extra parentheses, depending on the linting profile you're using. It's your linter, tell it what you want it to do for you.

Some other answers also list things like the spread operator or array_key_last(), which are also reasonable solutions. They may be perfectly valid but they're more complicated to use and read.

I'll just use the @ prefix

This solution is valid, however incorrect. It is valid because it solves the problem. That's about the end of its merit.

Suppressing errors is always bad practice. There are many reasons why. One very large one is that you are trying to suppress one specific error condition (one that you have created), but the error suppression prefix suppresses all errors.

In this case, you will probably get away with this. However, engaging in bad programming habits is cheating and will likely lead you to cheat more and bigger in the future. You will be responsible for bad code. But I'm not the Code Police and it's your code. It's valid because it solves the problem.

Okay, so what's the best answer?

Do what @ryeguy suggests. Don't do string manipulation to solve a well-defined problem that the platform already solves for you. Use pathinfo().

This has the added benefit that it actually does what you want, which is finding the extension on a file name. There is a subtle difference.

What you are doing is getting the text following the final dot. This is different from finding the file extension. Consider the file name, .gitignore. PHP knows how to handle this. Does your code?

Once again, I'm not the Code Police. Do what suits you best.

Solution 10 - Php

Just as you can't index the array immediately, you can't call end on it either. Assign it to a variable first, then call end.

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

Solution 11 - Php

PHP offical Manual : end()

Parameters

array

The array. This array is passed by reference because it is modified by the function. This means you must pass it a real variable and not a function returning an array because only actual variables may be passed by reference.

Solution 12 - Php

First, you will have to store the value in a variable like this

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

Then you can use the end function to get the last index from an array like this

echo end($value);

I hope it will work for you.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFrank NwokoView Question on Stackoverflow
Solution 1 - PhpOswaldView Answer on Stackoverflow
Solution 2 - PhpSinan EldemView Answer on Stackoverflow
Solution 3 - PhpryeguyView Answer on Stackoverflow
Solution 4 - PhpFloernView Answer on Stackoverflow
Solution 5 - PhpWill VousdenView Answer on Stackoverflow
Solution 6 - PhpNVRMView Answer on Stackoverflow
Solution 7 - PhpwizardView Answer on Stackoverflow
Solution 8 - PhpTgrView Answer on Stackoverflow
Solution 9 - PhpStephan SamuelView Answer on Stackoverflow
Solution 10 - Phpjon_darkstarView Answer on Stackoverflow
Solution 11 - PhpevenviView Answer on Stackoverflow
Solution 12 - PhpJailendra RajawatView Answer on Stackoverflow