Question

I'm trying to load data from database and display it in table like here:

http://img196.imageshack.us/img196/1857/cijene.jpg

In database I have two tables:

cities (id, name)
prices (id, city1_id, city2_id, price)

For example, the printed table for 4 cities would look like this:

<table>
 <tr>
  <td>city1</td>
  <td> </td>
  <td> </td>
  <td> </td>
 </tr>

 <tr>
  <td> price_city1-city2</td>
  <td>city2</td>
  <td> </td>
  <td> </td>
 </tr>

 <tr>
  <td> price_city1-city3</td>
  <td> price_city2-city3</td>
  <td>city3</td>
  <td> </td>
 </tr>

 <tr>
  <td> price_city1-city4</td>
  <td> price_city2-city4</td>
  <td> price_city3-city4</td>
  <td>city4</td>
 </tr>
</table>

Does someone know what's the PHP statement to echo this kind of tables?

Was it helpful?

Solution

// This single query gets all required data
// NOTE: this query assumes that your price data is entered
//   such that from_city always alphabetically precedes to_city!
$sql =
    "SELECT a.name AS from_city, b.name AS to_city, price ".
    "FROM prices ".
    "INNER JOIN cities AS a ON a.id=prices.city1_id ".
    "INNER JOIN cities AS b ON b.id=prices.city2_id";


// connect and do query
$conn = mysql_connect($host, $user, $pass);
mysql_select_db($db, $conn);
$q = mysql_query($sql, $conn);


// Stuff all data into an array for manipulation;
//   keep list of all cities mentioned
$price = array();
$cities = array();
while (($res = mysql_fetch_assoc($q)) !== false) {
    $from = $res['from_city'];
    $cities[ $from ] = true;

    $to = $res['to_city'];
    $cities[ $to ] = true;

    $price[$to][$from] = $res['price'];
}

// Invert to get alphabetical list of cities
$cities = array_keys($cities);
sort($cities);
$num = count($cities);


// some utility functions
function table($rows) {
    return '<table>'.join($rows).'</table>';
}
function row($cells) {
    return '<tr>'.join($cells).'</tr>';
}
function cell($text) {
    $text = (string) $text;
    if (strlen($text)==0)
        $text = '&nbsp;';
    return '<td>'.$text.'</td>';
}


// The data is now in the desired order;
// produce output as HTML table
$rows = array();
for ($to = 0; $to < $num; ++$to) {
    $t = $cities[$to];
    $cells = array();

    for ($from = 0; $from < $to; ++$from) {
        $f = $cities[$from];

        if isset($price[$t]) && isset($price[$t][$f])
            $text = $price[$t][$f];
        else
            $text = '';

        $cells[]= cell($text);
    }

    $cells[]= cell($t);    // add destination-label

    for ($from = $to+1; $from < $num; ++$from)   // pad to proper number of cells
        $cells[]= cell('');

    $rows[]= row($cells);
}
$html = table($rows);


// show results!
echo $html;

OTHER TIPS

I've used a very simple approach to converting the results of a query to an HTML table. I test that $query_result is true and fetch the results as an associative array...

$query_result = mysqli_query($db, $query);

if ($query_result) {

    while ($columns = mysqli_fetch_assoc($query_result)) {

        echo "<tr>\n";

        foreach ($columns as $name => $column) {
            echo "<td>";
            printf("%s",$columns[$name]);
            echo "</td>\n";
        }

        echo "</tr>\n";
    }
}

EDIT: Now I've been able to look at your table, I can see that I haven't really answered your question. The query is obviously very important. Does the question become 'how do I create a query which returns results which can be turned into a table by my simple-minded approach?'

I hope someone else has a few ideas.

This is somewhat at the edge of practicality, but I'm approaching this problem more as an exercise in "doing it right."

I would do a simple select of each table and insert in to an array:

$query1 = "SELECT * FROM cities";
$query2 = "SELECT * FROM prices";

$results1 = mysql_query( $query1 );
$results2 = mysql_query( $query2 );

while( $rows = mysql_fetch_array( $results1 ) ) $cities[] = $row['name'];
while( $rows = mysql_fetch_array( $results2 ) ) $prices[] = array(
                                                               $row['city1_id'],
                                                               $row['city2_id'], 
                                                               $row['name']
                                                            );

I would then use this to dynamically create two javascript lists:

$java_array1 = "var Cities = new Array;\n";
foreach( $cities as $key=>$city ) $java_array1 .= "Cities[$key] = \"$city\";\n";
$java_array2 = "var Prices = new Array;\n";
foreach( $cities as $key=>$price ) $java_array2 .= "Prices[$key] = new Array(
                                                                     \"{$price[0]}\",
                                                                     \"{$price[1]}\",
                                                                     \"{$price[2]}\",
                                                                  );\n";

I would next output a table with carefully crafted ids for each cell. I would use code very similar to that in the first answer, but I would give each cell a unique id of "cell-<row>-<col>".

The last thing I would do would be whip up some onload javascript which would populate the table using the appropriate pairings. My javascript is quite rusty, but it would look something like this (NOTE: pseudocode follows):

n = 1;
for( var i in cities )
{
    // set city names on the diagonal
    document.getElementById( 'cell-'&i&'-'&i ).innerHTML = names[i];
    n = n + 1;
}

for( var j in prices )
{
    // use the city IDs in the prices array (see earlier code initializing
    // prices array) to place the prices
    document.getElementById( 'cell-'&prices[1]&'-'&prices[2] ).innerHTML = prices[0];
}

I almost certainly messed up some of that javascript; use at your own risk.

This is a lot more complex than the simpler answer given above, but this is the only way I can think of doing it so that it makes "sense." Basically, with this method, you place everything where it should be, and you don't have to worry about odd tables and weird selects.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top