@alex_maldinsky

PHP Операторы поиска, как использовать?

Добрый день. Подскажите пожалуйста как правильно разбить и подготовить строку с использованием операторов поиска.
Операторы:
"текст"   - искать этот текст;
!слово   - искать записи без этого слова;
=слово  - искать точную словоформу;
слово | слово   - искать или одно или другое


Все что вне или внутри этих операторов нужно экранировать, чтобы не сломать запрос.

Накидал вот такой кривоватый вариант:
private function getMatchWithSeparator($string){
        $separators = ['!', '"', '|', '='];

        if(substr_count($string, '"') % 2 != 0) return Yii::$app->sphinx->escapeMatchValue($string);

        $array = explode(' ', $string);

        if(count($array) == 1 && $array[0][0] === '!') return '';

        $query = [];
        foreach($array as $item){
            if(strlen($item) < 3){
                $query[] = ($item == '"')? $item: Yii::$app->sphinx->escapeMatchValue($item);
            } else {
                $first = (isset($item[0])) ? $item[0] : '';
                $second = (isset($item[1])) ? $item[1] : '';
                $last = substr($item, -1);

                if ($second == '"') {                                                                        /*   !", =" и другие*/
                    if (in_array($first, $separators) && $first != '"' && $last == '"') {
                        $str = substr(substr($item, 0, -1), 2);
                        $query[] = $first . $second . Yii::$app->sphinx->escapeMatchValue($str) . $last;
                    } elseif ($first == '"' && $last == '"') {                                              /* если слово в ковычках*/
                        $str = substr(substr($item, 0, -1), 1);
                        $query[] = $first . Yii::$app->sphinx->escapeMatchValue($str) . $last;
                    } elseif (in_array($first, $separators) && !($last == '"')) {                           /* если слово начивается с спецсимвола */
                        $str = substr($item, 2);
                        $query[] = $first . $second . Yii::$app->sphinx->escapeMatchValue($str);
                    } elseif ($last == '"') {                                                               /* если слово заканчивается ковычкой*/
                        $str = substr($item, 0, -1);
                        $query[] = Yii::$app->sphinx->escapeMatchValue($str) . $last;
                    } else {
                        $query[] = Yii::$app->sphinx->escapeMatchValue($item);
                    }
                } else {
                    if ($first == '"' && $last == '"') {                                          /* если слово в ковычках*/
                        $str = substr(substr($item, 0, -1), 1);
                        $query[] = $first . Yii::$app->sphinx->escapeMatchValue($str) . $last;
                    } elseif (in_array($first, $separators) && !($last == '"')) {                  /* если слово начивается с спецсимвола */
                        $str = substr($item, 1);
                        $query[] = $first . Yii::$app->sphinx->escapeMatchValue($str);
                    } elseif ($last == '"') {                                                     /* если слово заканчивается ковычкой*/
                        $str = substr($item, 0, -1);
                        $query[] = Yii::$app->sphinx->escapeMatchValue($str) . $last;
                    } else {
                        $query[] = Yii::$app->sphinx->escapeMatchValue($item);
                    }
                }
            }
        }
        return implode(' ',$query);
    }


Но не получается обрабатывать кривые ошибки и они ломают запрос. Например: Привет " !"

Как быть?
  • Вопрос задан
  • 294 просмотра
Пригласить эксперта
Ответы на вопрос 2
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
1. Распознаём корректно токены.
2. Обрабатываем результат логических выражений в соответствии с приоритетами операций.
У Вас п.1 - не выполнен!
Ответ написан
@alex_maldinsky Автор вопроса
Ап, может кто-то еще что-то может подсказать?
Пока есть такой вариант:
private function getMatchWithSeparator($string){
        $regexps = [
            '/="(.*?)"/',
            '/!"(.*?)"/',
            '/"(.*?)"/',
            '/!(.*?) /',
            '/=(.*?) /',
            '/ (.*?) \| (.*?) /'
        ];
        $count = 0;
        $array_replace = [];
        foreach($regexps as $regexp){
            $string = preg_replace_callback(
                $regexp,
                function($matches) use (&$array_replace, &$count){
                    $count++;
                    $array_replace['str'.$count] = str_replace($matches[1], Yii::$app->sphinx->escapeMatchValue($matches[1]),$matches[0]);
                    return 'str'.$count;
                },
                $string);
        }

        $string = Yii::$app->sphinx->escapeMatchValue($string);

        foreach($array_replace as $key => $item){
            $string = str_replace($key, $item, $string);
        }

        return $string;
    }


Но проблема когда в строке нету больше слов кроме с условием "не", например:
!Привет
!Привет "
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы