function deleteNews($selected) { $file = file_get_contents('news.json', true); $data=json_decode($file,true); unset($file); foreach($selected as $index){ unset($data[$index]); } $result=json_encode($data); file_put_contents('news.json', $result); echo $result; unset($result); $url="./deleteNews.php"; //redirect($url); }
Вышеупомянутая функция должна удалить запись из JSON, например:
[ { "dummy":"dummy", "dummy1":"dumy" }, { "dummy":"dummy1", "dummy1":"dummy" } ]
Но в конце функция вставляет числовые индексы в JSON, что нежелательно.
Результат подобен
[ "0": { "dummy":"dummy", "dummy1":"dumy" }, "1": { "dummy":"dummy1", "dummy1":"dummy" } ]
Как я могу получить свой оригинальный формат JSON? Я не хочу, чтобы 0 1 2 части индекса.
NB: это делает foreach
. Без foreach
, JSON создается, как ожидалось.
Попробуйте с помощью array_values:
$result = json_encode(array_values($data));
TL; DR PHP-массивы со всеми числовыми ключами , начиная с нуля , сортируются и без отверстий, являются единственным видом, который будет отображаться в массив JSON [ "square", "brackets" ]
. Все остальные виды станут словарями JSON { "curly": "brackets" }
.
Причина наблюдаемого поведения и причина, по которой array_values
видимому, array_values
проблему (и в этом случае, на самом деле), заключается в различии между массивами PHP и JSON и словарями.
Это массив PHP с непрерывными числовыми ключами:
$a = array( "Apple", "Banana", "Canteloupe" );
Это действительно
$a = array( 0 => "Apple", 1 => "Banana", 2 => "Canteloupe" );
В JSON это становится массивом :
[ "Apple", "Banana", "Canteloupe" ]
Это вместо этого массив PHP с текстовыми клавишами (хэш):
$a = array( "a" => "Apple", "b" => "Banana", "c" => "Canteloupe" );
В JSON это словарь (обратите внимание на фигурные скобки):
{ "a": "Apple", "b": "Banana", "c": "Canteloupe" }
Некоторые операции изменяют массив с массивом PHP-array-render-as-array (ARA) в -reded-as-dictionary (ARD) .
И эти операции:
Добавление ключа TEXT в массив NUMERIC.
Наличие цифровых клавиш NOT в непрерывной упорядоченной последовательности 0 … N.
Таким образом, они кажутся массивами, но на самом деле являются словарями :
$a = array ( 2 => "Canteloupe", 1 => "Banana", 0 => "Apple" ); $a = array ( 0 => "Apple", 2 => "Canteloupe" ); $a = array ( 1 => "Banana", 0 => "Apple" );
И это, наконец, причина, по которой удаление ключа, который не является последним, приведет к трэш-массиву и сделает его словарем:
0 1 2 3 => remove 3 => 0 1 2 => still an array! 0 1 2 3 => remove 2 => 0 1 3 => NOT an array! 0 1 2 3 => remove 2 => 0 1 3 => not an array => remove 3 => 0 1 => again an array!
Если бы вы подвергли массив какой-либо операции перенумерации или array_values
, вы получили бы чисто числовой массив:
/** * delete news items given their index. * * @param array $selected the list of indexes (eg [ 0, 1, 7 ]) * @return nothing */ function deleteNews(array $selected = [ ]) { try { $news = array_values( // Reorder... array_diff_key( // ...all keys... json_decode(file_get_contents('news.json', true), true), // ...in here... array_flip($selected) // ...that are not in $selected. ) ); } catch (\Exception $e) { // TODO handle errors (eg file not found and bad JSON) } try { file_put_contents('news.json', json_encode($news)); } catch (\Exception $e) { // TODO handle errors } // $url="./deleteNews.php"; // redirect($url); }
Поэтому, если ваш код удалил последние индексы вашего массива, все могло бы работать. Как только отбрасывание создало отверстие в массиве или текстовый ключ был добавлен …
То же самое касается сортировки : [ 1 => "B", 0 => "A" ]
– словарь JSON. Сортируйте его, сохраняя ассоциации ключей с [ 0 => "A", 1 => "B" ]
, и он становится массивом JSON.
Одно замечание о вашем коде: вы читаете «news.json» с include-path, установленным в true . Но затем вы сохраните его в текущем каталоге. Если у вас есть «news.json» где-нибудь еще на вашем пути, кроме текущего каталога, у вас будет два файла news.json; какой из этих двух используется, зависит от самого включения пути.
Сохранение локальных файлов, как это происходит здесь с news.json
, в порядке, но некоторые меры предосторожности часто в порядке.
В общем, лучше всего разместить такие «переменные» файлы в своем собственном каталоге (например, «./cache» или «./temp») с подходящим .htaccess
чтобы предотвратить прямое чтение / выполнение, если это не требуется, и чтобы разрешения могут быть усилены более четко.
Например, можно было бы использовать каталог «./data» и иметь файлы PHP, которые в других местах устанавливаются только для чтения для веб-сервера; и, наконец, проинструктируйте, скажем, веб-сервер Apache, чтобы этот один каталог при записи на веб-сервере не мог быть легко использован для использования в системе:
<directory "/var/www/mysite/htdocs/data"> # You CANNOT ask for /data and have a directory listing. Just in case. options -Indexes # You CANNOT save "news.php" and have it executed :-) php_flag engine off </directory>
Таким образом, даже если кто-то успел загрузить файл в вашей системе и этот файл содержал исполняемый, вредоносный PHP-код, этот код не был бы разрешен (не напрямую, по крайней мере).
function deleteNews ($ selected) {$ file = file_get_contents ('news.json', true);
$data=json_decode($file,true); unset($file); foreach($selected as $index){ unset($data[$index]); } foreach($data as $value){ $new_data[] = $value; } $result=json_encode($new_data); file_put_contents('news.json', $result); echo $result; unset($result); $url="./deleteNews.php";
с$data=json_decode($file,true); unset($file); foreach($selected as $index){ unset($data[$index]); } foreach($data as $value){ $new_data[] = $value; } $result=json_encode($new_data); file_put_contents('news.json', $result); echo $result; unset($result); $url="./deleteNews.php";
не$data=json_decode($file,true); unset($file); foreach($selected as $index){ unset($data[$index]); } foreach($data as $value){ $new_data[] = $value; } $result=json_encode($new_data); file_put_contents('news.json', $result); echo $result; unset($result); $url="./deleteNews.php";
с$data=json_decode($file,true); unset($file); foreach($selected as $index){ unset($data[$index]); } foreach($data as $value){ $new_data[] = $value; } $result=json_encode($new_data); file_put_contents('news.json', $result); echo $result; unset($result); $url="./deleteNews.php";
// перенаправление ($ URL); }