Link to home
Start Free TrialLog in
Avatar of trent21
trent21

asked on

Sort by most views

Hey guys,
My problem is i have a page that displays files for download, and i need to make it so the user can select how they want to sort the downloads. One of the options is to sort them by the ones with the most hits appearing at the top and the lowest hits appearing at the bottom. I have written some code for it but it doesnt work because i am stuck with a problem, i will try and make it as clear as possible:

Example:

$table = array("1","8",6","9");
// So element 2 of $table is 8, and element 2 of $hits is 3, so table 8 has 3 hits, so i can use it when getting the file from the database.
$hits = array("7","3","4","5");

rsort($hits); // Sort $hits in order from lowest to highest, in this case 3457
$hits = array_reverse($hits); // Reverse $hits so now it is from highest to lowest, in this case 7543

But now it has scrambled things, because $hits is fine but it has been reversed, so meanwile element 2 of $table is 8 and element 2 of $hits is 5, witch is wrong, table 8 actully has the file of hits 3, but because things have been reversed in order to display highest to lowest it changes the correspondance between the 2 arrays elements. Understand? Please help... i need a simple as possible example or solution to this problem. Thanks
Avatar of cachedVB
cachedVB

are you loading this from a database? if so, you can add SORT BY hits DESC to the query
Avatar of trent21

ASKER

Yes i am loading it from a database, heres what needs to happen, i have the html to display each download stored in a database column called downloads, i store the download display html in the row named downloadtext and the hits for each download in the row hits and the id of the download in the row downloadid heres what i want to happen.

1. Get all downloads from the database and display them by the most hits at the top of the page and the lowest hits at the bottom.

So basicly do you mean, i have the query to get the hits witch is $query = "SELECT hits FROM downloads WHERE downloadid='$i'"; and $i is the download id witch has been iterated through with a for statement. So in order to get the hits and the downloadtext from the download id witch contains the most hits then display them by the highest hits first, i would do ?
Avatar of Roonaan
SELECT hits, downloadid, downloadtext FROM downloads ORDER BY hits DESC

You then iterate through the results displaying all your downloads order by hits, highest hits first.
Avatar of trent21

ASKER

Your code does not work, it simply orders them by there normal order.
ASKER CERTIFIED SOLUTION
Avatar of Roonaan
Roonaan
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
array_multisort($hits, SORT_ASC, $table);
// flag can also be SORT_DESC
Avatar of trent21

ASKER

It definetly does not work with what you gave Roonan, it displays them all in wrong error, here is what happens when i trim it down to just hits:

Hits Id Text
7
6
2
2
10
0
0
0

You can see its obviously in wrong order...
Avatar of trent21

ASKER

Here is the complete code, nevermind log.php, it has nothing to do with the problem...

<?php

include("log.php");

// Database
$db = mysql_connect("localhost","profchemx");
$que = "SELECT * FROM downloads";
$res = mysql_query($que);
$rows = mysql_num_rows($res);
$rowhits = array();
$tablenum = array();
// Database

for($i = 0; $i<($rows + 1); $i++)
{
// Database 2
$query = "SELECT hits, downloadid, downloadtext FROM downloads WHERE downloadid='$i' ORDER BY hits DESC";
$result = mysql_query($query);
$hits = mysql_result($result, 0);

$rowhits[$i] = $hits;
$tablenum[$i] = $i;

// Database 2
}


natsort($rowhits);
$rowhits = array_reverse($rowhits);

// Scan through array and print all its elements.
for($i = 0; $i<count($rowhits); $i++)
{
$quer = "SELECT downloadtext FROM downloads WHERE hits='$rowhits[$i]'";
$resul = mysql_query($quer);
$dcode = mysql_result($resul,0);

if(!$resul)
{
print mysql_error();
}
else
{
$dhits = getdownloads($i);
eval("\$dcode = \"$dcode\";");
print $dcode;

}
}
// Scan through array and print all its elements

?>

Now this code i wrote works, it displays downloads by there highest to lowest, but it displays them twice well allot of them, and we no as i said this is because the correspondance between the arrays tablenum and rowhits change when the array is reversed. Hope this can help...
Yeah, but want I ment is that you have somewhat of an overkill on your queries, because afterall you would like to show ALL downloads available and not just a selection. Therefor you could just request them from the database in the correct ordering (order by hits in your/our case). This is done by using the code I posted earlier, but I suppose I am seeing things not that clearly this early in the morning.

What I see is happening in your code is this:
1. Retrieve all downloads
2. For each download retrieve the number of hits (which are already in the results done by the query at step 1)
3. Fill 2 paralel arrays with this data.
4. Do somekind of phpbased sorting (whereas sorting on mysql-level/step 1 should do the trick.)
5. Try to rematch the relation between the two arrays at stage 3.
6. Output things.

My suggestion would then be:
1. Retrieve all downloads ordered by hits
6. Output things.

possibly you could explain things in a non code matter like the stageplan I wrote, for me?

regards

-r-
Avatar of trent21

ASKER

Thats correct friend, you understand it well... i know the order should be right, but maybe it is the server im testing it on? It is a Lycos server, although the code you posted earlier doesnt print them by the highest first. This is very weird, it should but it doesnt, trust me, i no your right but what other options can we do here? What other SQL query can i try?
You could use usort thats is easier than the way you are using now, and hopefully will work:

usort is used to execute a custom ordering using a callback function. in this callback function we compare the hits field and return -1 when a<b, 0 when a=b, 1 when a>b.

I'm not familiar with the php-limitations there might or might not be on lycos systems, so I can't say something usefull about that issue.

<?php
/*connect first*/

//query db
$q = mysql_query('select * from `downloads`);
if(mysql_error()) exit('DB flaw');

//fetch records
$records = array();
while($record = mysql_fetch_assoc($q))
  $record = $records;

//sort records
usort($records, 'sortbyhit');

echo '<div>We have '.count($records).' records.</div>';

//output data
echo '<table>';
foreach($records as $record)
{
  echo '<tr><td>'.implode('</td><td>', $record).'</td></tr>';
}
echo '</table>';
//supportive methods below
function sortbyhit($rec1, $rec2)
{
  if(!is_array($rec1) || !is_array($rec2)) return 0;

  if ($rec1['hits'])  == $rec2['hits']) {
       return 0;
   }
   return ($rec1['hits'])  < $rec2['hits']) ) ? -1 : 1;
}

?>
Or if it isnt too much trouble move to another free php/sql host (like codewarz.net, the one i use)