Last active
May 9, 2024 00:29
-
-
Save vanthao03596/b49747bf5725a97d091f482d42c7c576 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Models\Concerns; | |
trait SearchBuilder | |
{ | |
public function scopeSearchBuilder($query) | |
{ | |
if (request()->filled('searchBuilder') && request()->query('searchBuilder') !== 'false') { | |
$query->where(function ($query) { | |
$this->searchBuilderCondition($query, request()->query('searchBuilder')); | |
}); | |
} | |
} | |
protected function searchBuilderCondition($query, $data) | |
{ | |
$first = true; | |
if (!isset($data['criteria'])) { | |
return; | |
} | |
// Iterate over every group or criteria in the current group | |
foreach ($data['criteria'] as $crit) { | |
// If criteria is defined then this must be a group | |
if (isset($crit['criteria'])) { | |
// Check if this is the first, or if it is and logic | |
if ($data['logic'] === 'AND' || $first) { | |
// Call the function for the next group | |
$query->where(function ($q) use ($crit) { | |
$this->searchBuilderCondition($q, $crit); | |
}); | |
// Set first to false so that in future only the logic is checked | |
$first = false; | |
} else { | |
$query->orWhere(function ($q) use ($crit) { | |
$this->searchBuilderCondition($q, $crit); | |
}); | |
} | |
} else if (isset($crit['condition']) && (isset($crit['value1']) || $crit['condition'] === 'null' || $crit['condition'] === '!null')) { | |
// Sometimes the structure of the object that is passed across is named in a strange way. | |
// This conditional assignment solves that issue | |
$val1 = isset($crit['value1']) ? $crit['value1'] : ''; | |
$val2 = isset($crit['value2']) ? $crit['value2'] : ''; | |
if (strlen($val1) === 0 && $crit['condition'] !== 'null' && $crit['condition'] !== '!null') { | |
continue; | |
} | |
if (strlen($val2) === 0 && ($crit['condition'] === 'between' || $crit['condition'] === '!between')) { | |
continue; | |
} | |
// Switch on the condition that has been passed in | |
switch ($crit['condition']) { | |
case '=': | |
// Check if this is the first, or if it is and logic | |
if ($data['logic'] === 'AND' || $first) { | |
// Call the where function for this condition | |
$query->where($crit['origData'], '=', $val1); | |
// Set first to false so that in future only the logic is checked | |
$first = false; | |
} else { | |
// Call the orWhere function - has to be or logic in this block | |
$query->orWhere($crit['origData'], '=', $val1); | |
} | |
break; | |
case '!=': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where($crit['origData'], '!=', $val1); | |
$first = false; | |
} else { | |
$query->orWhere($crit['origData'], '!=', $val1); | |
} | |
break; | |
case 'contains': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where($crit['origData'], 'LIKE', '%' . $val1 . '%'); | |
$first = false; | |
} else { | |
$query->orWhere($crit['origData'], 'LIKE', '%' . $val1 . '%'); | |
} | |
break; | |
case 'starts': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where($crit['origData'], 'LIKE', $val1 . '%'); | |
$first = false; | |
} else { | |
$query->orWhere($crit['origData'], 'LIKE', $val1 . '%'); | |
} | |
break; | |
case 'ends': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where($crit['origData'], 'LIKE', '%' . $val1); | |
$first = false; | |
} else { | |
$query->orWhere($crit['origData'], 'LIKE', '%' . $val1); | |
} | |
break; | |
case '<': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where($crit['origData'], '<', $val1); | |
$first = false; | |
} else { | |
$query->orWhere($crit['origData'], '<', $val1); | |
} | |
break; | |
case '<=': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where($crit['origData'], '<=, $val1'); | |
$first = false; | |
} else { | |
$query->orWhere($crit['origData'], '<=, $val1'); | |
} | |
break; | |
case '>=': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where($crit['origData'], '>=, $val1'); | |
$first = false; | |
} else { | |
$query->orWhere($crit['origData'], '>=, $val1'); | |
} | |
break; | |
case '>': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where($crit['origData'], '>', $val1); | |
$first = false; | |
} else { | |
$query->orWhere($crit['origData'], '>', $val1); | |
} | |
break; | |
case 'between': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where(function ($q) use ($crit, $val1, $val2) { | |
$q->where($crit['origData'], '>', is_numeric($val1) ? intval($val1) : $val1)->where($crit['origData'], is_numeric($val2) ? intval($val2) : $val2, '<'); | |
}); | |
$first = false; | |
} else { | |
$query->orWhere($crit['origData'], '>', is_numeric($val1) ? intval($val1) : $val1)->where($crit['origData'], is_numeric($val2) ? intval($val2) : $val2, '<'); | |
} | |
break; | |
case '!between': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where(function ($q) use ($crit, $val1, $val2) { | |
$q->where($crit['origData'], '<', is_numeric($val1) ? intval($val1) : $val1)->orWhere($crit['origData'], is_numeric($val2) ? intval($val2) : $val2, '>'); | |
}); | |
$first = false; | |
} else { | |
$query->orWhere($crit['origData'], '<', is_numeric($val1) ? intval($val1) : $val1)->orWhere($crit['origData'], is_numeric($val2) ? intval($val2) : $val2, '>'); | |
} | |
break; | |
case 'null': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where(function ($q) use ($crit) { | |
$q->where($crit['origData'], "=", null); | |
if (strpos($crit['type'], 'date') === false && strpos($crit['type'], 'moment') === false && strpos($crit['type'], 'luxon') === false) { | |
$q->orWhere($crit['origData'], "=", ""); | |
} | |
}); | |
$first = false; | |
} else { | |
$query->orWhere(function ($q) use ($crit) { | |
$q->where($crit['origData'], "=", null); | |
if (strpos($crit['type'], 'date') === false && strpos($crit['type'], 'moment') === false && strpos($crit['type'], 'luxon') === false) { | |
$q->orWhere($crit['origData'], "=", ""); | |
} | |
}); | |
} | |
break; | |
case '!null': | |
if ($data['logic'] === 'AND' || $first) { | |
$query->where(function ($q) use ($crit) { | |
$q->where($crit['origData'], "!=", null); | |
if (strpos($crit['type'], 'date') === false && strpos($crit['type'], 'moment') === false && strpos($crit['type'], 'luxon') === false) { | |
$q->where($crit['origData'], "!=", ""); | |
} | |
}); | |
$first = false; | |
} else { | |
$query->orWhere(function ($q) use ($crit) { | |
$q->where($crit['origData'], "!=", null); | |
if (strpos($crit['type'], 'date') === false && strpos($crit['type'], 'moment') === false && strpos($crit['type'], 'luxon') === false) { | |
$q->where($crit['origData'], "!=", ""); | |
} | |
}); | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment