Сохранение массивов JSON при сортировке

у меня есть два массива JSON, поступающие с внешнего веб-сайта. Я сортирую и объединяю два массива, декодирую их, а затем сортирую их от самого высокого до самого низкого по идентификатору.

В настоящее время, когда опция "алфавитный" нажата,?sort=alphabetical добавляется в конец URL-адреса, и когда страница закончит перезагрузку, массивы JSON снова декодируются и объединяются.

Это не мой желаемый результат: я не хочу, чтобы массивы JSON были декодированы и объединены снова, когда опция нажал-я просто хочу, чтобы уже декодированные и Объединенные массивы JSON были отсортированы в алфавитном порядке.


массивы:

$homepage = array();  

$homepage[]= '{  
   "info":{  
      "collection":[  
         {  
            "Name":"Charlie",
            "ID":"7"
         },
         {  
            "Name":"Emma",
            "ID":"9"
         }
      ]
   }
}';  

$homepage[] = '{  
   "info":{  
      "collection":[  
         {  
            "Name":"Bob",
            "ID":"5"
         }
      ]
   }
}';

сортировка:

$data = array();
foreach ($homepage as $homepage2) {
    $tmp=json_decode($homepage2, false);
    $data = array_merge($data,$tmp->info->collection);
}

if(!empty($_GET['sort']) && $_GET['sort'] == 'alphabetical') {
    usort($data, function ($a, $b) {
        return strcmp($a->Name, $b->Name);
    });
}else{
    usort($data, function ($a, $b) {
        return $b->ID - $a->ID;
    });
}

echo'
<select onchange="location.href = this.value;">
    <option value="example.php?sort=alphabetical">Alphabetical</option>
</select>
';

foreach($data as $key) {
    echo'
    <a href="test.com">
    <p>'.$key->ID.'</p>
    <p>'.$key->Name.'</p>
    </a>
    ';
}  

3 ответов


вы можете использовать JavaScript для сортировки по щелчку и использовать PHP только для передачи ему JSON.

после того, как вы предоставили структуру HTML, в которой хотите отобразить список, я обновил этот ответ, чтобы использовать div элементы для записей и p элементы для полей.

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

вот код PHP:

<?php

$homepage = array();  

$homepage[]= '{  
   "info":{  
      "collection":[  
         {  
            "Name":"Charlie",
            "ID":"13"
         },
         {  
            "Name":"Emma",
            "ID":"9"
         }
      ]
   }
}';  

$homepage[] = '{  
   "info":{  
      "collection":[  
         {  
            "Name":"Bob",
            "ID":"10"
         }
      ]
   }
}';

$data = array();
foreach ($homepage as $homepage2) {
    $tmp=json_decode($homepage2, false);
    $data = array_merge($data,$tmp->info->collection);
}

?>

<div id="container"></div>

<button id="sort1">Alphabetical</button>
<button id="sort2">High to Low</button>

<script>
    var collection = <?=json_encode($data)?>;

    function populate(compareFunc) {
        collection.sort(compareFunc);
        var container = document.getElementById('container');
        container.innerHTML = '';
        collection.forEach(function (key) {
            var div = document.createElement("div");
            div.className = "inventory";
            var span = document.createElement("span");
            span.textContent = key.ID;
            div.appendChild(span);
            span = document.createElement("span");
            span.textContent = key.Name;
            div.appendChild(span);
            container.appendChild(div);
        });
    }

    var populateById = populate.bind(null, function (a, b) {
        return a.ID - b.ID;
    });

    var populateByName = populate.bind(null, function (a, b) {
        return a.Name.localeCompare(b.Name);
    });

    document.getElementById("sort1").addEventListener('click', populateByName);
    document.getElementById("sort2").addEventListener('click', populateById);
    document.addEventListener('DOMContentLoaded', populateById);

</script>

для выборки данных результатом будет следующий JavaScript / HTML, который вы можете проверить здесь:

var collection = [{"Name":"Charlie","ID":"13"},{"Name":"Emma","ID":"9"},{"Name":"Bob","ID":"10"}];

function populate(compareFunc) {
    collection.sort(compareFunc);
    var container = document.getElementById('container');
    container.innerHTML = '';
    collection.forEach(function (key) {
        var div = document.createElement("div");
        div.className = "inventory";
        var span = document.createElement("span");
        span.textContent = key.ID;
        div.appendChild(span);
        span = document.createElement("span");
        span.textContent = key.Name;
        div.appendChild(span);
        container.appendChild(div);
    });
}

var populateById = populate.bind(null, function (a, b) {
    return a.ID - b.ID;
});

var populateByName = populate.bind(null, function (a, b) {
    return a.Name.localeCompare(b.Name);
});

document.getElementById("sort1").addEventListener('click', populateByName);
document.getElementById("sort2").addEventListener('click', populateById);
document.addEventListener('DOMContentLoaded', populateById);
span { margin-left: 5px }
div.inventory { border-bottom: 1px solid gray }
<div id="container"></div>

<button id="sort1">Alphabetical</button>
<button id="sort2">High to Low</button>

обратите внимание, что я дал три элемента разные значения ID, чем в вашем вопросе, так как в противном случае порядок сортировки будет одинаковым для ID и Name.

С помощью таблиц: альтернатива

есть хорошие библиотеки JavaScript, которые дают гораздо больше возможностей для представления наборов данных. Вот пример использования jQuery с DataTables:

var collection = [{"Name":"Charlie","ID":"13"},{"Name":"Emma","ID":"9"},{"Name":"Bob","ID":"5"}];

function populate() {
  var tbody = $('#collection>tbody');
  collection.forEach(function (key) {
    var row = $('<tr>');
    row.append($('<td>').text(key.ID));
    row.append($('<td>').text(key.Name));
    tbody.append(row);
  });
}

$(document).ready(function(){
  populate();
  $('#collection').DataTable();
});
<script src="http://code.jquery.com/jquery-1.12.3.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css">
<script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>

<table id="collection">
    <thead>
        <tr><th>ID</th><th>Name</th></tr>
    </thead>
    <tbody/>
</table>

фактический код даже меньше (не считая включенной библиотеки), чем чистое решение JavaScript было бы с базовой таблицей. Но у этого есть сортировка вверх и вниз, фильтрация, разбиение на страницы, хорошие стили ...


для этого ответа есть несколько альтернатив, поэтому я представлю простой:

отправить данные уже отсортированы, по умолчанию, если пользователь ничего не выбирал. Затем установите функцию, которая сортирует данные по мере необходимости и перерисовывает таблицы/divs/все, что вы используете для их представления.

Как пример:

function sortAlpha(){
   for each (stuff in data){
      document.getElementById("aTable").textContent=data.StringRepresentation;
   }
}

затем функция для sortSize, sortEtc и т. д... в каждой функции вы очищаете содержимое div и заполняете его снова. Таким образом, вы не необходимо запросить новый контент с серверов

getElementById документация


существует несколько решений, в которых вы можете достичь желаемых результатов.

если вы хотите, это чисто PHP кстати, что вы можете сделать, это сохранить данные в PHP-сессиями и повторите их по мере необходимости.

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

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

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

вы можете сделать другую функцию, которая вернет true для всех случаев, когда приложение должно повторно извлечь resultset из внешнего источник.

Я написал псевдо-код, чтобы вы поняли, что я пытаюсь передать,

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

function hasToRefreshResult() {
        if(/* CERTAIN CONDITIONS */) {
            return true;
        }
        return false;
    }

пару функций для получения данных из локального/внешнего источника в соответствии с переданным параметром:

    function getResultArray($getdatafromlocal) {
        if(!hasToRefreshResult() && $getdatafromlocal && array_key_exists("filertereddata",$_SESSION) && isset($_SESSION["filertereddata"])) {
            $data=$_SESSION["filertereddata"];
        } else {
            $data=getDataFromExternalURL();
        }

        if(!empty($_GET['sort']) && $_GET['sort'] == 'alphabetical') {
            usort($data, function ($a, $b) {
                return strcmp($a->Name, $b->Name);
            });
        } else {
            usort($data, function ($a, $b) {
                return $b->ID - $a->ID;
            });
        }

        return $data;
    }

    function getDataFromExternalURL() {
        /*****
           YOUR LOGIC TO GET DATA FROM EXTERNAL URL;
         *****/

        $data = array();
        foreach ($homepage as $homepage2) {
            $tmp=json_decode($homepage2, false);
            $data = array_merge($data,$tmp->info->collection);
        }
        $_SESSION["filertereddata"]=$data;
        return $data;
    }

Я надеюсь, что это решит вашу проблему строго с помощью PHP.

Также не забудьте написать session_start(); в верхней части PHP file вы будете использовать эти функции.