where(function ($q) use ($cols, $like) { $first = true; foreach ($cols as $col) { if (self::hasJoin($col)) { $exp = explode('.', $col); if (sizeof($exp) > 2) { if ($first){ $whereHas = 'whereHas'; }else{ $whereHas = 'orWhereHas'; } $q->$whereHas ($exp[0], function ($q) use ($exp, $like) { return $q->whereHas($exp[1], function ($q2) use ($exp, $like) { return $q2->whereRaw(self::foldedLikeSql($exp[2]), [$like]); }); }); } else { if ($first){ $whereHas1 = 'whereHas'; }else{ $whereHas1 = 'orWhereHas'; } $q->$whereHas1 ($exp[0], function ($q) use ($exp, $like) { return $q->whereRaw(self::foldedLikeSql($exp[1]), [$like]); }); } } else { if ($first){ $where = 'whereRaw'; }else{ $where = 'orWhereRaw'; } $q->$where(self::foldedLikeSql($col), [$like]); } if ($first) { $first = false; } } }); } private static function foldedLikeSql(string $column): string { return PersianText::sqlFoldExpr('lower(`'.$column.'`)').' like ?'; } public static function hasJoin($col) { return sizeof(explode('.', $col)) > 1; } }