Use the Laravel diff in two Collections

Asked

Viewed 600 times

1

I am trying to fetch items that are not in a particular product.

I therefore have a model Produto, each product has several items, and another model Item.

I’m trying to use Collections of Laravel, more specifically the method diff, as follows:

public function buscarItens($id)
{
    $produto = Produto::find($id);

    //busca todos os itens cadastrados
    $todosItens = Item::all();

    //busca os itens do produto
    $itensDoProduto = $produto->itens;

    //retorna os produtos que NÃO PERTENCEM ao item + os produtos que PERTENCEM ao item
    $collection1 = collect($todosItens);
    $diff = $collection1->diff($itensDoProduto);

    return response()->json($collection1);
}

It turns out that this difference that is returning is equal to itself $todosItens, as if there were no items in common between the $itensDoProduto and $todosItens, but there is.

What might be going on?

OBS: I thought I’d use the diffKeys(), but I want to seek only the difference of ids, and not of all attributes.

1 answer

1

What is the Collection certain?

You need to understand that there is a difference between classes Illuminate\Database\Eloquent\Collection and Illuminate\Support\Collection. The first is returned when you call the get in a consultation made by Eloquent, the second, however, when you call the function collect.

The diff of these two classes operate in different ways!

Note the difference between the definition of Illuminate Database Eloquent Collection and Illuminate Support Collection.

Therefore, you should choose to use the Collection of Eloquent and not of Support.

Thus:

public function buscarItens($id)
{
    $produto = Produto::find($id);

    $todosItens = Item::all();

    $diff = $todosItens->diff($produto->itens);

    return response()->json($diff);
}

Note: I cleaned up the definitions, because it is not necessary to go out declaring so many variables that are barely used.

Pay attention to the code!

Another detail is that you want to return the difference, but are returning the variable $collection1, which represents "all items". This is looking like a fault of yours when writing the code.

Why not return direct from the query?

You can return relationship-based results through Eloquent. There are four methods I use a lot for this: whereHas, has, doesntHave, whereDoesntHave.

For example, if I want to return all items that do not have relationships with the Produto id 1, I can use whereDoesntHave.

$itensNaoRelacionados = Item::whereDoesntHave('produto', function ($query) use ($id) {
                                $query->where('id', '=', $id);
                            })->get();

Browser other questions tagged

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