【问题标题】:Sort object(SimpleXMLElement) php排序对象(SimpleXMLElement)php
【发布时间】:2013-12-18 20:03:30
【问题描述】:

我正在尝试找到一种方法来对 SimpleXMLElement 中的数组进行排序。我想按可以从 event_start_dt 获得的开始时间进行排序。我还想按房间 ID 排序作为一个单独的过程。目前该数组按 object(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 和 asort 但都没有让它与任何一种方法一起使用。

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 工作: 我得到: usort() 期望参数 1 是数组、给定对象或 null。

$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"
        }
    } }

请求 print_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" 
}

【问题讨论】:

  • usort() 应该在一个单独的数组上工作,你到底尝试了什么?
  • 要记住的关键是SimpleXMLElement 不是一个数组,它是一个对象(var_dump 非常具有误导性)。它不能直接排序,因为它代表的是 XML 文件的实际结构,而不仅仅是其数据的副本。
  • 我添加了我尝试过的一种 usort 方法。我无法通过 $array['reservation'][$i]['event_start_dt'] 获取数据,但我可以通过 $array->event_start_dt 获取数据。
  • 在这篇文章中查看接受的答案:stackoverflow.com/questions/15604459/…

标签: php sorting simplexml usort


【解决方案1】:

您必须使用 json encode decode 将 frist in 转换为 xml 到数组

$xml_array = json_decode(json_encode((array)$xml), TRUE);

你会得到数组列表......然后你可以使用 strtotime 函数根据日期进行排序。

【讨论】:

    【解决方案2】:

    使用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

    【讨论】:

    • 应用此方法时出错。参数 #4 应该是这一行的数组或排序标志:array_multisort($dateTime,SORT_ASC,SORT_STRING,$rez->reservation);
    • @sloga 您的预订是不是数组??我的意思是 $rez->reservation
    【解决方案3】:

    在对数据进行排序之前,您需要创建一个数组,其中包含要排序的单独项目作为其值。从您的调试输出来看,这些是输入 XML 中的多个 &lt;reservation&gt; 节点,它们是这些示例中由 $array/$this-&gt;data 表示的元素的子节点(它是否是文档的根并不重要) , SimpleXML 没有 Document 对象)。

    您的print_rvar_dump 输出显示您当前没有这样的数组,只有一个SimpleXML 对象:

    • 您的第一个示例显示 var_dump($array) 给出以 object(SimpleXMLElement)#275 (1) { 开头的输出 - 忽略后面的单词 array,这就是 var_dump 渲染对象的内部的方式。
    • 稍后,您有一个以array(1) { 开头的print_r($array); - 但这只是因为您已将真实数据包装在上面一行 ($array = array($this-&gt;data);) 的单元素数组中,并且该元素 (@987654333 @) 显示为object(SimpleXMLElement)#280 (1) { ...

    请注意,无需进一步将所有内部 SimpleXML 对象转换为数组 - 您只需要一个可排序的列表,其中包含您感兴趣的项目。我个人会使用简单而明确的 foreach 循环, 为了最大限度地提高代码可读性,尽管有“更聪明”的解决方案可供使用。

    一旦你有了一个可排序的列表,你就需要一个用于usort 的回调函数来比较它的两个参数。您所做的尝试是正确的,但指的是不存在的(在该函数中)变量$array;你需要比较的值是函数的参数,你称之为$a$b——具体来说,你想比较strtotime($a-&gt;event_start_dt)strtotime($b-&gt;event_start_dt)

    您还可以使函数更简单,因为它遵循回调的返回值应该是-101 的常见误解。事实上,它可以是任何整数,只有符号很重要——返回 -42 与返回 -999 的效果相同,即在结果数组中将项目 $a 放在 $b 之前。

    我不能轻易给出一个经过测试的例子,因为你没有提供底层的 XML 来重现你的输入(例如echo $this-&gt;data-&gt;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
    // e.g. 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>';
    

    【讨论】:

      【解决方案4】:

      我将使用此函数(来自 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');
      

      【讨论】:

      • 我不完全理解这一点...我得到 $a = strtotime($a['event_start_dt']); 的“未定义索引” $b = strtotime($b['event_start_dt']);如果更改为 $a=strtotime($arrTimes['event_start_dt']); $b = strtotime($arrTimes['event_start_dt']);我得到未定义的变量。我有 $arrTimes = xml2array($array->reservation);在 sortByTime 函数上方。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-26
      • 1970-01-01
      • 2012-02-03
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      相关资源
      最近更新 更多