Laravel request()输入文件和隐藏的同名输入

I have simplified my form for this question.

This is my example

<form method="post" name="test" enctype="multipart/form-data">
   {{csrf_field()}}
   <input class="form-control" type="file" name="test[]" id="companion"/>
   <input type="hidden" name="test[]" value="random-value" />
   <input type="submit" value="Submit">
</form>

In my route a just dd the request as follow:

dd(request('test'));

Now I would expect an array with a file (UploadedFile type) and the random-value, instead, I'm getting only the file.

array:1 [▼
   0 => UploadedFile {#539 ▶}
]

Any idea why I'm getting this result? I know that I can change the name of the variables, but I wanna understand why it doesn't work like that.

Thanks in advance.

Ok, I might have found a solution.

Since I'm editing, I know if the file/hidden input is new (as in the edit I can add other items) or got from the DB.

<form method="post" name="test" enctype="multipart/form-data">
   {{csrf_field()}}
   <input class="form-control" type="file" name="test[]" id="companion"/>
   <input type="hidden" name="test[id-{{id}}]" value="random-value" />
   <input type="submit" value="Submit">
</form>

With this "fix" I will manage to get my goal.

dd(request('test'));
------------------------
array:2 [▼
  "id-1" => "random-value"
  0 => UploadedFile {#539 ▶}
]

I do not care about the keys so I'm happy with this solution.

NB this is just a simplification of my problem but it helped me to understand it.

I hope it'll help other people =)

Feel free to ask me if you have any question ;)

Cheers.

It's because:

  1. You call request('test'). This made a call to the helper in Illuminate\Foundation\helpers.php

    function request($key = null, $default = null)
    {
        ...
        $value = app('request')->__get($key);
        ...
    }
    
  2. This directs the call to the __get method to quickly get a value in Illuminate\Http\Request.php

    public function __get($key)
    {
        if (array_key_exists($key, $this->all())) {
            return data_get($this->all(), $key);
        }
        ...
    }
    
  3. The problem lies in the all() method defined in the trait Illuminate\Http\Concerns\InteractsWithInput

    public function all($keys = null)
    {
        $input = array_replace_recursive($this->input(), $this->allFiles());
        if (! $keys) {
            return $input;
        }
        ...
    }
    

So you see what's going on here? You actually still have the test[] hidden value, but the all() method simply merged it with files with the same name. I assume it's for the sake of simplicity on why they would do this, and I don't think it's that common to have two inputs with the same name, with different input type.

I guess, the simplest solution here now is, to access it via the request instance. Try this (untested, theoretically should work):

\Log::info(app('request')->file('test'));
\Log::info(app('request')->get('test'));

And find the output in laravel.log file. You should be able to do a simple array merge with them.