joedawson's avatar

Issue passing files (photos) to command bus

Evening everyone,

I'm currently diving into Commands and I've hit a bit of a brick wall. I can't seem to pass my files (photos) to my command.

So, I have an AdminPhotosController that currently deals with the PhotoRequest, creating a thumbnail, uploading to S3 and persisting some details to the database. Of course, this isn't ideal.

I followed Taylors screencast which showed an example of passing a Request to the command itself, so here's my store method on my AdminPhotosController;

public function store(PhotoRequest $request)
{
    $this->dispatchFrom(AddPhotoCommand::class, $request);

    return redirect()->route('admin.photos.index');
}

Note: The PhotoRequest doesn't have any validation rules for now so that's not the issue.

Now, here's my AddPhotoCommand;

class AddPhotoCommand extends Command implements SelfHandling, ShouldBeQueued {

    use InteractsWithQueue, SerializesModels;

    protected $female_id, $photos;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct($female_id, $photos)
    {
        $this->female_id = $female_id;
        $this->photos = $photos;
    }

    /**
     * Execute the command.
     *
     * @return void
     */
    public function handle()
    {

        foreach($this->photos as $photo) {

            /* ------------------------------------
            #. Generate Thumb
            ------------------------------------ */
            $thumbnail = Image::make($photo->getRealPath());
            $thumbnail->fit(300)->save(public_path('temp/').$photo->getClientOriginalName());

            /* ------------------------------------
            #. Random String for File
            ------------------------------------ */
            $str = str_random(10).'-';

            /* ------------------------------------
            #. Target Paths
            ------------------------------------ */
            $path       = s3_female_path($this->female_id).$str.$photo->getClientOriginalName().'';
            $thumb_path = s3_female_thumb_path($request->input('female_id', true)).$str.$photo->getClientOriginalName().'';

            /* ------------------------------------
            #. Put to S3
            ------------------------------------ */
            $disk = Storage::disk('s3'); // Mount Disk

            $disk->put($path, file_get_contents($photo)); // Full Image
            $disk->put($thumb_path, $thumbnail); // Thumbnail

            /* ------------------------------------
            #. Persist
            ------------------------------------ */
            $photo = Photo::create([
                'female_id' => $this->female_id,
                'path'      => s3_file_path($path),
                'thumb_path'=> s3_file_path($thumb_path),
                'size'      => $photo->getSize()
            ]);

        }
    }
}

When submitting my form, I receive the following error;

ErrorException in AddPhotoCommand.php line 37:
Invalid argument supplied for foreach()

So what I then did, was die and dump $this->photos which for some odd reason is returning null.

I then proceeded to attempt a die and dump on $this->female_id - which returned the id successfully, so my Request is making it's way through - but I can't seem to access my the photos?

Any help would be appreciated!

Edit: Here's a closer look at the problem - https://www.youtube.com/watch?v=KV9fV0ExZnI

0 likes
12 replies
usman's avatar

@JoeDawson I haven't tinkered with self handling command yet. But I think your handler when resolved out of the queue will receive a Command object try:

public function handle($command)
    {   
    $photos = $command->photoes;
    ....
    .....
    }

Usman.

joedawson's avatar

@usman no luck there...

public function handle($command)
{
    dd($command);
    ...
}
ErrorException in AddPhotoCommand.php line 34:
Missing argument 1 for InkedFemales\Commands\AddPhotoCommand::handle()

What's odd - is that I can access female_id from the request - this returns the id successfully;

protected $female_id, $photos;

public function __construct($female_id, $photos)
{
    $this->female_id = $female_id;
    $this->photos = $photos;
}

public function handle()
{
    dd($this->female_id);
    ...
}

But I can't do this to access my files/photos;

protected $female_id, $photos;

public function __construct($female_id, $photos)
{
    $this->female_id = $female_id;
    $this->photos = $photos;
}

public function handle()
{
    dd($this->photos);
    ...
}

It returns null :/

usman's avatar

@JoeDawson I hope the name of request attributes match those that are supplied inside the constructor i.e $request->has('female_id') //true and same for the $photos. This could be an issue, if they don't match.

joedawson's avatar

@usman I believe everything is marrying up?

<div class="form-group">
    {!! Form::label('female_id', 'Female:') !!}
    {!! Form::select('female_id', $females, null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
    {!! Form::label('photos[]', 'Photo(s):') !!}
    {!! Form::file('photos[]', ['multiple']) !!}
</div>
<div class="form-group">
    {!! Form::submit($submitButtonText, ['class' => 'btn btn-primary']) !!}
</div>

Here's a video with a closer look at everything I have - https://www.youtube.com/watch?v=KV9fV0ExZnI

usman's avatar

@JoeDawson Ok, have you tried without using the dispatchFrom method and explicitly passing the arguments?

joedawson's avatar

Sorry - was playing Forza lol.

public function store(PhotoRequest $request)
{
    $this->dispatch(new AddPhotoCommand($request->females, $request->file('photos')));

    return redirect()->route('admin.photos.index');
}

Returns;

Exception in Queue.php line 91:
Serialization of 'Symfony\Component\HttpFoundation\File\UploadedFile' is not allowed

:( - any ideas?

usman's avatar
usman
Best Answer
Level 27

update:// @JoeDawson I would say, save the file in store method and read file contents back from the handle.

Usman.

joedawson's avatar

Thanks @usman, really appreciate your help!

Unfortunately, I can't use getRealPath etc. now - it's getting late here so I'll take another look tomorrow at some point.

Thanks again!

Please or to participate in this conversation.