如何更新值多对多 Laravel

Posted

技术标签:

【中文标题】如何更新值多对多 Laravel【英文标题】:How update values Many To Many Laravel 【发布时间】:2021-06-01 11:29:03 【问题描述】:

如何更新 laravel 中的编辑字段?

我试过sync()方法,用atach()分离 不成功,我请你帮忙。

我非常感谢任何可以帮助我的人

记住,我已经设法用create方法保存了值,按照代码:

我的控制器:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Pedido;
use App\Models\Cliente;
use App\Models\Produto;

class PedidosController extends Controller

    /**
     * mostrar conteudo no index
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    
        $pedidos = Pedido::orderBy('id', 'asc')->paginate(2000);
        return view('pedidos.index', compact('pedidos'));
    

    /**
     * Mostra o form para criar um novo pedido.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    
        $clientes = Cliente::all();
        $produtos = Produto::all();
        return view('pedidos.create', compact('clientes', 'produtos'));
    

    /**
     * armazena um novo pedido pra enviar ao BD
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    
        $request->validate([
            'status' => 'required',
            'clientes_id' => 'required',
            'produtos_id' => 'required'
        ]);

        $pedido = Pedido::create($request->only([
            'pedidos_id',
            'produtos_id',
            'clientes_id'
        ]));

        $cliente = Cliente::find($request->clientes_id);
        $pedido->clientes()->save($cliente);
        $produto = Produto::find($request->produtos_id);
        $pedido->produtos()->attach($produto);

        return redirect()->route('pedidos.index')
            ->with('success', 'Pedido cadastrado com sucesso');
    

    /**
     * Exibe um pedido
     *
     * @param  \App\Models\Pedido  $pedido
     * @return \Illuminate\Http\Response
     */
    public function show(Pedido $pedido)
    
        return view('pedidos.show', compact('pedido'));
    

    /**
     * Exibe um pedido para edição
     *
     * @param  \App\Models\Pedido  $pedido
     * @return \Illuminate\Http\Response
     */
    public function edit(Pedido $pedido)
    
        $clientes = Cliente::all();
        $produtos = Produto::all();
        return view('pedidos.edit', compact('pedido', 'clientes', 'produtos'));
    
    /**
     * Atualiza um pedido no BD
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Pedido  $pedido
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Pedido $pedido)
    
        $request->validate([
            'status' => 'required',
            'clientes_id' => 'required',
            'produtos_id' => 'required',
        ]);
        
        $pedido->update($request->all());

        return redirect()->route('pedidos.index')
            ->with('success', 'Pedido atualizado com sucesso');
    
    /**
     * Remove um pedido do BD
     *
     * @param  \App\Models\Pedido  $pedido
     * @return \Illuminate\Http\Response
     */
    public function destroy(Pedido $pedido)
    
        $pedido->delete();

        return redirect()->route('pedidos.index')
            ->with('success', 'Pedido deletado com sucesso');
    

我的编辑:

@extends('layouts.app')

@section('content')
<div class="container content">
    <div class="row">
        <div class="col-md">
            <p class="text-center fs-1">Editar o pedido nº$pedido->id</b></p>
            <div class="float-left">
                <a class="btn btn-primary" href=" route('pedidos.index') " title="Voltar"> <i class="fas fa-backward "></i> </a>
            </div>
            </br>
            @if ($errors->any())
            <div class="alert alert-danger">
                <strong>Ops!</strong> Há um problema com seu Pedido<br><br>
                <ul>
                    @foreach ($errors->all() as $error)
                    <li> $error </li>
                    @endforeach
                </ul>
            </div>
            @endif

            <div class="row h-100">
                <div class="col">
                    <form action=" route('pedidos.update', $pedido->id) " method="POST">
                        @csrf
                        @method('PUT')
                        <div class="row">
                            <div class="col-xs-12 col-sm-12 col-md-12">
                                <label for="selectBox"> Cliente selecionado: </label>
                                <select style=width:400px name="clientes_id" class="form-control" onfocus="this.selectedIndex = -1;">
                                    @foreach ($pedido->clientes as $cliente)
                                    <option selected value=" $cliente->id"> $cliente->nome</option>
                                    @endforeach
                                    @foreach($clientes as $cliente)
                                    <option value=" $cliente->id"> $cliente->nome</option>
                                    @endforeach
                                </select>
                                </br>
                                <div class="custom-select">
                                    <label for="selectBox"> Status selecionado: </label>
                                    <select style=width:400px name="status" class="form-control" onfocus="this.selectedIndex = -1;">
                                        <option selected>  $pedido->status </option>
                                        <option value=aberto>Em aberto</option>
                                        <option value=pago>Pago</option>
                                        <option value=cancelado>Cancelado</option>
                                    </select>
                                </div>
                                </br>
                                <label for="selectBox"> Escolha um produto: </label>
                                <select style=width:400px class="form-control" name="produtos" id="selectBox" onfocus="this.selectedIndex = -1;" onchange="addProduct(options);">
                                    @foreach ($produtos as $produto)
                                    <option value=" $produto->id"> $produto->nome</option>
                                    @endforeach
                                </select>
                                </br></br>
                                <table class="table">
                                    <thead>
                                        <tr>
                                            <th>Código Produto</th>
                                            <th>Produto selecionado</th>
                                            <th>Remover</th>
                                        </tr>
                                    </thead>
                                    <tbody id="tbody">
                                        @foreach ($produtos as $key => $produto)
                                        <tr>
                                            <td>
                                                <input type="hidden" name="produtos_id[$key]" value=" $produto->id"> $produto->id
                                            </td>
                                            <td>
                                                 $produto->nome
                                            </td>
                                            <td>
                                                <input type='button' value='Remover' onclick='removeProduct()' />
                                            </td>
                                        </tr>
                                        @endforeach
                                    </tbody>
                                </table>
                                </br>
                                <div class="col-xs-12 col-sm-12 col-md-12 text-center">
                                    <button type="submit" class="btn btn-primary">Enviar</button>
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
<script>
    var table = document.getElementById('tbody');
    var count = linhas;

    function addProduct(product) 
        table.innerhtml += "<tr><td><input type='hidden' name='produtos_id[" + count + "]' value='" + product[product.selectedIndex].value + "'>" + product[product.selectedIndex].value + "</td><td>" + product[product.selectedIndex].innerText + "</td><td><input type='button' value='Remover' onclick='removeProduct()'/></tr></td>";
        count++;
    

    function removeProduct() 
        var td = event.target.parentNode;
        var tr = td.parentNode;
        tr.parentNode.removeChild(tr);
        count--;
    
</script>
@endsection

Pedido 模型

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Pedido extends Model


    protected $table = 'pedidos';
    public $timestamps = true;

    protected $fillable = [
        'status',
        'clientes_id',
        'created_at'
    ];

    public function clientes()
    
        return $this->hasMany(Cliente::class, 'id', 'clientes_id');
    
    public function produtos()
    
        return $this->belongsToMany(Produto::class, 'pedidos_produtos', 'pedidos_id', 'produtos_id');
    

产品模型

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Produto extends Model

    use HasFactory;

    protected $table = 'produtos';
    public $timestamps = true;

    protected $casts = [
        'preco' => 'float'
    ];

    protected $fillable = [
        'nome',
        'descricao',
        'preco',
        'quantidade',
        'created_at'
    ];
    public function pedidos()
    
        return $this->belongsToMany(Pedido::class, 'pedidos_produtos', 'produto_id', 'pedidos_id');
    


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Produto extends Model

    use HasFactory;

    protected $table = 'produtos';
    public $timestamps = true;

    protected $casts = [
        'preco' => 'float'
    ];

    protected $fillable = [
        'nome',
        'descricao',
        'preco',
        'quantidade',
        'created_at'
    ];
    public function pedidos()
    
        return $this->belongsToMany(Pedido::class, 'pedidos_produtos', 'produto_id', 'pedidos_id');
    

【问题讨论】:

请分享您的模型代码和架构。 attach 需要数组作为参数。使用 $pedido->produtos()->attach([$produto]); @r89human 部分正确,它可以带单个参数或数组,但应该是id,所以attach($produto-&gt;id) attach([$produto-&gt;id]) 那么您的问题解决了吗? @r89human 如果帮助github.com/wgerenutti/projetont 【参考方案1】:

您需要尝试此代码。它会起作用的。

$produtoId = [];
foreach ($produto as $pdt) 
    $produtoId[] = $pdt->id;

    
$pedido->produtos()->sync($produtoId);
$pedido->update($request->all());

【讨论】:

sync()之前不需要detach()sync() 执行 attach()detach()updateExistingPivot() 多合一幕后工作:) 下一期Produto::find() 应该返回null 或单个Produto 实例,因此foreach() 完全没有必要。你的代码可以简单到$produto = Produto::find($request-&gt;produtos_id) 然后$pedido-&gt;produtos()-&gt;sync($produto-&gt;id);,甚至$pedido-&gt;produtos()-&gt;sync($request-&gt;produtos_id); 我自己在聊天中检查了这段代码。出于某种原因 $produto = Produto::find($request->produtos_id);正在返回一个集合数组。 哦,真的吗?这很奇怪,但如果是这样的话,那么这段代码是正确的。非常有趣,因为 find() 应该只返回一个模型实例(或 null 作为后备) 是的。可能有多个具有相同“producto_id”的条目,它不是主键或架构有问题。很好的讨论。谢谢。

以上是关于如何更新值多对多 Laravel的主要内容,如果未能解决你的问题,请参考以下文章

在多对多关系 laravel4 的情况下更新数据透视表

使用 Laravel 表单模型绑定和复选框更新多对多 Eloquent 关系

在 laravel 中使用多对多关系同步:PostgreSQL 数据透视表不更新

多对多关系 - 如何更新数据透视表中的属性

使用 Laravel 中多个复选框的 attach() 更新多对多关系数据

在事件监听器中同步多对多关系(Laravel 5.7)