Я написал небольшой статический метод для моего класса, который возвращает переменную $_POST
если она установлена, или NULL
противном случае. Элементы ввода в форме HTML имеют имена с дефисами, например, «имя-клиент».
Поэтому я думаю, что я мог бы получить к ним доступ, как этот $var = $_POST['customer-name']
. Но с моим методом:
public static function getPost($param) { echo $param." = ".$_POST[$param]."<br/>"; return isset($_POST[$param]) ? $_POST[$param] : NULL; }
Я не могу. И я замечаю какое-то странное поведение при добавлении некоторых выражений echo
в мой метод. Он отключает все после дефиса, поэтому я получил ошибку:
Notice: Undefined index: customer- in .. on line ..
Вот как я его тестирую:
$arr = (array)$object; $newArr = array(); foreach($arr as $key => $val) { $newKey = str_replace(get_class($object), "", $key); $newArr[$newKey] = MyObject::getPost(strtolower(get_class($object))."-".$newKey); }
И это результат моего теста:
... Notice: Undefined index: customer- in .. on line 116 customer-id = Notice: Undefined index: customer- in .. on line 116 customer-name = Notice: Undefined index: customer- in .. on line 116 customer-phonecode = ...
EDIT 1 – меня попросили ввести HTML-форму :
<form action="" method="post" class="form-horizontal" role="form"> <input type="text" name="customer-name" id="customer-name" class="form-control" placeholder="Name" required="required" autocomplete="off" /> <select id="customer-phonecode" name="customer-phonecode" class="form-control"> <option value="+123"></option> </select> </form>
EDIT 2 – Протестировано на phptester.net версии 5.2, 5.3, 5.4, 5.5 php. Получение такой же ошибки.
EDIT 3 – Протестировано по следующему сценарию. Если передать строку в качестве ключа, я получаю элемент в супер-глобальном массиве $ _POST /. Но если передать переменную, которая указывает на строку, элемент не может быть доступен
<?php $test = array('customer-test1' => 1, 'customer-test2' => 2); function getPost($param) { global $test; $newParam = (string)$param; echo $param." = ".$test[$newParam]."<br/>"; return isset($test[$newParam]) ? $test[$newParam] : NULL; } class Customer { private $test1; private $test2; function __construct() { } } $object = new Customer(); $arr = (array)$object; $newArr = array(); foreach($arr as $key => $val) { $newKey = str_replace(get_class($object), "", $key); $newArr[$newKey] = getPost(strtolower(get_class($object))."-".$newKey); }
Может ли это быть ошибкой PHP?
Это может быть ограничение PHP – при использовании суперглобалов, таких как $ _POST, происходят некоторые «магические» вещи. PHP преобразует имена элементов формы разными способами, например
<input type="text" name="hello[mate]" />
Будет доступен как $ _POST ['hello'] ['mate'], потому что имена форм обрабатываются как переменные. Поэтому использование дефиса обычно не является хорошей идеей, потому что они не допускаются в именах переменных и, вероятно, вмешиваются здесь. Я бы посоветовал использовать только символы, которые разрешены для переменных в PHP, и заменять тире с символами подчеркивания.
Таким образом, проблема заключалась в том, что объект каста для массива добавляет нулевые символы в ключи массива. Это не просто имя класса + имя свойства. Это то, как PHP управляет свойствами частного класса при кастинге.
$object = new Customer(); $arr = (array)$object; print_r(array_map("addslashes", array_keys($arr)));
Выходы:
Array ( [0] => \0Customer\0test1 [1] => \0Customer\0test2 )
Я не уверен, почему var_dump()
не показывает эти нулевые байты. Возможно, это мой следующий вопрос. Таким образом, эти нули были все еще в моем аргументе статического метода. Но почему PHP останавливается сразу после тире / дефиса?
В PHP мы можем просто написать:
$Tmp= 'hehe';
Но для того же самого в C мы использовали бы следующий код:
Char Tmp [4]; Tmp [0] = 'h'; Tmp [1] = 'e'; Tmp [2] = 'h'; Tmp [3] = 'e'; Tmp [4] = '\0';
C обрабатывает строки как массивы символов, для этого нужен способ определения последнего символа строки. Это делается с использованием нулевого байта. Нулевой байт пожертвован \ 0 в C. Поэтому, когда программа запускается, он начинает считывать строку с первого символа до тех пор, пока не будет достигнут нулевой байт. Это создает проблему. Как известно, PHP также реализуется в C. Это может стать проблемой, поскольку некоторые функции в PHP могут обрабатывать входную строку, поскольку они обрабатываются C.
Источники: # 71673 , null-byte-injection-php
EDIT 1: добавлено решение
Решение заключается в замене символов «\ 0», а также имени класса ""
в моем цикле foreach:
foreach($arr as $key => $val) { $newKey = str_replace(array(get_class($object), "\0"), "", $key); $newArr[$newKey] = getPost(strtolower(get_class($object))."-".$newKey); }