Я пытаюсь найти способ сортировки моего массива из SimpleXMLElement. Я хотел бы отсортировать по времени начала, которое я могу получить от event_start_dt. Я также хотел бы сортировать по номеру комнаты как отдельный процесс. В настоящее время массив упорядочен по объекту (SimpleXMLElement) #. Вот массив var_dump ($ array):
object(SimpleXMLElement)#275 (1) { ["reservation"]=> array(3) { [0]=> object(SimpleXMLElement)#287 (28) { ["reservation_id"]=> string(7) "8644894" ["event_start_dt"]=> string(25) "2013-12-02T12:00:00-08:00" ["event_end_dt"]=> string(25) "2013-12-02T13:00:00-08:00" ["event_id"]=> string(6) "314147" ["event_name"]=> string(24) "Practice" ["room_id"]=> string(3) "202" } [1]=> object(SimpleXMLElement)#288 (28) { ["reservation_id"]=> string(7) "8595185" ["event_start_dt"]=> string(25) "2013-12-02T08:00:00-08:00" ["event_end_dt"]=> string(25) "2013-12-02T09:00:00-08:00" ["event_id"]=> string(6) "314005" ["event_name"]=> string(24) "Meeting" ["room_id"]=> string(3) "207" } [2]=> object(SimpleXMLElement)#289 (28) { ["reservation_id"]=> string(7) "8718654" ["event_start_dt"]=> string(25) "2013-12-02T10:00:00-08:00" ["event_end_dt"]=> string(25) "2013-12-02T11:00:00-08:00" ["event_id"]=> string(6) "315811" ["event_name"]=> string(20) "Maintenance" ["room_id"]=> string(3) "202" } } }
Я пробовал использовать и асорт, но не получил его для работы с любым методом.
метод usort:
function sortByTime($a, $b){ $a = strtotime($array->event_start_dt); $b = strtotime($array->event_start_dt); if ($a==$b) return 0; return ($a < $b) ?-1 : 1; } usort($arrTimes, 'sortByTime'); var_dump($arrTimes);
Попытка кода ниже дает мне предупреждение: usort () ожидает, что параметр 1 будет массивом, указанным объектом.
foreach ($rez->reservation as $value){ $var1 = $value->space_reservation->space_name; $var2 = substr($value->event_start_dt,11,5); } sort_obj_arr($value,$var1,SORT_DESC); echo "<pre>SORTED "; print_r($value); echo "</pre>"; function sort_obj_arr(& $arr, $sort_field, $sort_direction) { $sort_func = function($obj_1, $obj_2) use ($sort_field, &$sort_direction) { if ($sort_direction == SORT_ASC) { return strnatcasecmp($obj_1->$sort_field, $obj_2->$sort_field); } else { return strnatcasecmp($obj_2->$sort_field, $obj_1->$sort_field); } }; usort($arr, $sort_func); }
У меня есть массив из моего контроллера, но я не могу заставить его работать: я получаю либо: usort () ожидает, что параметр 1 будет массивом, заданным объектом или нулем.
$array = array($this->data); print_r($array); array(1) { [0]=> object(SimpleXMLElement)#280 (1) { ["reservation"]=> array(3) { [0]=> object(SimpleXMLElement)#287 (28) { ["reservation_id"]=> string(7) "8644894" ["event_start_dt"]=> string(25) "2013-12-02T12:00:00-08:00" ["event_end_dt"]=> string(25) "2013-12-02T13:00:00-08:00" ["event_id"]=> string(6) "314147" ["event_name"]=> string(24) "Practice" ["room_id"]=> string(3) "202" } [1]=> object(SimpleXMLElement)#288 (28) { ["reservation_id"]=> string(7) "8595185" ["event_start_dt"]=> string(25) "2013-12-02T08:00:00-08:00" ["event_end_dt"]=> string(25) "2013-12-02T09:00:00-08:00" ["event_id"]=> string(6) "314005" ["event_name"]=> string(24) "Meeting" ["room_id"]=> string(3) "207" } [2]=> object(SimpleXMLElement)#289 (28) { ["reservation_id"]=> string(7) "8718654" ["event_start_dt"]=> string(25) "2013-12-02T10:00:00-08:00" ["event_end_dt"]=> string(25) "2013-12-02T11:00:00-08:00" ["event_id"]=> string(6) "315811" ["event_name"]=> string(20) "Maintenance" ["room_id"]=> string(3) "202" } } }
Запрос на печать_r:
SimpleXMLElement Object ( [reservation] => Array(3) ( [0] => SimpleXMLElement Object ( [reservation_id] => 8604174 [event_start_dt] => 2013-12-31T06:00:00-08:00 [event_end_dt] => 2013-12-31T08:00:00-08:00 [event_id] => 314147 [event_name] => Practice [room_id] => 202 ) [1] => SimpleXMLElement Object ( [reservation_id] => 8604177 [event_start_dt] => 2013-12-31T05:00:00-08:00 [event_end_dt] => 2013-12-31T06:00:00-08:00 [event_id] => 314150 [event_name] => Meeting [room_id] => 216 ) [2] => SimpleXMLElement Object ( [reservation_id] => 8604189 [event_start_dt] => 2013-12-31T10:00:00-08:00 [event_end_dt] => 2013-12-31T11:00:00-08:00 [event_id] => 314150 [event_name] => Maintenance [room_id] => 220 ) ) ) $arrTimes = xml2array($array->reservation); var_dump($arrTimes) array(5) { ["reservation_id"]=> string(7) "8604175" ["event_start_dt"]=> string(25) "2014-01-02T06:00:00-08:00" ["event_end_dt"]=> string(25) "2014-01-02T08:00:00-08:00" ["event_id"]=> string(6) "314147" ["event_name"]=> string(24) "Practice" }
Прежде чем вы сможете сортировать данные, вам необходимо создать массив, который содержит в качестве значений отдельные элементы, которые вы хотите отсортировать. От ваших отладочных выходов это несколько узлов <reservation>
во входном XML, которые являются дочерними элементами элемента, представленного $this->data
$array
/ $this->data
в этих образцах (неважно, является ли это корнем документа или not, SimpleXML не имеет объекта Document).
Вывод print_r
и var_dump
показывает, что в настоящее время у вас нет такого массива, а только объект SimpleXML:
var_dump($array)
дающий начальный object(SimpleXMLElement)#275 (1) {
вывода object(SimpleXMLElement)#275 (1) {
– игнорировать array
слов дальше, вот как var_dump
визуализирует внутренности объекта. print_r($array);
begin array(1) {
– но это только потому, что вы обернули реальные данные в одноэлементном массиве в строке выше ( $array = array($this->data);
) и что один элемент ( $array[0]
) показывает как object(SimpleXMLElement)#280 (1) { ...
Обратите внимание, что нет необходимости идти дальше и преобразовывать все внутренние объекты SimpleXML в массивы – вам просто нужен сортируемый список, содержащий интересующие вас элементы. Я бы лично использовал простой и явный цикл foreach
для максимальной удобочитаемости кода , хотя доступны «более умные» решения.
Когда у вас есть сортируемый список, вам нужна функция обратного вызова для usort
которая сравнивает два параметра. Попытка, которую вы сделали, находится вдоль правильных строк, но относится к несуществующей (в этой функции) переменной $array
; значения, которые нужно сравнить, – это аргументы функции, которые вы назвали $a
и $b
– в частности, вы хотите сравнить strtotime($a->event_start_dt)
с strtotime($b->event_start_dt)
.
Вы также можете сделать функцию намного проще, потому что она следует за распространенным заблуждением, что возвращаемое значение обратного вызова должно быть -1
, 0
или 1
. Фактически, это может быть любое целое число, и только его значение имеет значение – возврат -42
будет иметь тот же эффект, что и возвращение -999
, а именно размещение объекта $a
перед $b
в результирующем массиве.
Я не могу легко дать пример, потому что вы не предоставили базовый XML для воспроизведения вашего ввода (например, echo $this->data->asXML();
), но основной подход, который я бы принял, был бы следующим:
// Start with an empty array, and add all the items we're interested in to it $sortable_array = array(); // Loop over all <reservation> children of the SimpleXML object $this->data // See http://php.net/manual/en/simplexml.examples-basic.php foreach ( $this->data->reservation as $reservation_node ) { // Add the individual node to our array $sortable_array[] = $reservation_node; } // Now let's sort out the callback function for the sorting // This could also be an anonymous function passed directly to usort function sort_callback_event_start($a, $b) { // $a and $b are both items in our $sortable_array, and therefore // <reservation> nodes which we expect to each have a child // called <event_start_dt> // If we convert both dates to Unix timestamps, we have two integers // to compare, and a simple subtraction gives the desired result // of <0, 0, or >0 as documented at http://php.net/usort return strtotime((string)$a->event_start_dt) - strtotime((string)$b->event_start_dt); } // Now, we have everything we need to do the actual sorting usort($sortable_array, 'sort_callback_event_start'); // $sortable_array is now sorted as desired! :D // Note that the items within it are still SimpleXML objects, // so you still need to access their properties to do something useful // eg some HTML output with the names listed in order of their start date: echo '<ol>'; foreach ( $sortable_array as $reservation_node ) { echo '<li>', (string)$reservation_node->event_name, '</li>'; } echo '</ol>';
Использовать array_multisort
foreach ($rez->reservation as $value) { $dateTime[] = $value->event_start_dt; } array_multisort($dateTime,SORT_ASC,SORT_STRING,$rez->reservation); echo "<pre>"; print_r($rez->reservation);
Проверь это. это мой код
<?php $myarray=array( 0 => array ( 'dateTime' => '2013-12-02T10:00:00-08:00', 'chanl1' => '20.10', 'chanl2' => '45.4', 'chanl3' => '', ), 1 => array ( 'dateTime' => '2013-12-02T11:00:00-08:00', 'chanl1' => '20.11', 'chanl2' => '45.4', 'chanl3' => '', ), 2 => array ( 'dateTime' => '2013-12-02T12:00:00-08:00', 'chanl1' => '20.12', 'chanl2' => '33.8', 'chanl3' => '', ), 3 => array ( 'dateTime' => '2013-12-02T09:00:00-08:00', 'chanl1' => '20.9', 'chanl2' => '33.9', 'chanl3' => '' )); foreach($myarray as $c=>$key) { $dateTime[] = $key['dateTime']; } array_multisort($dateTime,SORT_ASC,SORT_STRING,$myarray); echo "<pre>"; print_r($myarray); ?>
Выход:
Array ( [0] => Array ( [dateTime] => 2013-12-02T09:00:00-08:00 [chanl1] => 20.9 [chanl2] => 33.9 [chanl3] => ) [1] => Array ( [dateTime] => 2013-12-02T10:00:00-08:00 [chanl1] => 20.10 [chanl2] => 45.4 [chanl3] => ) [2] => Array ( [dateTime] => 2013-12-02T11:00:00-08:00 [chanl1] => 20.11 [chanl2] => 45.4 [chanl3] => ) [3] => Array ( [dateTime] => 2013-12-02T12:00:00-08:00 [chanl1] => 20.12 [chanl2] => 33.8 [chanl3] => ) )
FIDDLE
Я бы просто бросил его как массив, используя эту функцию (пример функции из php.net). Но учтите, что это не сортирует XML, а сортирует новый массив
/** * function xml2array * * This function is part of the PHP manual. * * The PHP manual text and comments are covered by the Creative Commons * Attribution 3.0 License, copyright (c) the PHP Documentation Group * * @author k dot antczak at livedata dot pl * @date 2011-04-22 06:08 UTC * @link http://www.php.net/manual/en/ref.simplexml.php#103617 * @license http://www.php.net/license/index.php#doc-lic * @license http://creativecommons.org/licenses/by/3.0/ * @license CC-BY-3.0 <http://spdx.org/licenses/CC-BY-3.0> */ function xml2array ( $xmlObject, $out = array () ) { foreach ( (array) $xmlObject as $index => $node ) $out[$index] = ( is_object ( $node ) ) ? xml2array ( $node ) : $node; return $out; }
и передать его XMLObject
$arrTimes = xml2array(YourSimpleXMLElement);
а затем используйте свою оригинальную функцию usort на новом массиве
function sortByTime($a, $b){ $a = strtotime($a['event_start_dt']); $b = strtotime($b['event_start_dt']); if ($a==$b) return 0; return ($a < $b) ? -1 : 1; }
в заключение
usort($arrTimes, 'sortByTime');
Вам нужно преобразовать frist в xml в массив с использованием json encode decode
$ xml_array = json_decode (json_encode ((массив) $ xml), TRUE);
u получит список массивов …. чем u может sory согласно дате, используя функцию strtotime.