preg_match(): ошибка компиляции: недопустимый диапазон в классе символов со смещением

Заранее благодарю за то, что уделили время на помощь в этом вопросе

preg_match(): ошибка компиляции: недопустимый диапазон в классе символов по смещению 20 session.php в строке 278

Это перестало работать внезапно после нескольких месяцев работы, после обновления PHP на нашем сервере.

Вот код

    else{
     /* Spruce up username, check length */
     $subuser = stripslashes($subuser);
     if(strlen($subuser) < $config['min_user_chars']){
        $form->setError($field, "* Username below ".$config['min_user_chars']."characters");
     }
     else if(strlen($subuser) > $config['max_user_chars']){
        $form->setError($field, "* Username above ".$config['max_user_chars']."characters");
     }


     /* Check if username is not alphanumeric */
    /* PREG_MATCH CODE */

     else if(!preg_match("/^[a-z0-9]([0-9a-z_-\s])+$/i", $subuser)){        
        $form->setError($field, "* Username not alphanumeric");
     }


    /* PREG_MATCH CODE */


     /* Check if username is reserved */
     else if(strcasecmp($subuser, GUEST_NAME) == 0){
        $form->setError($field, "* Username reserved word");
     }
     /* Check if username is already in use */
     else if($database->usernameTaken($subuser)){
        $form->setError($field, "* Username already in use");
     }
     /* Check if username is banned */
     else if($database->usernameBanned($subuser)){
        $form->setError($field, "* Username banned");
     }
  }

Ответ 1

Диапазон классов символов определяется с помощью - между двумя значениями в символьном классе ([] в регулярном выражении). [0-9] означает все между 0 и 9 включительно. В регулярном выражении в вашем коде у вас есть несколько диапазонов классов символов, a-z, 0-9. Существует также один класс, который вы, вероятно, не хотели его указывать, а именно _-\s.

"/^[a-z0-9]([0-9a-z_-\s])+$/i"
                   ^^^^ 

Это, по-видимому, не считается недопустимым диапазоном символов в некоторых (большинство?) версиях PCRE (используется библиотека регулярных выражений PHP), но в последнее время она может быть изменена, и если библиотека PCRE была обновлена ​​на сервере, это может быть причиной.

Debuggex - хороший инструмент, который может помочь отлаживать ошибки (ну, сообщение об ошибке с PHP рассказало вам как строку, так и символ где ошибка была, так что..) вот так (я не аффилирован, просто фанат).

Ответ 2

Ваша ошибка зависит от вашего переводчика регулярных выражений.

Вы можете избежать дефиса, чтобы понять, как его использовать. То есть, используя \- вместо -.

Ваш окончательный код:

/^[a-z0-9]([0-9a-z_\-\s])+$/i

Ответ 3

Проблема действительно старая, но есть некоторые новые разработки, связанные с PHP 7.3 и более новыми версиями, которые необходимо охватить. Механизм PHP PCRE мигрирует на PCRE2, и версия PCRElibrary, используемая в PHP 7.3, - 10.32, и именно отсюда происходят несовместимые назад изменения :

  • API внутренней библиотеки изменилось
  • Модификатор 'S' не имеет никакого эффекта, шаблоны изучаются автоматически. Никакого реального воздействия.
  • Модификатор "X" является поведением по умолчанию в PCRE2. Текущий патч возвращает поведение к значению "X", как это было в PCRE, но, возможно, было бы лучше перейти с новым поведением и включить "X" по умолчанию. Так что в настоящее время никакого влияния тоже нет.
  • Было замечено некоторое изменение поведения из-за более нового движка Unicode. Это Unicode 10 в PCRE2 против Unicode 7 в PCRE. Некоторое изменение поведения может быть замечено с недопустимыми образцами.

Точность. в журнал изменений PHP 10.33:

  1. С установленным PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL escape-последовательностями, такими как \s которые действительны в классах символов, но не в качестве конца диапазонов, были трактуется как литералы. Примером является [_-\s] (но не [\s-_], потому что это дало ошибка в начале диапазона). Теперь выдается ошибка "Недопустимый диапазон" независимо от PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL.

До PHP 7.3 вы могли использовать дефис в символьном классе в любой позиции, если вы избежали его, или если вы поместили его "в положение, где его нельзя интерпретировать как указание диапазона". В PHP 7.3 кажется, что PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL был установлен в false. Таким образом, теперь, чтобы поместить дефис в класс символов, всегда используйте его только в начальной или конечной позициях.

Смотрите также эту ссылку:

Проще говоря,

PCRE2 более строг в проверке шаблонов, поэтому после обновления некоторые из существующих шаблонов больше не могут компилироваться.

Вот простой фрагмент, используемый в php.net

preg_match('/[\w-.]+/', ''); // this will not work in PHP7.3
preg_match('/[\w\-.]+/', ''); // the hyphen need to be escaped

Как видно из приведенного выше примера, между этими двумя строками есть небольшая, но существенная разница.

Ответ 4

У меня есть эта ошибка, и я решаю ее, делая это

Route::get('{path}','[email protected]')->where( 'path', '([A-z]+)?' );

и это работа для меня.

Ответ 5

Во-первых, Route :: get ('{path}', "HomeController @index") → где ('path', '([A-z\d-/_.] +)?');

это не работает для меня тогда, когда я пытаюсь снизу, и это происходит :-)

Route :: get ('{path}', 'HomeController @index') → где ('path', '([A-z] +)?')