Collection::whereNull

Filters a collection down to the items whose value at the given key is strictly null.

Signature
public function whereNull(string|null $key = null): static
  • Added in Laravel 6.0

Parameters

ParameterTypeDescription
$keyoptionalstring|null= nullKey to read from each item, resolved with data_get so dot notation reaches into nested arrays and objects. When omitted, each item itself is compared against null.

Return value

staticA new collection containing only the items whose value at $key is identical to null. The original keys are preserved, so the result is usually not a clean list.

Changelog

  • PHP 6.0whereNull and whereNotNull were added and placed on the Enumerable contract, so they work on both Collection and LazyCollection.

whereNull keeps only the items whose value at $key is exactly null. It is a thin wrapper over whereStrict($key, null), so the comparison is ===. Values that are merely falsy — 0, '', '0', false, [] — are not matched.

When to reach for it

Use it once the rows are already in memory: an Eloquent result set you have to split two ways without a second query, a decoded JSON payload, a parsed CSV. If the data is still in the database, use the query builder's whereNull instead so the filtering happens in SQL and you never load the rows you are about to discard.

What trips people up

  • A missing key counts as null. Lookup goes through data_get, which returns null for an absent key, so an item with no shipped_at at all comes back next to items whose shipped_at really is null.
  • Keys are preserved. Like every filter, the original keys survive. Call values() before json_encode or you will get a JSON object instead of an array.
  • Dot notation works. whereNull('profile.deleted_at') reaches into nested structures.

Called with no key, it compares each item itself against null — a compact way to find the holes in a flat list.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Split an already-loaded set of orders into shipped and unshipped without hitting the database again.
  • Find imported CSV rows where a required column came through as null.
  • Detect models whose nullable relation column was never populated after an eager load.
  • Strip the null entries out of a flat list by calling it with no key.

Frequently asked questions

Does Collection::whereNull match empty strings, 0 or false?

No. whereNull delegates to whereStrict, which compares with ===, so only a real null matches. Use filter() with no callback if you want every falsy value removed instead.

Why does whereNull return items that do not have the key at all?

Because the lookup uses data_get, which returns null when the key is absent, making a missing key indistinguishable from a null value. Filter with array_key_exists first if you need to tell them apart.

Should I use the collection whereNull or the query builder whereNull?

Use the query builder version whenever the rows are still in the database, so the filtering happens in SQL. The collection version is for data you have already loaded, decoded or parsed.

More examples

Dot notation, and why an absent key matches

Amelia matches because deleted_at is explicitly null. Chidi matches too, even though his profile has no deleted_at key at all — data_get returns null for a missing path, and whereNull cannot tell the two cases apart. If that distinction matters, filter with array_key_exists yourself.

Example · php
<?php

$users = collect([
    ['name' => 'Amelia', 'profile' => ['deleted_at' => null]],
    ['name' => 'Bruno',  'profile' => ['deleted_at' => '2024-03-01']],
    ['name' => 'Chidi',  'profile' => []],
]);

echo json_encode($users->whereNull('profile.deleted_at')->pluck('name')->all()), "\n";
// ["Amelia","Chidi"]

echo json_encode($users->whereNotNull('profile.deleted_at')->pluck('name')->all()), "\n";
// ["Bruno"]

No key: comparing each item against null

With no argument the item itself is the value under test. The second line is the point: 0, false and '' all survive whereNotNull because the comparison is strict. This is the difference between whereNotNull and filter(), which would drop every falsy value.

Example · php
<?php

$mixed = collect(['a', null, 'b', null, 0, false, '']);

// Keys are preserved, so the nulls keep their original positions.
echo json_encode($mixed->whereNull()->keys()->all()), "\n";
// [1,3]

// The inverse keeps every falsy value that is not null.
echo json_encode($mixed->whereNotNull()->values()->all()), "\n";
// ["a","b",0,false,""]

Splitting a loaded result set in an application

data_get reads model attributes as well as array keys, so whereNull works unchanged on an Eloquent collection. The commented alternative is the one to use when you have not already loaded the posts — the collection method filters in PHP after every row has been hydrated, while the query builder method filters in SQL.

Example · php
<?php

use App\Models\Post;

$posts = Post::with('author')->get();

$drafts = $posts->whereNull('published_at');
$live   = $posts->whereNotNull('published_at')->sortByDesc('published_at');

echo $drafts->count() . " drafts, " . $live->count() . " live\n";

// Prefer this when the rows are still in the database:
// $drafts = Post::whereNull('published_at')->get();

Discussion

  • Be the first to comment on this lesson.