Skip to content

Commit 22ecbfb

Browse files
committed
Refactor BelongsToArrayColumn: simplify JSON contains constraints and enhance eager loading logic
1 parent 84ec92f commit 22ecbfb

File tree

2 files changed

+16
-83
lines changed

2 files changed

+16
-83
lines changed

.github/workflows/run-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
matrix:
1515
os: [ubuntu-latest, windows-latest]
1616
php: [8.4, 8.3, 8.2, 8.1]
17-
laravel: [10.*, 11.*, 12.*]
17+
laravel: [^10.38.0, 11.*, 12.*]
1818
stability: [prefer-lowest, prefer-stable]
1919
include:
2020
- laravel: 10.*
@@ -33,7 +33,7 @@ jobs:
3333
php: 8.1
3434
- Laravel: 12.*
3535
php: 8.1
36-
36+
3737

3838
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
3939

src/Relations/BelongsToArrayColumn.php

Lines changed: 14 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ public function addConstraints(): void
2929
}
3030
$query = $this->getBaseQuery();
3131

32-
$parentKey = $this->getParentKey();
33-
if ($parentKey !== null) {
34-
$searchValue = $this->isString ? (string) $parentKey : $parentKey;
35-
$this->addJsonContainsConstraint($query, $this->ownerKey, $searchValue);
36-
}
32+
$query->when($this->isString, function ($q) {
33+
$q->whereJsonContains($this->ownerKey, (string) $this->getParentKey());
34+
}, function ($q) {
35+
$q->whereJsonContains($this->ownerKey, $this->getParentKey());
36+
});
3737

3838
$query->whereNotNull($this->ownerKey);
3939
}
@@ -44,37 +44,15 @@ public function addConstraints(): void
4444
public function addEagerConstraints(array $models): void
4545
{
4646
$ids = $this->getEagerModelKeys($models);
47-
48-
if ($this->isString) {
49-
// For strings, simple OR with quoted values
50-
$this->query->where(function ($q) use ($ids) {
51-
foreach ($ids as $id) {
52-
$q->orWhere($this->ownerKey, 'LIKE', '%"' . $id . '"%');
53-
}
54-
});
55-
} else {
56-
// For integers, use pattern matching with OR logic
57-
$this->query->where(function ($q) use ($ids) {
58-
foreach ($ids as $id) {
59-
$q->orWhere(function ($subQuery) use ($id) {
60-
$patterns = [
61-
'%[' . $id . ',%',
62-
'%,' . $id . ',%',
63-
'%,' . $id . ']%',
64-
'%[' . $id . ']%'
65-
];
66-
67-
foreach ($patterns as $i => $pattern) {
68-
if ($i === 0) {
69-
$subQuery->where($this->ownerKey, 'LIKE', $pattern);
70-
} else {
71-
$subQuery->orWhere($this->ownerKey, 'LIKE', $pattern);
72-
}
73-
}
74-
});
75-
}
76-
});
77-
}
47+
$this->query->where(function ($q) use ($ids) {
48+
foreach ($ids as $id) {
49+
$q->when($this->isString, function ($q) use ($id) {
50+
$q->orWhereJsonContains($this->ownerKey, (string) $id);
51+
}, function ($q) use ($id) {
52+
$q->orWhereJsonContains($this->ownerKey, $id);
53+
});
54+
}
55+
});
7856
}
7957

8058
/**
@@ -107,49 +85,4 @@ public function getResults(): mixed
10785
{
10886
return $this->query->get();
10987
}
110-
111-
/**
112-
* Add JSON contains constraint in a database-agnostic way.
113-
* Uses pattern matching that works across all database engines and Laravel versions.
114-
*/
115-
protected function addJsonContainsConstraint($query, string $column, $value, string $boolean = 'and'): void
116-
{
117-
// Use pattern matching for all databases to ensure compatibility
118-
// with prefer-lowest dependency resolution in CI environments
119-
if ($this->isString) {
120-
// For strings, search for quoted value: "value"
121-
$method = $boolean === 'or' ? 'orWhere' : 'where';
122-
$query->$method($column, 'LIKE', '%"' . $value . '"%');
123-
} else {
124-
// For integers, use precise pattern matching for unquoted numbers
125-
$patterns = [
126-
'%[' . $value . ',%', // [1,
127-
'%,' . $value . ',%', // ,1,
128-
'%,' . $value . ']%', // ,1]
129-
'%[' . $value . ']%' // [1]
130-
];
131-
132-
if ($boolean === 'or') {
133-
$query->orWhere(function ($subQuery) use ($column, $patterns) {
134-
foreach ($patterns as $i => $pattern) {
135-
if ($i === 0) {
136-
$subQuery->where($column, 'LIKE', $pattern);
137-
} else {
138-
$subQuery->orWhere($column, 'LIKE', $pattern);
139-
}
140-
}
141-
});
142-
} else {
143-
$query->where(function ($subQuery) use ($column, $patterns) {
144-
foreach ($patterns as $i => $pattern) {
145-
if ($i === 0) {
146-
$subQuery->where($column, 'LIKE', $pattern);
147-
} else {
148-
$subQuery->orWhere($column, 'LIKE', $pattern);
149-
}
150-
}
151-
});
152-
}
153-
}
154-
}
15588
}

0 commit comments

Comments
 (0)