Home > Software design >  Adding captions or descriptions to multiple image upload in Laravel
Adding captions or descriptions to multiple image upload in Laravel

Time:06-13

So I am trying to upload images for a project where each image can have its own description or caption. I am trying to do this through the project creation form. Now, everything works except that I am getting duplicate entries in the project_images table because of the nested foreach loop, take a look at the summarised structure of the code Please, specifically the logic in the storProject method if anyone can help I will be forever grateful. Thank you.

I am using Laravel with Livewire.

Models

Project Model

public function up()
{
    Schema::create('projects', function (Blueprint $table) {
        $table->id();
        $table->unsignedBigInteger('user_id');
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('title');
        $table->integer('budget');
        $table->string('proposed_by');
        $table->string('executed_by');
        $table->string('status')->nullable();
        $table->integer('progress_indicator')->nullable();
        $table->date('starting_date');
        $table->date('completion_date')->nullable();
        $table->string('cover_image')->nullable();
        $table->mediumText('body')->nullable();
        $table->timestamps();
    });
}

Project_images Model

 public function up()
{
    Schema::create('project_images', function (Blueprint $table) {
        $table->id();
        $table->string('images');
        $table->string('caption')->nullable();
        $table->UnsignedBigInteger('project_id');
        $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');
        $table->timestamps();
    });
}

The Form

<x-slot name="content">
        <x-errors />
        <div >

            <form method="#" enctype="multipart/form-data">


                    @if ($projectImages)
                        Images Preview:
                        <div >

                            @foreach ($projectImages as $key => $projectImage)
                                <div >
                                    <img width="100%" src="{{ $projectImage->temporaryUrl() }}">
                                    <x-input placeholder="Caption"
                                        wire:model.defer="captions.{{ $key }}" />
                                </div>
                            @endforeach
                        </div>
                    @endif
                </div>

                <label >Upload
                    Projects Images</label>
                <div >
                    <label
                        >
                        <div >
                            
                            <p >
                                Select a photo</p>
                        </div>
                        <input wire:model="projectImages" type="file" multiple  />
                    </label>
                </div>

                <x-textarea wire:model.lazy="body" label="Body" placeholder="write your article" />

            </form>

        </div>

    </x-slot>
    <x-slot name="footer">
        @if ($projectId)
            <div >
                <x-button wire:click="CancelConfirmation" label="Cancel" flat />
                <x-button type="submit" wire:click="updateProject" label="Update" wire:loading.attr="disabled"
                    primary />
            </div>
        @else
            <div >
                <x-button wire:click="CancelConfirmation" label="Cancel" flat />
                <x-button type="submit" wire:click="storeProject" label="Create" wire:loading.attr="disabled"
                    primary />
            </div>
        @endif

    </x-slot>

</x-jet-dialog-modal>

The Project Component

public function storeProject()
{
    $this->validate([
        'title' => 'required',
        'status' => 'required',
        'budget' => 'required',
        'proposedBy' => 'required',
        'executedBy' => 'required',
        'startingDate' => 'required',
        'completionDate' => 'required',
        'progressIndicator' => 'required',
        'body'  => 'required',
        'image' => 'image|max:1024|nullable'
    ]);


    $image_name = $this->image->getClientOriginalName();
    $this->image->storeAs('public/photos', $image_name);
    $project = new Project();
    $project->user_id = auth()->user()->id;
    $project->title = $this->title;
    
    $project->status = $this->status;
    $project->budget = $this->budget;
    $project->proposed_by = $this->proposedBy;
    $project->executed_by = $this->executedBy;
    $project->starting_date = Carbon::create($this->startingDate);
    $project->completion_date = Carbon::create($this->completionDate);
    $project->progress_indicator = $this->progressIndicator;
    $project->body = $this->body;
    $project->cover_image = $image_name;
    $project->save();


    foreach ($this->projectImages as $projectImage) {

             $image_name = $projectImage->getClientOriginalName();

            $projectImage->storeAs('public/photos', $image_name);
            
            foreach ($this->captions as $caption) {

                $projectImages = new ProjectImages();
                $projectImages->project_id = $project->id;
                $projectImages->images = $image_name;
                $projectImages->caption = $caption;
            
               $projectImages->save();
            }


    }
    
    $this->notification()->success(
        $title = 'Success',
        $description = 'Project Created Successfully'
    );
    $this->reset();
}

so just so you can see visually what am trying to do here is a screenshot of the form

what the project form looks like

CodePudding user response:

I assume that you only want each project image to have one caption. If that's the case then the nested foreach loops are unnecessary and changing it to one foreach like this should solve the problem.

foreach ($this->projectImages as $key => $value) {
        $image_name = $value->getClientOriginalName();
        $value->storeAs('public/photos', $image_name);
        $projectImages = new ProjectImages();
        $projectImages->project_id = $project->id;
        $projectImages->images = $image_name;
        $projectImages->caption = $this->captions[$key];
        $projectImages->save();
}
  • Related