2011-01-04 22 views
12

Sto scrivendo uno script di segnalazione rapido e sporco che richiede un rapporto e invia i risultati via e-mail. Quando si utilizza la console di MySQL i risultati sono in una tabella ben formattata:Formattazione dei risultati di una query MySQL come se fosse eseguita dalla console

mysql> select * from users; 
+-----------+------------+-------+ 
| firstname | city  | zip | 
+-----------+------------+-------+ 
| Maria  | Holland | 12345 | 
| Rene  | Doylestown | 65432 | 
| Helen  | Conway  | 98745 | 
+-----------+------------+-------+ 
3 rows in set (0.01 sec) 

C'è un modo semplice per replicare questo formattazione quando va a prendere i risultati con PHP? Ovviamente potrei ottenere questo risultato scrivendo il mio report formattatore ma speravo in qualcosa di un po 'più elegante.

+0

No, è necessario formattarla te stesso. Quando ottieni risultati per mysql che non usi il client mysql, stai usando php e le librerie mysql. La formattazione è qualcosa fatto dal client della riga di comando. Se vuoi la stessa formattazione, dovrai farlo tu stesso. Se vuoi aiutare a farlo, non dovrebbe essere troppo difficile. – ehudokai

+0

@ehudokai Capisco le differenze tra le librerie mysql di PHP e la console. Speravo davvero in qualcosa di più intelligente. –

+0

Capisco :) Ho scritto cosa avrebbe dovuto essere fatto nella mia risposta, ma se non ti dispiace i moduli PEAR Console_Table che @mfonda ha detto sembra che faccia la stessa cosa. – ehudokai

risposta

12

Si potrebbe fare abbastanza facilmente utilizzando il pacchetto PEAR Console_Table. Basta scorrere i risultati MySQL e aggiungere righe al tuo tavolo. È possibile utilizzare il metodo Console_Table::setHeaders() per aggiungere le intestazioni per le colonne, quindi il metodo Console_Table::addRow() per aggiungere ciascuna riga e infine Console_Table::getTable() per visualizzarlo.

Non c'è niente di integrato in PHP per farlo. Se non si desidera utilizzare/scrivere codice per disegnare tabelle console, è sufficiente passare -e query a mysql tramite PHP utilizzando passthru(). Ciò funzionerà query terminati sia con ; e \G:

passthru("mysql -e '$query;' database_name"); 
0

Questo non ha senso tenendo presente il modo in cui si recuperano i dati da MySQL in PHP. (es .: generalmente stai recuperando una fila di dati alla volta come un array (mysql_fetch_object) o un oggetto (mysql_fetch_object).

Come tale, devi scrivere il tuo trucco per afferrare tutte le righe e formattare l'output in questo modo. (Detto questo, dovrebbe essere banale afferrare i dati e visualizzarli come tabella HTML - potresti usare i nomi dei campi tramite array_keys se usi mysql_fetch_array, ecc.)

+0

Grazie per la risposta. Sono a conoscenza di tutti i metodi di recupero e non dubito della mia capacità di creare un formattatore di tabelle che emuli la console. Sto davvero cercando una soluzione leggera e pre-costruita nativa per MySQL o PHP. Se tale opzione non esiste sarei contento di quella risposta :) –

3

Potresti usare exec o backtick ed effettivamente eseguirlo dalla riga di comando tramite php. Apparentemente il comando mysql ha uno switch -H che puoi usare, e produrrà HTML formattato. Non l'ho provato, ma potrebbe anche sembrare bello.

echo '<pre>'; 
echo `mysql -u user -ppass -e "select * from table;" database_name`; 

2 linee, senza pacchetti di pere, quanto più elegante può ottenere per una pagina di statistiche rapida e sporca.

5

quello che dovete fare da soli.

fare un ciclo per trovare la dimensione massima per ogni colonna. Quindi invia ogni riempimento di riga a quella dimensione +2 con uno spazio all'inizio e alla fine. separare ogni colonna con un | |

Utilizzare + e - per creare la parte superiore e inferiore.

È difficile dare un esempio concreto senza sapere cosa si sta utilizzando per ottenere i risultati. Ma supponendo che tu stia usando mysql_query. Ecco un esempio.

$conn = mysql_connect("localhost", "mysql_user", "mysql_password"); 
mysql_select_db("mydbname"); 
$result = mysql_query("SELECT * FROM myTable"); 
//first get your sizes 
$sizes = array(); 
$row = mysql_fetch_assoc($result); 
foreach($row as $key=>$value){ 
    $sizes[$key] = strlen($key); //initialize to the size of the column name 
} 
while($row = mysql_fetch_assoc($result)){ 
    foreach($row as $key=>$value){ 
     $length = strlen($value); 
     if($length > $sizes[$key]) $sizes[$key] = $length; // get largest result size 
    } 
} 
mysql_data_seek($result, 0); //set your pointer back to the beginning. 

//top of output 
foreach($sizes as $length){ 
    echo "+".str_pad("",$length+2,"-"); 
} 
echo "+\n"; 

// column names 
$row = mysql_fetch_assoc($result); 
foreach($row as $key=>$value){ 
    echo "| "; 
    echo str_pad($key,$sizes[$key]+1); 
} 
echo "|\n"; 

//line under column names 
foreach($sizes as $length){ 
    echo "+".str_pad("",$length+2,"-"); 
} 
echo "+\n"; 

//output data 
do { 
    foreach($row as $key=>$value){ 
     echo "| "; 
     echo str_pad($value,$sizes[$key]+1); 
    } 
    echo "|\n"; 
} while($row = mysql_fetch_assoc($result)); 

//bottom of output 
foreach($sizes as $length){ 
    echo "+".str_pad("",$length+2,"-"); 
} 
echo "+\n"; 

Questo lo farebbe (spero di non essermi perso un punto e virgola :).

Spero che questo aiuti!

+0

Cosa succede se interrompo una query con \ G? L'output cambia completamente dallo stile della tabella allo stile verticale. Davvero, davvero non voglio scrivere il mio formattatore proprio come MySQL fa un ottimo lavoro. –

+0

@mikeB, se vuoi mysql, usa solo mysql. Puoi eseguire mysql da exec come altri hanno già detto. – ehudokai

0

sembra che sia necessario utilizzare uno qualsiasi dei metodi exec o backtick. Non sono sicuro del thingy di \ G, ma ho pubblicato una funzione di php chiamata query2Table() alcuni mesi fa @http://www.logicwizards.net/php-query2table - basata su una funzione che ho riciclato da anni. Ho un gruppo che ho accumulato nel corso degli anni: query2xml, query2excel, query2json, ecc.Penso di avere ancora le vecchie versioni perl & asp anche da qualche parte.

Fondamentalmente, nella mia soluzione, è sufficiente passare la stringa di query e sputare dinamicamente una tabella html utilizzando i nomi di colonna recuperati dai risultati come riga di intestazione della tabella. Cresce anche a riempire la larghezza del suo oggetto contenitore ereditato.

query2table("select * from table;"); 

Ho un più aggiornata versione query2AjaxTable(), che avvolge tutto piacevolmente in una classe e aggiunge jQuery ordinamento & animazioni - ma non è pronto per la pubblicazione ancora.

Se la mia piccola funzione sciocco non ti aiuta, nel tuo dilemma, forse qualcun altro lo troverà utile ...

+0

Link non funziona più. –

1

ho ottimizzato the answer of @ehudokai in modo che utilizza meno cicli (5 vs 9). E per completezza ho aggiunto la linea di comando, le statistiche e output di errore, anche:

<pre> 
<?php 
$db = mysqli_connect('localhost', 'my_user', 'my_password', 'my_db'); 
$start = microtime(true); 
$sql = "SELECT * FROM myTable"; 
$result = mysqli_query($db, $sql); 
$exec_time = microtime(true) - $start; 
// obtain the maximum string length of all column headings and rows 
$colwidths = array(); 
while ($row = mysqli_fetch_assoc($result)) { 
    foreach ($row as $key => $value) { 
     // heading 
     if (!isset($colwidths[ $key ])) { 
      $colwidths[ $key ] = strlen($key) + 2; 
     } 
     // rows 
     $colwidths[ $key ] = max($colwidths[ $key ], strlen($value) + 2); 
    } 
} 
echo 'mysql>' . trim($sql) . PHP_EOL; 
// SELECT, SHOW, DESCRIBE, EXPLAIN = resource 
// INSERT, UPDATE, DELETE, DROP = true 
// Error = false 
if (!is_bool($result)) { 
    if ($colwidths) { 
     mysqli_data_seek($result, 0); 
     while ($row = mysqli_fetch_assoc($result)) { 
      // create and display horizontal line and column headings 
      if (!isset($header)) { 
       $header = '| '; 
       $line = '+'; 
       foreach ($row as $key => $value) { 
        $line .= str_repeat('-', $colwidths[ $key ] + 2) . '+'; 
        $header .= str_pad($key, $colwidths[ $key ]) . ' | '; 
       } 
       echo $line . PHP_EOL; 
       echo $header . PHP_EOL; 
       echo $line . PHP_EOL; 
      } 
      // display row values 
      foreach ($row as $key => $value) { 
       echo '| ' . str_pad($value, $colwidths[ $key ] + 1); 
      } 
      echo '|' . PHP_EOL; 
     } 
     echo $line . PHP_EOL; 
    } 
    mysqli_free_result($result); 
} 
$affectedrows = mysqli_affected_rows($db); 
if ($result === false) { 
    echo PHP_EOL . 'ERROR ' . mysqli_errno($db) . ': ' . mysqli_error($db); 
} 
else if ($result === true) { 
    echo 'Query OK, ' . $affectedrows . ' rows affected (' . round($exec_time/$iterations * 1000) . ' ms)'; 
} 
else if ($affectedrows) { 
    echo $affectedrows . ' rows in set (' . round($exec_time/$iterations * 1000) . ' ms)'; 
} 
else { 
    echo 'Empty set (' . round($exec_time/$iterations * 1000) . ' ms)'; 
} 
?> 
</pre> 

Esempi

SELEZIONA

mysql>SELECT 
     topic_id, 
     MATCH(text) AGAINST('tuning') AS score 
    FROM 
     topics 
    WHERE 
     MATCH(text) AGAINST('tuning' IN BOOLEAN MODE) 
    ORDER BY 
     score DESC 
    LIMIT 10 
+----------+--------------------+ 
| topic_id | score    | 
+----------+--------------------+ 
| 153257 | 5.161948204040527 | 
| 17925 | 4.781417369842529 | 
| 66459 | 4.648380279541016 | 
| 373176 | 4.570812702178955 | 
| 117173 | 4.55166482925415 | 
| 167016 | 4.462575912475586 | 
| 183286 | 4.4519267082214355 | 
| 366132 | 4.348565101623535 | 
| 95502 | 4.293642520904541 | 
| 29615 | 4.178250789642334 | 
+----------+--------------------+ 
10 rows in set (141 ms) 

Errore:

mysql>SELECT * WHERE 1=1 

ERROR 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 1=1' at line 1 

UPDATE

mysql>UPDATE topics_search SET topic_id = topic_id WHERE topic_id = 2 
Query OK, 0 rows affected (0 ms) 
1

Sulla risposta di mfonda, si può molto facilmente caricare il Console_Table pear package con il compositore oggi: https://packagist.org/packages/pear/console_table

$ composer require pear/console_table

<?php 
//Suppress E_DEPRECATED errors for statically calling a non-static method (this package is pretty old!) 
error_reporting(E_ALL & ~E_DEPRECATED); 
require __DIR__ . '/vendor/autoload.php'; 

//echo "<pre>"; #uncomment this line if running script in a browser 

//The class isn't namespaced so just call it directly like so: 
echo Console_Table::fromArray(
    ['column', 'headings'], 
    [ 
     ['1st row', 'values'], 
     ['2nd row', 'values'], 
     ['...', '...'] 
    ] 
); 

Questo uscite:

+---------+----------+ 
| column | headings | 
+---------+----------+ 
| 1st row | values | 
| 2nd row | values | 
| ...  | ...  | 
+---------+----------+ 
Problemi correlati