Collection::contains

Determines whether the collection holds a matching item, by value, key/value pair or truth test.

Signature
contains(mixed $key, mixed $operator = null, mixed $value = null): bool
  • Added in Laravel 4.0

Parameters

ParameterTypeDescription
$$key(callable(TValue, TKey): bool)|TValue|stringA value to search for, a closure truth test, or — when further arguments are given — the key to inspect on each item.
$$operatoroptionalmixed= nullWith three arguments, the comparison operator (=, ==, ===, !=, <, >, <=, >=, <=>). With two arguments, the value to compare the key against.
$$valueoptionalmixed= nullThe value the resolved key must match.

Return value

boolTrue when a matching item exists, false otherwise.

Changelog

  • PHP 9.xdoesntContain() was added as the direct inverse, replacing the ! $collection->contains(...) idiom.
  • PHP 5.3Passing a key/value pair began comparing against the item's key rather than treating both arguments as values.

contains() answers "is this in here?" and changes meaning with the number of arguments you pass.

One argument

A closure runs as a truth test. Anything else is compared against the collection's values with in_array() — never against the keys. collect(['name' => 'Desk'])->contains('name') is false; use has() for keys.

Two or three arguments

Two arguments read as key and value: contains('product', 'Desk') checks each item's product field. Three arguments insert an operator: contains('price', '>', 100). Both resolve the key with data_get(), so arrays, objects, models and dot paths all work.

Loose comparison is the default

The one-argument form uses in_array() without the strict flag, so '2' matches 2 and 0 matches '0'. That is usually what you want for a route parameter, and dangerous when the collection mixes types. containsStrict() has the same signature and compares with ===. PHP 8's tightened string-to-number rules removed the old 'abc' == 0 trap, but numeric strings still match integers.

Inverse

Prefer doesntContain() over ! $collection->contains(); it reads better and takes the same arguments.

Example

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

When to use it

  • Check whether a submitted id appears in a list of allowed ids.
  • Test whether any order in a batch exceeds a value threshold.
  • Confirm a user's roles include a required role name before authorising an action.

Frequently asked questions

Does contains() check keys or values?

Values, when you pass one argument — collect(['name' => 'Desk'])->contains('name') returns false. Pass two arguments to check a key/value pair on each item, or use has() to test whether a key exists.

What is the difference between contains() and containsStrict()?

contains() compares loosely, so the string '2' matches the integer 2, while containsStrict() compares with ===. Use the strict version whenever the collection mixes types, and cast request input first since it always arrives as a string.

How do I check that a collection does not contain a value?

Use doesntContain(), added in Laravel 9, which takes exactly the same arguments as contains() and returns the opposite result. doesntContainStrict() is its strict counterpart.

More examples

The loose-comparison trap with request input

The first pair shows why containsStrict() on raw request input rejects valid ids: HTTP input is always a string. The last block shows the opposite failure — loose comparison treats false as equal to 0, so a strict check or an explicit cast is the only reliable guard on a collection of flags.

Example · php
<?php

$allowedIds = collect([1, 2, 3]);

// Request input arrives as a string.
$submitted = '2';

var_dump($allowedIds->contains($submitted));        // bool(true)
var_dump($allowedIds->containsStrict($submitted));  // bool(false)

// Casting makes the intent explicit and survives either method.
var_dump($allowedIds->containsStrict((int) $submitted)); // bool(true)

// Where loose comparison genuinely misfires:
$flags = collect([0, 1]);
var_dump($flags->contains('0'));        // bool(true)
var_dump($flags->contains(false));      // bool(true)  <- 0 == false
var_dump($flags->containsStrict(false)); // bool(false)

Operator form and doesntContain on models

The operator form filters on a numeric attribute without a closure, and dot notation reaches an eager-loaded relation. doesntContain() reads better than negating the call. The final line shows the safe way to test model identity: contains() with a model uses loose comparison of attributes, while is() compares key and table. Needs a booted application with a database.

Example · php
<?php

$orders = Order::whereDate('created_at', '2026-03-01')->get();

// Three-argument form: key, operator, value.
if ($orders->contains('total_cents', '>', 100_00)) {
    echo "At least one large order today\n";
}

// Dot notation resolves through data_get().
var_dump($orders->contains('customer.country', 'NO'));

// The readable inverse.
if ($orders->doesntContain('status', 'refunded')) {
    echo "Clean day, no refunds\n";
}

// Passing a model compares with ==, so a fresh instance of the same
// row still matches. Compare ids when identity matters.
var_dump($orders->contains(fn (Order $o) => $o->is($target)));

Discussion

  • Be the first to comment on this lesson.