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

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

В настоящее время, когда нажата опция "Алфавитный список", в конце URL-адреса добавляется ?sort=alphabetical, а когда страница завершила перезагрузку, массивы 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>
    ';
}  

Ответ 1

Вы можете использовать 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>

Ответ 2

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

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

В качестве быстрого примера:

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

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

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

Ответ 3

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

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

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

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

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

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

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

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

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, который вы будете использовать.