Skip to content

Extended Search with includeMatches = true throws “Undefined array key 1” when matching empty strings #133

@Schwankenson

Description

@Schwankenson

Extended Search with includeMatches = true throws “Undefined array key 1” when matching empty strings

Description

When using the PHP port of Fuse.js (loilo/Fuse) with extended search and includeMatches = true, the library attempts to calculate match indices ([start, end]) even on empty or null field values. If a record field is the empty string ("") or null, PHP emits an “Undefined array key 1” error during the internal offset‐parsing step and aborts the search.

Version & Environment

  • loilo/Fuse version: 7.0
  • PHP: 7.4 / 8.0+ (behaves identically)
  • OS / Platform: Linux / macOS (any)

Steps to Reproduce

<?php
require 'vendor/autoload.php';

use Fuse\Fuse;

$data = [
    ['name' => '', 'vorname' => 'Alice'],
    ['name' => 'Bob', 'vorname' => ''],
];

$options = [
    'keys'              => ['name', 'vorname'],
    'useExtendedSearch' => true,
    'includeScore'      => true,
    'includeMatches'    => true,
];

$fuse = new Fuse($data, $options);

// Search on an empty string
$query = ['name' => '=whatever'];
$results = $fuse->search($query);

Actual Behavior

A PHP warning/exception is thrown:

PHP Notice:  Undefined array key 1 in .../vendor/loilo/fuse/src/ExtendedSearch.php on line XXX

or, in strict mode:

Exception: Undefined array key 1

which aborts the search entirely.

Expected Behavior

Fields with empty strings or null values should be skipped when calculating match offsets, resulting in:

  • No PHP notices or exceptions.
  • An empty matches array for that field (or simply no entry in matches), while other fields continue to be matched and scored.

Proposed Fix

Add a guard in ExtendedSearch.php (e.g. in the matchExtended() method) before attempting to read [start, end] indices:

protected function matchExtended(string $pattern, $text)
{
    // Guard against empty or non-string values
    if (!is_string($text) || $text === '') {
        return [];  // skip match-offset computation
    }

    // existing logic to compute start/end indices …
}

Workarounds

  • Disable match-offset reporting by setting:
    'includeMatches' => false
  • Normalize your data and set fields with empty string value to mb_chr(0x2060, 'UTF-8')

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions