Collection::min
Returns the smallest value in the collection, optionally read from a key or callback.
public function min(callable|string|null $callback = null): mixedParameters
| Parameter | Type | Description |
|---|---|---|
$$callbackoptional | callable|string|null= null | A key to read from each item (dot notation supported) or a callback returning the value to compare. Omit it to compare the items themselves. |
Return value
mixedThe smallest value found, or null when the collection is empty or every value is null.
min is the mirror of max: it reduces the collection to its smallest value. Called bare it compares the items themselves, with a string it reads that key from every item via data_get (dot notation included), and with a callback it compares whatever the callback returns.
When to reach for it
Cheapest price in a loaded product list, earliest timestamp in a parsed batch, lowest score in an in-memory leaderboard. As with max, if the rows are still in the database the query builder's aggregate is much cheaper than hydrating everything to scan it in PHP.
What trips people up
Values that are null are dropped before the comparison, which is usually what you want — a missing price should not beat a real one — but it means the result can be null only when there was nothing comparable at all. Distinguish "no rows" from "minimum of zero" explicitly.
Only the value comes back, never the item that held it; use sortBy() with first() for the whole row. And comparison uses PHP's <, so mixed types follow PHP's rules: numeric strings compare numerically, dates compare lexically and are only trustworthy in an unambiguous format such as ISO-8601.
Example
When to use it
- Find the cheapest variant among an already loaded set of product options.
- Get the earliest ISO-8601 timestamp from a batch of imported records.
- Determine the lowest stock level to decide whether a reorder is needed.
Frequently asked questions
Does it ignore null values?
Yes — nulls are filtered out before the comparison, so a missing value never wins. If every value is null the result is null.
How do I get the row holding the minimum?
Use sortBy('column')->first(); this method only returns the compared value, never the item it came from.
Should I use this or the query builder's aggregate?
Use the query builder when the rows are still in the database — it runs one aggregate query instead of hydrating every model into memory first.
More examples
Cheapest variant with a callback
The callback computes the effective price, so the answer is 1100 from the medium variant rather than the 1200 sticker price of the small one. Printed as currency that is 11.00.
<?php
$variants = collect([
['name' => 'small', 'price' => 1200, 'discount' => 0],
['name' => 'medium', 'price' => 1800, 'discount' => 700],
['name' => 'large', 'price' => 2400, 'discount' => 300],
]);
$cheapest = $variants->min(fn (array $v) => $v['price'] - $v['discount']);
echo number_format($cheapest / 100, 2) . PHP_EOL;Earliest date, safely formatted
ISO-8601 strings sort correctly as text, so the earliest value 2024-04-28T23:45:00Z is returned without parsing anything into date objects. The same code with dates written as 28/04/2024 would return the wrong row.
<?php
$jobs = collect([
['id' => 1, 'queued_at' => '2024-05-02T08:00:00Z'],
['id' => 2, 'queued_at' => '2024-04-28T23:45:00Z'],
['id' => 3, 'queued_at' => '2024-05-01T06:10:00Z'],
]);
echo $jobs->min('queued_at') . PHP_EOL;Empty versus zero
An empty collection and a genuine minimum of zero both look falsy, which is why the check uses is_null and a strict comparison. The dumps show NULL and int(0) respectively.
<?php
$stock = collect([]);
$lowest = $stock->min('qty');
if (is_null($lowest)) {
echo 'nothing to check' . PHP_EOL;
} elseif ($lowest === 0) {
echo 'out of stock' . PHP_EOL;
}
var_dump($lowest);
var_dump(collect([['qty' => 0], ['qty' => 4]])->min('qty'));
Discussion