laravel / nova-issues

556 stars 34 forks source link

storeAs in a Repeater field #6513

Open Brand3000 opened 2 months ago

Brand3000 commented 2 months ago

Hi! Tho storeAs feature doesn't work in Repeaters. Is it difficult to fix it? Very inconvenient.

jeremynikolic commented 2 months ago

Hi @Brand3000, thanks for reporting this. To help investigating, please post an example to illustrate the case and ease the reproduction 🙏

Brand3000 commented 2 months ago

It's very easy to reproduce. Just try using the storeAs function on any image field in a repeatable class.

jeremynikolic commented 2 months ago

I am unfortunately not able to reproduce the issue. Setting up a Repeater with an item containing a file or image field, and using storeAs callback, behave as expected.

Please provide further information of the context leading to the issue you encounter so we may assist.

Brand3000 commented 2 months ago

There's my field declaration:

Image::make('Image 1 (330 x 220)', 'image1')->storeAs(function (Request $request) {
                return pathinfo($request->image1->getClientOriginalName(), PATHINFO_FILENAME).'_'.uniqid().'.'.pathinfo($request->image1->getClientOriginalName(), PATHINFO_EXTENSION);
            })->disk('public_tour')->prunable()->hideFromIndex(),

and there's the error: App\Nova\Repeater\ScheduleItem::App\Nova\Repeater\{closure}(): Argument #1 ($request) must be of type App\Nova\Repeater\Request, Laravel\Nova\Http\Requests\UpdateResourceRequest given. It works fine if I remove the storeAs method from the chain.

The same field with the same settings works perfect in the parent resource.

jeremynikolic commented 2 months ago

Thanks for the details 👍

It's missing the right import as per the exception indicates. You'd need importing \Illuminate\Http\Request or \Laravel\Nova\Http\Requests\NovaRequest if you need something more specific (and adjust Request to NovaRequest accordingly) 🤔

Brand3000 commented 2 months ago

Unfortunately, the NovaRequest class doesn't have the getClientOriginalName method as it's written in the docs. My code is:

use Laravel\Nova\Http\Requests\NovaRequest;

            Image::make('Image 1 (330 x 220)', 'image1')->storeAs(function (NovaRequest $request) {
                return pathinfo($request->image1->getClientOriginalName(), PATHINFO_FILENAME).'_'.uniqid().'.'.pathinfo($request->image1->getClientOriginalName(), PATHINFO_EXTENSION);
            })->disk('public_tour')->prunable()->hideFromIndex(),
jeremynikolic commented 2 months ago

As you are in a repeater, your file is nested within the resource payload.

$request->file("{resource_key}.{repeater_iteration}.fields.image1")

With that said, I realized while looking into this that you'll be missing a way to know which file is the one (which repeater_iteration pretty much) for which the storeAs was called for, due to it being in a repeater. In other methods we inject a requestAttribute parameter which will tell you which one it is. I'll take note of that specific case and see for us to address 👍