Certainly! The problem here is that you want to set up a relationship where the "foreign" key can have wildcards (using ?) and you want to match those to the parts of an id column in another model that don't have wildcards—at the database relationship (Eloquent) level if possible.
Relationships in Laravel typically use exact matches, but in your case, you need pattern matching (using LIKE) with support for ? as a single-character wildcard.
Solution Outline
- Storing parts in generated columns makes this easier. We'll assume your table has columns for
firstname,lastname,titlefor both models. - You can't use
orWhereor an advanced query directly inside an Eloquent relationship's definition. However, you can use a custom relationship withhasManyand add extra constraints using->where(...)or->whereRaw(...). - You can't directly use
?as a wildcard in SQL; you must convert?to_(underscore), the single-character wildcard in SQLLIKE.
Example Solution
Let's assume your RelatedName model has columns:
name_id: string, e.g.'???_SMITH_??'firstname,lastname,titleas stored generated columns
Step 1: Add an Accessor to Convert ? to _ in Name Model
public function namePattern()
{
// Converts THIS model's id into a SQL LIKE pattern, replacing '?' with '_'
return str_replace('?', '_', $this->id);
}
Step 2: Custom Relationship Definition
Because we want RelatedNames whose pattern matches the Name's ID, but the pattern with _ wildcards, we use whereRaw with a LIKE.
public function relatedNames()
{
return RelatedName::query()
->whereRaw('? LIKE REPLACE(name_id, "?", "_")', [$this->id]);
}
This makes the relationship: return all RelatedNames WHERE the pattern in name_id, with '?' replaced by '_' (SQL wildcard), matches this model's id.
If you want this as an actual relationship property, you can use:
public function relatedNames()
{
return $this->hasMany(RelatedName::class, 'name_id', 'id')
->whereRaw('? LIKE REPLACE(name_id, "?", "_")', [$this->id]);
}
But this will run the exact same query.
Step 3: Usage
$name = Name::find(1);
$related = $name->relatedNames; // Will contain all related names matching the pattern
Summary
- Store patterns as
???_SMITH_??inname_idofRelatedName. - On the
Namemodel, define the relationship usingwhereRaw+LIKE, replacing?with_. - This tells Eloquent to match Name's
idagainst the wildcard pattern.
Full Example
In Name model:
public function relatedNames()
{
return $this->hasMany(RelatedName::class, 'name_id', 'id')
->whereRaw('? LIKE REPLACE(name_id, "?", "_")', [$this->id]);
}
Usage:
$relatedNames = $name->relatedNames; // Now includes wildcard matches
Note: If you have the parts as columns, adjust the whereRaw to build the LIKE condition per part.
Let me know if you want a version that splits and matches by firstname, lastname, and title columns!