A
A
alex_maldinsky2018-11-12 11:45:45
Yii
alex_maldinsky, 2018-11-12 11:45:45

PHP Search operators how to use?

Good afternoon. Please tell me how to properly split and prepare a string using search operators.
Operators:

"текст"   - искать этот текст;
!слово   - искать записи без этого слова;
=слово  - искать точную словоформу;
слово | слово   - искать или одно или другое

Everything outside or inside these operators needs to be escaped so as not to break the request.
I threw in this crooked version:
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);
    }

But it is not possible to process crooked errors and they break the request. For example: Hello "!"
How to be?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
X
xmoonlight, 2018-11-12
@xmoonlight

1. Recognize tokens correctly.
2. We process the result of logical expressions in accordance with the priorities of operations.
Your item 1 is not fulfilled!

A
alex_maldinsky, 2018-11-15
@alex_maldinsky

Um, maybe someone else can suggest something?
While there is this option:

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;
    }

But the problem is when there are no more words in the line except for the "not" condition, for example:
!Hi
!Hi "

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question