prgrm
prgrm

Reputation: 3833

Getting a specific eloquent object out of a collection in Laravel

I have a function that looks for possible boxes that can carry the article.

public static function get_possible_boxes($article,$quantity)
{
    $i = 0;

    $possible_boxes = array();

    $total_weight = $articles->grams * $quantity;

    $boxes = Boxes::all();


    foreach($boxes as $box)
    {
        if($total_weight+ $box->grams < $box->max_weight)
        {
            $possible_boxes[$i] = $box;
            $i++;
        }
    }

        return collect($possible_boxes);
}

This gives me a collection with boxes that can carry my items.

Now I should check if the ID of the box selected by the customer exists. If it does not exist, it will pick the first valid one.

This is where I am stuck. I have tried to use puck:

public function someotherfunction(){
...
$boxes = get_possible_boxes($something,$number);
$valid_box = $boxes->where("id", $request->selected_box)->pluck("id");
if(!$valid_box){
  $valid_box = $boxes[0]
}
...

This works if the selected box cannot be used. The function pluck only gives me the id, clearly it is not the function I am looking for and I have already read the Laravel documentation.

So the question is, how do I get the correct eloquent model ?

Upvotes: 1

Views: 545

Answers (3)

The Alpha
The Alpha

Reputation: 146191

It could be done in many ways but I would rather use the following approach:

$boxes = get_possible_boxes($something,$number)->keyBy('id');

$valid_box = $boxes->get($request->selected_box) ?: $boxes->first();

Upvotes: 1

patricus
patricus

Reputation: 62228

You're looking for the first() method.

$valid_box = $boxes->where("id", $request->selected_box)->first();

Alternatively, if you rework your get_possible_boxes() method to return a Illuminate\Database\Eloquent\Collection instead of a plain Illuminate\Support\Collection, you could use the find() method, like so:

Function:

public static function get_possible_boxes($article,$quantity)
{
    $total_weight = $article->grams * $quantity;

    $boxes = Boxes::all()->filter(function ($box) use ($total_weight) {
        return $total_weight + $box->grams < $box->max_weight;
    });

    return $boxes;
}

Find:

$boxes = get_possible_boxes($something, $number);
$valid_box = $boxes->find($request->selected_box) ?? $boxes->first();

And you could probably squeeze out a little more performance by adding the weight condition as part of the SQL query instead of filtering the collection after you've returned all the boxes, but I left that up to you.

Upvotes: 3

Ohgodwhy
Ohgodwhy

Reputation: 50777

What you want is probably filter.

$valid_box = $boxes->filter(function($box) use ($request){
    return $box->id == $request->selected_box;
});

if($valid_box)...

I should note that if you don't want $valid_box to be a collection, you can use first instead of filter in the exact same way to only get the object back.

Upvotes: 1

Related Questions