How to Check if a Specific Item Exists Within a Collection in Laravel

Laravel’s contains() method verifies item existence by evaluating scalar values, callbacks, or key-operator-value expressions against collection items using loose or strict comparison logic.

The Illuminate\Support\Collection class provides a robust API for array manipulation throughout the Laravel framework. When you need to check if a specific item exists within a collection in Laravel, the contains() method offers three distinct operational modes—value matching, callable filtering, and attribute comparison—without requiring manual iteration.

Understanding the contains() Method Signature

The implementation resides in src/Illuminate/Collections/Collection.php and accepts flexible arguments to accommodate different lookup strategies:

public function contains($key, $operator = null, $value = null)
{
    if (func_num_args() === 1) {
        if ($this->useAsCallable($key)) {
            return array_any($this->items, $key);
        }

        return in_array($key, $this->items);
    }

    return $this->contains($this->operatorForWhere(...func_get_args()));
}

Source: Laravel 12.x Collection.php (lines 183–194)

This single method handles three distinct calling conventions:

  • Single argument: Checks for scalar values using in_array() or executes a callback via array_any()
  • Three arguments: Parses $key, $operator, and $value into a comparison closure
  • Callable detection: Uses useAsCallable() from src/Illuminate/Support/Traits/EnumeratesValues.php to identify closures

How contains() Works Under the Hood

The method determines its execution path through argument counting and type inspection:

  1. Argument Inspection: func_num_args() identifies whether you passed one value or three
  2. Callable Routing: When the single argument is a closure or invokable object, Laravel delegates to array_any() (a core helper that iterates until the callback returns true)
  3. Value Lookup: Non-callable single arguments trigger PHP’s native in_array() with loose comparison
  4. Complex Comparisons: Three-argument calls route through operatorForWhere() to generate a closure, then recurse back into the single-argument logic

This architecture allows contains() to handle primitive scalars, object instances, and dynamic conditions through a unified interface.

Practical Examples: Checking for Items in Laravel Collections

Checking for Simple Scalar Values

When verifying primitive values or exact string matches, pass the target value directly. The method performs a loose comparison using ==.

$users = collect([
    ['id' => 1, 'name' => 'Alice'],
    ['id' => 2, 'name' => 'Bob'],
]);

// Check if "Bob" exists in the names column
$hasBob = $users->pluck('name')->contains('Bob'); // true

// Loose type comparison example
$numbers = collect([1, 2, 3]);
$hasStringOne = $numbers->contains('1'); // true (loose comparison)

Using Closures for Custom Logic

For complex conditions or computed checks, pass a closure (or arrow function) that receives the item and returns a boolean. The iteration stops at the first match.

// Check if any user has an age greater than 30
$hasSenior = $users->contains(fn ($user) => ($user['age'] ?? 0) > 30);

// Check if collection contains an even number
$hasEven = collect([1, 3, 5, 7, 8, 9])->contains(fn ($num) => $num % 2 === 0); // true

Key-Operator-Value Comparisons

Pass three arguments to perform attribute-based comparisons without writing explicit closures. Laravel supports standard operators (=, ==, >, <, >=, <=, !=).

// Find user with id equal to 2
$hasIdTwo = $users->contains('id', '=', 2); // true

// Find user with id greater than 1
$hasHighId = $users->contains('id', '>', 1); // true

Behind the scenes, operatorForWhere() constructs the comparison logic and passes it back to the callable branch of contains().

Strict Comparisons with containsStrict()

When type safety matters, use containsStrict() instead. This method enforces === comparison semantics, available in the same Collection.php file.

$mixed = collect([1, '1', 2, '2']);

// Loose check
$mixed->contains(1);        // true (matches integer 1 and string '1')

// Strict check
$mixed->containsStrict(1); // true (matches only integer 1)
$mixed->containsStrict('1'); // true (matches only string '1')

Summary

  • contains() resides in src/Illuminate/Collections/Collection.php and accepts one or three arguments depending on your lookup strategy
  • Loose comparison is the default for scalar checks, using PHP’s in_array() internally
  • Callable support enables complex logic via closures detected by useAsCallable() in EnumeratesValues.php
  • Three-argument syntax ($key, $operator, $value) delegates to operatorForWhere() for attribute filtering
  • Strict type checking requires containsStrict() to enforce === comparisons instead of ==

Frequently Asked Questions

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

contains() performs loose comparisons using == semantics, meaning the integer 1 matches the string "1". containsStrict() uses === semantics, requiring both value and type to match. According to the Laravel source code, both methods share the same internal logic but containsStrict() passes a strict flag to the underlying comparison operations.

Can I use contains() on Eloquent Collections?

Yes. Eloquent Collections extend the base Illuminate\Support\Collection class, so all contains() variants work with model collections. When checking for model instances, contains() uses object identity comparison by default, while containsStrict() ensures the exact same instance or matching primary key depending on your closure logic.

How does contains() handle object comparisons?

When passing an object to contains(), Laravel uses in_array() which checks for object identity by default (same instance). To match objects by attribute values (such as checking if any user has a specific email), use a closure: $users->contains(fn ($user) => $user->email === 'test@example.com').

Is contains() case-sensitive when checking strings?

Yes. The in_array() function and standard comparison operators used internally are case-sensitive. The string "Admin" does not match "admin" in a standard contains() check. For case-insensitive searches, normalize the case within a closure: $collection->contains(fn ($item) => strtolower($item) === 'admin').

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →