Order by date without a database?

Hi,

** edit - just noticed this got in to application design somehow when it should be in the main php forum **

My php is quite rusty, I’m hoping there’s an easy answer to this one that I just don’t know about.

I have a situation where I need to store some data from various feeds (twitter,facebook,rss and some custom xml) and then display them in order of most recent in an unordered list. Problem is i’m told that I don’t have the luxury of a database…which would make this an easy task.

What I’m currently doing is storing everything, including a timestamp of when the item was created, in seperate xml files (one for each feed) and then pulling these in using php and building a html fragment containining the ul and li’s etc - which can then be pulled in to the page using ajax.

Problem is I’m really not sure how to go about ordering these by date. I’m using simplexml to read in each feed seperately from the stored xml so currently i have a bunch of seperate arrays containing the xml node info. I could easily make it so that all info from each xml is in one array…but my question is how do I loop through that array and order them by date that they were created?

Take a look at [fphp]usort[/fphp]


function timestampSorter($a, $b)
{
   if ($a['timestamp'] === $b['timestamp']) return 0;
   return $a['timestamp'] < $b['timestamp'] ? -1 : 1;
}
usort($myArray, 'timestampSorter');

You would do this ~after~ you’ve merged all arrays together.

Why use XML for this BTW? It sounds like a nice job for a NoSQL database :slight_smile:

Hi, thanks so much for the reply - think this will be perfect for my problem!

Reason for using XMl is that I’ve been told I can’t have access to a database for this project!

Thanks again

Not even sqlite, bundled with PHP5?

I’d go for MySQL too…

Hi again, I’m having trouble thinking of a good way to sort an array with 30 or so entries and that has a nested structure like this:

Array
(
    [0] => Array
        (
            [time] => SimpleXMLElement Object
                (
                    [0] => Wed Apr 28 08:51:03 +0000 2010
                )

            [timestamp] => 1272444663
            [title] => SimpleXMLElement Object
                (
                    [0] => A static tweet here
                )

            [link] => SimpleXMLElement Object
                (
                    [0] => [Google](http://www.google.com)
                )

            [type] => SimpleXMLElement Object
                (
                    [0] => Static
                )

        )

    [1] => Array
        (
            [time] => SimpleXMLElement Object
                (
                )

            [timestamp] => 1308320969
            [title] => SimpleXMLElement Object
                (
                    [0] => a title
                )

            [link] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [isPermaLink] => false
                        )

                    [0] => [url.com: Search with Many](http://url.com/?p=206)
                )

            [type] => rss
        )

    [2] => Array
        (
            [time] => SimpleXMLElement Object
                (
                )

            [timestamp] => 1308503003
            [title] => SimpleXMLElement Object
                (
                    [0] => Happy Father’s Day
                )

            [link] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [isPermaLink] => false
                        )

                    [0] => [Profit From Customer Care](http://aurl.com/?p=209)
                )

            [type] => rss
        )

any ideas?

What code have you tried to sort it?

Despite the “use a db” calls, my experience of interleaving and sorting disparate feeds is that they may use different date formats - so you’ll need to normalize them.

PHPs strtotime function will likely come in handy to do that.

Heres something from a class which, from (my) memory, orders feeds already in a db…


#
# Utility date sorter
#

 static function cmp_pubdate( $a, $b ) {

 $a_t = strtotime( $a['pubdate'] ) ;
 $b_t = strtotime( $b['pubdate'] ) ;

 if( $a_t == $b_t ) return 0 ;

 return ($a_t > $b_t ) ? -1 : 1;

 }

Hi Cups,

Yes I’ve got them all into timestamp format using strtotime. It seems to have converted all of them without any problem.

Hi Rémon,

Well I tried to get at it using a nested foreach but it’s not the right thing to be doing. I’m trying to find another approach but I’m at a bit of a loss:

foreach ($aggregatedArray as $i) {
 //this line seems to get me to each array
so then I thought i could loop over here...but then that's only getting each date param at a time           
 foreach($i as $arr) {  
                $test = usort($arr, 'timestampSorter'); 
                print_r($arr);
	    }
     }
print_r($test);

Ahh, but that’s not how usort works :slight_smile:

Try this


function timestampSorter($a, $b) 
{ 
   if ($a['timestamp'] === $b['timestamp']) return 0; 
   return $a['timestamp'] < $b['timestamp'] ? -1 : 1; 
} 
usort($aggregatedArray, 'timestampSorter');  

No foreach needed whatsoever :slight_smile:

yeah I did try that but the reason why I tried the foreach was because the error that I was getting was :

Warning: usort() expects parameter 1 to be array, null given in

I’m definitely passing in the array you see in my previous post. But I don’t see how usort can work when my arrays are nested…don’t I need to get to the inner arrays and loop over them somehow?

No, you can apply the usort function to an array of arrays, that’s the beauty of it :slight_smile:

usort picks out two elements of the array at the time (which in your case are also arrays). It then gives these arrays to the callback function (in your case timestampSorter), and this function will then return which of the two is bigger. So it will compare the timestamp key of the first array ($a) to the timestamp key of the second array ($b) and return 0 if they’re equal, -1 if $a is smaller and 1 if $b is smaller.
It will do this for multiple arrays within the array and using the relation between different items it can figure out the relation between all items (since “bigger than” is a transitive relation).

Anyway, I suspect you either give an array that doesn’t contain what you think it does, or maybe made a typo in the array you’re passing.

It works fine here


function timestampSorter($a, $b) 
{ 
   if ($a['timestamp'] === $b['timestamp']) return 0; 
   return $a['timestamp'] < $b['timestamp'] ? -1 : 1; 
} 

$myArray=array(
  array(
     'timestamp'=>2,
     'text'=>'This is an RSS item',
  ),
  array(
     'timestamp'=>1,
     'text'=>'This is some other item',
  )
);

usort($myArray, 'timestampSorter');
var_dump($myArray);
/*
array
  0 => 
    array
      'timestamp' => int 1
      'text' => string 'This is some other item' (length=23)
  1 => 
    array
      'timestamp' => int 2
      'text' => string 'This is an RSS item' (length=19)
*/

Ah no it is working.
Thanks so much for your help on this :slight_smile: