thomvincent's avatar

Best way to handle single and multiple uploads for a model

Hello all. This is my first project using Laravel and I'm really enjoying the experience. Especially how it makes you consider different approaches to solving problems. To that end I've reached a point where I'm unsure what the best option is. I've done some reading on the matter and watched a few Laracasts, but can't decided with option to take and would appreciate any feedback / opinions.

I have two models; Brief which represents a project brief and Designer which represents a designer.

The Brief model requires the end-user to save some text data, upload some images in bulk, and a single image of a building floor plan.

The Designer model requires the end-user to save some text data, upload some images in bulk, and a single image of an avatar.

For both models I have completed the saving of text data and the uploading of images in bulk thanks to Dropzone.js (which is amazing).

Each image uploaded creates an entry in a database table. Saving usual things like filename, date uploaded, and file size. Also saving the ID of the Brief/Designer the images were uploaded to as well as the model's class i.e. App\Brief. As you no doubt guessed, it's polymorphic so in Laravel I can just type: $brief->attachment; to receive a collection of all the image for that brief. Same is true for designer or any future model I add images to in the future.

This is great for the images uploaded in bulk. But where I'm stuck is the instance of the single image i.e. floor plan or avatar. What do you think would be the best way to associate a single image to the floor plan or avatar field?

  1. Save the path to the uploaded image in the Brief / Designer table and abandon the image table for all one-off images.

  2. Save the ID of the uploaded image from the image table into the Brief / Designer table. Then write a method on the Brief / Designer model i.e. getFloorPlan().

  3. Save an additional flag to the image table i.e. "floorplan". Then write a method on the Brief / Designer model i.e. getFloorPlan().

Or is there another way I'm overlooking?

0 likes
8 replies
jekinney's avatar
Level 47

Look into a polymorphic relationships. For the avatar, if you only allow one at a time, I put in the related model by saving the path.

The bulk files may fit the polymorphic relationship nicely and the docs example is actually photos too.

I generally use a service class for image uploading and just pass related data to be saved after files have been moved, resized if needed etc.

thomvincent's avatar

Thank you for your reply @jekinney.

I did try saving 1 = 1 relationships for single images, but ended up changing all images to a polymorphic relationship for all images and created custom methods for retrieving the image. I like everything working the same way.

Just trying to work how to perform a check to see if each model has the minimum amount of images associated with it before it is saved.

uxweb's avatar

@thomvincent

Hi, im curious about on how did you solved saving the brief data and the bulk of attachments at the same time using dropzone.js.

I am using dropzone but I know that when you drop a file on it will try to upload the file immediately, at that time there is no brief created at the database, so there is no way to relate the attachment with the brief.

Thanks!

thomvincent's avatar

Hello @uxweb.

The create method on the BriefsController creates a new brief, saves it, and then redirects to the edit page with the brief id. I think there's a name for what I'm doing, but I can't remember it.

Thom

uxweb's avatar

@thomvincent

Thanks for the info!, so, first a brief with the basic information is created? and then redirected to the edit page of that brief where you can add the attachments?

thomvincent's avatar

You can do that. But I just create an "empty" brief (id, project_id*, created_on, updated_on) and then redirect to the edit page.

  • There is a 1 = 1 relationship between project and brief.
madsynn's avatar

@thomvincent can you please show your create function: " You can do that. But I just create an "empty" brief (id, project_id*, created_on, updated_on) and then redirect to the edit page.". I am also using the dropzone.js and would love to see how you accomplished this. Did you create it in the controller or in a route? if you could share it would be greatly appreciated.

thomvincent's avatar

Apologises for not replying sooner @madsyn. I didn't receive any notification for this.

To answer your question, I just stuck it in the Controller. Though since then I've started using the Repository pattern along with Gateways so I don't clutter up my Controllers.

However, here is the code for creating a new Brief for a Project. And then automatically redirecting to the Brief's edit view:

    public function create(Project $project)
    {
        $user = Auth::user();
        $customer_id = $user->userable->id;
        $brief = $project->brief()->create(['customer_id'=>$customer_id]);
        return Redirect::route('projects.{projects}.briefs.edit', array('projects' => $project->id, 'briefs' => $brief->id));
    }

Please or to participate in this conversation.