Tabla de pivote Laravel adjunta duplicaciones muchas veces

En mi proyecto, hay una competencia que incluye muchos equipos, y un organizador puede subir muchos documentos/fotos a una competencia que los asigna a un equipo, así que decidí hacer un files tabla para almacenar todos los datos del archivo mientras que hay tablas separadas para compactions, y teams y hice una tabla de pivotes como competition_file con campos competition_id , team_id , file_id, y type como imagen inferior

enter image description here

Así es como mi UI parece

enter image description here

En este formulario, usted es capaz de subir múltiples imágenes/documentos fotos son subidas por una solicitud de Ajax. El formulario obtiene la respuesta uuid's de las imágenes subidas en la tabla de archivos y se envía de nuevo a la store functions en la tabla de documentos.

Aquí está la función de la tienda Files controlador

public function store(Request $request)
{
    $this->validate($request, [
        'file' => 'required|image',
    ]);

    $fh = new FileUploader($request);
    $fh->toDisk('public');

    if ($request->has('upload_dir')) {
        $fh->saveToDir($request->input('upload_dir', 'files'));
    }

    $result = $fh->upload();
    if ($result->isSuccessful()) {
        $file = new File([
            'key' => Uuid::generate(4),
            'name' => $request->name,
            'description' => $request->description,
            'allow_public_access' => false,
            'original_filename' => $result->getOriginalFilename(),
            'file_path' => $result->filePath(),
            'file_disk' => $result->diskName(),
            'file_url' => $result->publicUrl(),
            'file_size_bytes' => $result->getFileSize(),
            'uploaded_by_user_id' => (auth()->id()) ?? auth()->id()
        ]);
        $file->category = $request->input('category', 'general');
        $file->save();

        return response()->apiSuccess([
            'uuid' => $file->uuid,
        ]);
    }

    return response()->apiError('Failed to upload file. Try with another file or contact admin.');
}

Aquí está la relación en la Teams modal

public function documents()
{
    return $this->belongsToMany(File::class,'competition_file')->wherePivot('type', 'image');
}

Y aquí está la función de la tienda del controlador de documentos

   public function store($competition, Request $request, Team $entity)
    {

    
    $uuid = $request->photos;
    File::whereIn('uuid', $uuid)->update(['name' => $request->name, 'description'=>$request->description]);        

     

     if ($request->has('photos') && is_array($request->photos)) {
        $files = $this->filesRepo->getByUuids($request->photos);

      

        if ($files->isNotEmpty()) {

           
            $entity->documents()->attach($files->pluck('id'),['team_id'=>$request->team,'competition_id'=>$competition]);
          

          
        }
    } }

Necesito saber qué pasa con la mesa de pivotes, no pude usar sync y yo usé attach, y cuando guardo los datos a la y adjuntar las relaciones, duplica si he seleccionado más de 1 imagen/documento, como se muestra en la imagen siguiente

enter image description here

mientras he seleccionado sólo 3 imágenes, obtengo duplicados '

así es como se ve la mesa de pivotes después de la tienda

enter image description here

Aquí están los archivos de migración para competition_file Cuadro

    class CreateCompetitionFileTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('competition_file', function (Blueprint $table) {
            $table->bigInteger('competition_id')->unsigned()->references('id')->on('competitions')->onDelete('cascade');
            $table->bigInteger('file_id')->unsigned()->references('id')->on('files')->onDelete('cascade');
$table->bigInteger('team_id')->unsigned()->references('id')->on('teams')->onDelete('cascade');
            $table->string('type')->default('image')->comment('image|attachment');

        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('competition_file');
    }
}

Alguien, por favor ayúdame.

Pregunta hecha hace 3 años, 4 meses, 28 días - Por debugdynamob312


2 Respuestas:

  • El problema que estás experimentando se debe a que estás adjuntando múltiples archivos al mismo tiempo y al guardar las relaciones en la tabla pivote competition_file, estás duplicando las entradas en la tabla.

    Para evitar la duplicación de relaciones en la tabla pivote al adjuntar múltiples archivos, puedes modificar tu función store en el controlador de documentos de la siguiente manera:

    php
    public function store($competition, Request $request, Team $entity)
    {
        $uuids = $request->photos;
    
        if ($request->has('photos') && is_array($request->photos) && count($uuids) > 0) {
            $files = $this->filesRepo->getByUuids($uuids);
    
            if ($files->isNotEmpty()) {
                $syncData = [];
                foreach ($files as $file) {
                    $syncData[$file->id] = ['team_id' => $request->team, 'competition_id' => $competition];
                }
    
                $entity->documents()->sync($syncData);
            }
        }
    
        // Resto de tu lógica de almacenamiento de archivos y retorno de respuesta
    }
    

    En este código, primero obtenemos los identificadores de los archivos basados en los UUIDs proporcionados en la solicitud. Luego creamos un array $syncData que contiene los IDs de los archivos como clave y los datos adicionales de la relación (como team_id y competition_id) como valor.

    Finalmente, utilizamos el método sync en la relación documents del equipo para sincronizar las relaciones con los archivos de forma que no se dupliquen en la tabla pivote.

    Con esta modificación, deberías poder evitar la duplicación de las relaciones en la tabla pivote al adjuntar múltiples archivos. ¡Espero que esta solución te sea de ayuda! Si tienes alguna otra pregunta o duda, no dudes en decírmelo.

    Respondida el Dec 19, 2020 a las 16:19 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Para resolver el problema de duplicados en la tabla pivote competition_file, puedes utilizar el método sync en lugar de attach. El método sync sobrescribirá los registros existentes en la tabla pivote, mientras que attach añadirá nuevos registros sin eliminar los existentes.

    Aquí tienes un ejemplo actualizado de tu función store en el controlador Documents:

    php
    public function store($competition, Request $request, Team $entity)
    {
        // ... (código anterior)
    
        if ($request->has('photos') && is_array($request->photos)) {
            $files = $this->filesRepo->getByUuids($request->photos);
    
            if ($files->isNotEmpty()) {
                $entity->documents()->sync($files->pluck('id'), ['team_id' => $request->team, 'competition_id' => $competition]);
            }
        }
    
        // ... (código posterior)
    }
    

    Además, asegúrate de que has definido correctamente la relación documents en el modelo Team para utilizar el método sync:

    php
    public function documents()
    {
        return $this->belongsToMany(File::class, 'competition_file')->withPivot('type')->wherePivot('type', 'image');
    }
    

    Con estos cambios, la tabla pivote competition_file debería actualizarse correctamente sin duplicados al almacenar los datos de documentos.

    Respondida el Dec 19, 2020 a las 16:24 - por Gemini

    Votos positivos: 0 | Votos negativos: 0