Laravel - función sync para una relación Has Many

Eleazar Resendez

Eleazar Resendez

May 02 — 2 mins read

Laravel tiene un método de sincronización para crear asociaciones con una relación de muchos a muchos.

El método de sincronización acepta un arreglo de IDs para colocarlos en la tabla intermedia. Cualquier ID que no esté en el arreglo se eliminará de la tabla intermedia.

Después de completar la operación anterior, solo los IDs del arreglo existirán en la tabla intermedia. Esto es excelente, pero la relación hasMany no cuenta con esta funcionalidad.

Amith Gotamey comparte un método simple para hacerlo utilizando las clases de Collection. Para ilustrar esto, supongamos que tenemos un modelo User con una relación HasMany Contacts.

/**
 * User Has Many Contacts
 *
 * @return hasMany
 */
public function contacts()
{
    return $this->hasMany(Contact::class);
}

Ahora, el método de sincronización sería algo así:

/**
 * Sync contacts
 *
 * @param array $contacts
 */
public function syncContacts(array $contact_items)
{
    $children = $this->contacts;
    $contact_items = collect($contact_items);

    $deleted_ids = $children->filter(function ($child) use ($contact_items) {
        return empty($contact_items->where('id', $child->id)->first());
    })->map(function ($child) {
        $id = $child->id;
        $child->delete();
        return $id;
    });

    /**
     * Añadí esta sección por si es necesario actualizar
     * los contactos que ya se encuentran relacionados.
     */
    $updates = $contact_items->filter(function ($contact) {
        return isset($contact['id']);
    })->map(function ($contact) {
        $this->contacts->map(function ($c) use ($contact) {
            $c->updateOrCreate([
                'id' => $contact['id']
            ],[
                'type' => $contact['type'],
                'value' => $contact['value'],
            ]);
        });
    });

    $attachments = $contact_items->filter(function ($contact) {
        return ! isset($contact['id']);
    })->map(function ($contact) use ($deleted_ids) {
        $contact['id'] = $deleted_ids->pop();
        return $contact;
    })->toArray();

    $this->contacts()->createMany($attachments);
}

Hope this helps!

laravel

¿Quieres leer más publicaciones similares?

Cada dos semanas envío un boletín con el contenido más reciente del blog.

Siguiente nota

Coderwall Tip: .gitignore is not working

Algunas veces al querer ignorar un archivo o carpeta y este ya se encuentra en .gitignore y aún así no desaparece de la lista de cambios. En...

Te puede interesar

Laravel 5.8 & Bulma Framework CSS

Bulma es un framework CSS opensource, basado en Flexbox, full responsive, modular y provee un sistema simple de grid.Es una colección de cla...

Laravel - función sync para una relación Has Many
Compartir