Relationship N:N in Laravel does not record object attributes

Asked

Viewed 609 times

1

My tables have, briefly, the following structure:

minutes:

id | vigencia

products:

id | nome | descricao

ata_produto:

ata_id | produto_id | vlr_produto | qtd_produto

The same product may have different value depending on the minutes, so the registration of the product has no price. It is only set at the time I insert it in a minutes. For that I need to record the id the quantity and value of each product.

The problem is there, I can relate the products to the minutes, but the price and quantity are not recorded.

Model - Product:

public function atas() {
    return $this->belongsToMany('App\Ata')->withPivot('vlr_produto', 'qtd_produto');
}

Model - Ata:

public function produtos() {
    return $this->belongsToMany('App\Produto')->withPivot('vlr_produto', 'qtd_produto');
}

Atacontroller:

public function store(Request $request) {
    $input = $request->all();
    $produtos      = (array)array_get($input, 'produto_id');
    $quantidades   = (array)array_get($input, 'qtd_produto');
    $valores       = (array)array_get($input, 'vlr_produto');

    $ata = Ata::create($input);
    $ata->produtos()->sync($produtos, $quantidades, $valores);

    return redirect('admin/atas');
}

As I said, the relationship works. I don’t know how to record, besides the produto_id and ata_id, the vlr_produto and the qtd_produto.

Can someone help me?

1 answer

2


Laravel Eloquent provides basically two ways to work with relationship several to several (N:N).

The first is attach and separate manually. For this use attach and detach.

The second is to build relationships between the models with sync.

Using this method you should pass an array with the id and their respective values in the intermediate table.

$produto_id = 1;
$valor = 10;
$quantidade = 10;

$attributes = [ 'vlr_produto' => $valor, 'qtd_produto' => $quantidade ];

$ata->produtos()->sync( $produto_id => $attributes );

In the case of several products:

$ata->produtos()->sync([ $produto_id => $attributes, 
                         $other_produto_id => $other_attributes ]);

ATTENTION

When using the method sync:

Any Ids that are not in the Given array will be Removed from the Intermediate table. So, after this Operation is complete, only the Ids in the array will exist in the Intermediate table

Laravel Eloquent Relationships

Apparently, you do not want to remove other relationships from minutes with products when invoking this method. So I recommend using the attach to create relationships.

For that, do:

$attributes = [ 'vlr_produto' => $valor, 'qtd_produto' => $quantidade ];

$ata->produtos()->attach( $produto_id, $attributes );

If you want to attach several products à minutes, I suggest you make a loop

$produtos = [ 1, 2, 3 ];

$valores = [ 
   1 => 10, 
   2 => 20, 
   3 => 30 
];

$quantidades = [ 
   1 => 10, 
   2 => 20, 
   3 => 30 
];

foreach ( $produtos as $index => $produto ) 
{
  // atributos do produto atual
  $attributes = [ 
     'vlr_produto' => $valores[ $index ], 
     'qtd_produto' => $quantidades[ $index ] 
  ];

  $ata->produtos()->attach( $produto, $attributes );
}

This is a didactic solution. Adapt it according to your data.

Save the model at the end of the operation

$ata->save();
  • it is. using Sync(), even as you suggested, it didn’t work. I don’t know how to use the attach for it. I am looking for and will try.

  • I used $ata->products()->attach($products, $attributes); and it worked if I was only writing a single product, but as an array. It’s an error. Strange that the $products variable is also an array.

  • Using attach this way returns the error: "preg_replace(): Parameter Mismatch, Pattern is a string while Replacement is an array"

  • I’ll update the answer to case attach of various products

  • Show! It worked. I just fixed the foreach to use the index because it was giving error! Thank you so much for the help. : D

Browser other questions tagged

You are not signed in. Login or sign up in order to post.