PHP: Недопустимое смещение строки

Мой проект с открытым исходным кодом работал очень хорошо, пока я не начал работать над ним после 6 месяцев перерыва. Обновлен до последнего XAMPP и начнет получать массу странных ошибок, один из которых:

У меня есть класс ввода, с вызывающим методом:

<?php class Input { public function __call ( $name , $arguments ) { if ( !in_array( $name, array( "post", "get", "cookie", "request", "server", "env" ) ) ) { throw new Exception( "Input::" . $name . "() not declared!" ); } $_name_of_superglobal = "_" . strtoupper( $name ); $_max_iteration_level_for_cleanup = in_array( $name, array( "server", "env" ) ) ? 1 : 10; # $arguments[0] is the index of the value, to be fetched from within the array. if ( !empty( $arguments[0] ) and array_key_exists( $arguments[0], $this->$name ) ) { return $this->$name[ $arguments[0] ]; } elseif ( !empty( $arguments[0] ) and array_key_exists( $arguments[0], $GLOBALS[ $_name_of_superglobal ] ) ) { return $this->$name[ $this->clean__makesafe_key( $arguments[0] ) ] = $this->clean__makesafe_value( $GLOBALS[ $_name_of_superglobal ][ $arguments[0] ], array(), true ); } elseif ( !empty( $arguments[0] ) and !array_key_exists( $arguments[0], $GLOBALS[ $_name_of_superglobal ] ) ) { return null; } else { if ( $this->_is_cleanup_done_for[ $name ] === true ) { return $this->$name; } $this->_is_cleanup_done_for[ $name ] = true; return $this->$name = $this->clean__makesafe_recursively( $GLOBALS[ $_name_of_superglobal ], $_max_iteration_level_for_cleanup ); } } ?> 

Этот фрагмент кода работает следующим образом: вы запрашиваете у него определенную сверхбольшую ценность, и он возвращает чистую версию, по запросу:

 <?php $input = new Input(); $server_name = $input->server("SERVER_NAME"); ?> 

Легко ли? Ну, после того, как я обновил PHP с помощью XAMPP, он просто не работает [edit: он работает, с предупреждающим сообщением] – ошибка:

 PHP Warning: Illegal string offset 'SERVER_NAME' in S:\...\kernel\input.php on line 159 

строка, соответствующая строке кода:

 return $this->$name[ $this->clean__makesafe_key( $arguments[0] ) ] = $this->clean__makesafe_value( $GLOBALS[ $_name_of_superglobal ][ $arguments[0] ], array(), true ); 

который является глупым: $_name_of_superglobal = "_SERVER" там, и $arguments[0] = "SERVER_NAME", а общее назначение – строка, которая очищается.

ЧТО МОЖЕТ БЫТЬ ПРОБЛЕМА? Я здесь полностью потерян!

Related of "PHP: Недопустимое смещение строки"

Введение

Я знаю, что на это был дан ответ, но Illegal string offset ERROR – это не единственная проблема, которую я вижу здесь. Я верю, что это лучшие способы представить гибкость, которую вы хотите, а также сохранить элементы без такой complexity и использования $GLOBALS .

Вы можете начать с рассмотрения:

  • Являются ли глобальные переменные в PHP плохой практикой? Если да, то почему?
  • Глобальные функции PHP
  • Почему глобальное состояние – дьявол, и как его избежать

Быстрый обзор

 $input = new Input(); <-- You add to initiate a class $server_name = $input->server("SERVER_NAME"); ^ ^ ^ | | | variable | | Variable | Variable 

Не уверен, что мешает вам просто использовать

  $_SERVER['SERVER_NAME'] = makeSave($_SERVER['SERVER_NAME']); ^ |- I guess this is what you want to introduce 

Успение – вы хотите феоксичность

Предположим, что вам нужна гибкость, а также рекурсия, тогда ваш вызов класса может быть таким же гибким, как:

 print_r($input->SERVER_NAME); | print_r($input['SERVER_NAME']); |----- Would Produce same result print_r($input->SERVER_NAME()); | 

Если это та гибкость, которую вы хотите, я бы __call что вы объедините __get , __call и ArrayAccess целом …

Позволяет себе представить

 $var = array(); $var["name"] = "<b>" . $_SERVER['SERVER_NAME'] . "</b>"; $var["example"]['xss'] = '<IMG SRC=javascript:alert("XSS")>'; $var["example"]['sql'] = "x' AND email IS NULL; --"; $var["example"]['filter'] = "Let's meet 4:30am Ât the \tcafé\n"; $_SERVER['SERVER_NAME'] = $var ; // Just for example 

Теперь вернемся к вашему формату

 $makeSave = new MakeSafe(MakeSafe::SAVE_XSS | MakeSafe::SAVE_FILTER); $input = new Input($_SERVER, $makeSafe); //You can print_r($input->SERVER_NAME); //Or print_r($input['SERVER_NAME']); //Or print_r($input->SERVER_NAME()); 

Все они будут выводить

 Array ( [0] => &lt;b&gt;localhost&lt;/b&gt; [1] => Array ( [0] => &lt;IMG SRC=javascript:alert(&quot;XSS&quot;)&gt; [1] => x&#039; AND email IS NULL; -- [2] => Let&#039;s meet 4:30am &#195;&#130;t the &#9;caf&#195;&#169;&#10; ) ) 

Смотрите Live DEMO

Изменен класс INPUT

 class INPUT implements \ArrayAccess { private $request = array(); private $makeSafe; public function __construct(array $array, MakeSafe $makeSafe) { $this->request = $array; $this->makeSave = $makeSafe; } function __get($offset) { return $this->offsetGet($offset); } function __call($offset, $value) { return $this->offsetGet($offset); } public function setRequest(array $array) { $this->request = $array; } public function offsetSet($offset, $value) { trigger_error("Error: SUPER GLOBAL data cannot be modified"); } public function offsetExists($offset) { return isset($this->request[$offset]); } public function offsetUnset($offset) { unset($this->request[$offset]); } public function offsetGet($offset) { return isset($this->request[$offset]) ? $this->makeSave->parse($this->request[$offset]) : null; } } с class INPUT implements \ArrayAccess { private $request = array(); private $makeSafe; public function __construct(array $array, MakeSafe $makeSafe) { $this->request = $array; $this->makeSave = $makeSafe; } function __get($offset) { return $this->offsetGet($offset); } function __call($offset, $value) { return $this->offsetGet($offset); } public function setRequest(array $array) { $this->request = $array; } public function offsetSet($offset, $value) { trigger_error("Error: SUPER GLOBAL data cannot be modified"); } public function offsetExists($offset) { return isset($this->request[$offset]); } public function offsetUnset($offset) { unset($this->request[$offset]); } public function offsetGet($offset) { return isset($this->request[$offset]) ? $this->makeSave->parse($this->request[$offset]) : null; } } 

Сделайте способ сохранения классом

 class MakeSafe { const SAVE_XSS = 1; const SAVE_SQL = 2; const SAVE_FILTER_HIGH = 4; const SAVE_FILTER_LOW = 8; const SAVE_FILTER = 16; private $options; function __construct($options) { $this->options = $options; } function escape($value) { if ($value = @mysql_real_escape_string($value)) return $value; $return = ''; for($i = 0; $i < strlen($value); ++ $i) { $char = $value[$i]; $ord = ord($char); if ($char !== "'" && $char !== "\"" && $char !== '\\' && $ord >= 32 && $ord <= 126) $return .= $char; else $return .= '\\x' . dechex($ord); } return $return; } function parse($mixed) { if (is_string($mixed)) { $this->options & self::SAVE_XSS and $mixed = htmlspecialchars($mixed, ENT_QUOTES, 'UTF-8'); $this->options & self::SAVE_SQL and $mixed = $this->escape($mixed); $this->options & self::SAVE_FILTER_HIGH and $mixed = filter_var($mixed, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH); $this->options & self::SAVE_FILTER_LOW and $mixed = filter_var($mixed, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_LOW); $this->options & self::SAVE_FILTER and $mixed = filter_var($mixed, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_LOW); return $mixed; } if (is_array($mixed)) { $all = array(); foreach ( $mixed as $data ) { $all[] = $this->parse($data); } return $all; } return $mixed; return $this->final; } } 

Вывод

Я сказал, что знаю, что на это был дан ответ, но я надеюсь, что это поможет кому-то еще не писать такой код, как ваш …

PS: Это также зафиксировало ваш PHP Предупреждение: неправильное смещение строки ERROR

Я нашел здесь свой ответ. По-видимому, линия

 return $this->$name[ $this->clean__makesafe_key( $arguments[0] ) ] = $this->clean__makesafe_value( $GLOBALS[ $_name_of_superglobal ][ $arguments[0] ], array(), true ); 

должен выглядеть следующим образом:

 return $this->{$name}[ $this->clean__makesafe_key( $arguments[0] ) ] = $this->clean__makesafe_value( $GLOBALS[ $_name_of_superglobal ][ $arguments[0] ], array(), true ); 

из-за приоритета.