格式化MySQL查询的结果,就好像它是从控制台运行一样

时间:2011-01-04 18:14:32

标签: php mysql zend-framework formatting

我正在编写一个快速而脏的报告脚本,用于查询报告并通过电子邮件发送结果。使用MySQL控制台时,结果位于格式良好的表中:

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

使用PHP获取结果时,是否有一种简单的方法可以复制此格式?显然,我可以通过编写自己的报告格式化程序来实现这一目标,但我希望能有一些更优雅的东西。

7 个答案:

答案 0 :(得分:12)

使用Console_Table PEAR包可以非常轻松地完成此操作。只需遍历MySQL结果,并向表中添加行。您可以使用Console_Table::setHeaders()方法添加列的标题,然后使用Console_Table::addRow()方法添加每一行,最后Console_Table::getTable()显示它。

PHP没有内置任何功能。如果您不想使用/编写代码来绘制控制台表,只需使用-e query通过PHP将passthru()传递给mysql。这将解决以;\G

结尾的查询
passthru("mysql -e '$query;' database_name");

答案 1 :(得分:5)

你必须自己做。

执行循环以查找每列的最大大小。然后将每行填充输出到该大小+2,并在开头和结尾添加一个空格。用|。

分隔每列

使用+和 - 创建顶部和底部。

如果不知道你用什么来获得结果,很难给出一个具体的例子。但假设你正在使用mysql_query。这是一个例子。

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

那会这样做(我希望我没有错过那里的分号:))。

希望有所帮助!

答案 2 :(得分:3)

您可以使用exec或反引号,并通过php从命令行实际运行它。显然mysql命令有一个你可以使用的-H开关,它将输出HTML格式。虽然没试过,但这看起来也不错。

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

2行,没有梨包,可以为快速和脏的统计页面获得多少优雅。

答案 3 :(得分:1)

我对the answer of @ehudokai进行了优化,因此它使用较少的循环(5对9)。为了完整起见,我还添加了命令行,统计信息和错误输出:

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

<强>实施例

选择

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)

错误:

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

更新

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

答案 4 :(得分:1)

在mfonda的答案基础上,您现在可以轻松地使用作曲家加载Console_Table pear packagehttps://packagist.org/packages/pear/console_table

<script> $(function () { $.fn.resize = function (a) { var d = Math.ceil; if (a == null) a = 200; var e = a, f = a; $(this).each(function () { var b = $(this).height(), c = $(this).width(); if (b > c) f = d(c / b * a); else e = d(b / c * a); $(this).css({ height: e, width: f }) }) }; $("#zoom1").resize(200); $('#zoom1').each(function () { var call = $(this); var src = call.attr('src'); var str = '<a href="' + src + '" class="cloud-zoom" rel="adjustX: 0, adjustY:0" />'; call.wrap(str); $(".cloud-zoom, .cloud-zoom-gallery").CloudZoom(); }); }); </script>

$ 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'], 
        ['...', '...']
    ]
);

答案 5 :(得分:0)

考虑到在PHP中从MySQL获取数据的方式,这没有任何意义。 (即:您通常以数组(mysql_fetch_array)或对象(mysql_fetch_object)的形式一次获取数据行。)

因此,您需要编写自己的hack以获取所有行并以此方式格式化输出。 (也就是说,抓取数据并将其作为HTML表输出应该是微不足道的 - 如果使用mysql_fetch_array等,可以通过array_keys获取字段名称。)

答案 6 :(得分:0)

听起来你只需要使用任何一个exec方法或反引号。我不确定'\ G'的东西......但是,我几个月前发布了一个名为query2Table()的php函数@ http://www.logicwizards.net/php-query2table - 基于我多年来一直在回收的函数。我有一堆多年来积累的:query2xml,query2excel,query2json等。我想我还有旧的perl&amp; asp版本也在某处。

基本上,在我的解决方案中,您可以将查询字符串传递给它,并使用从结果中获取的列名作为表的标题行动态吐出一个html表。它也会增长以填充它继承的容器对象的宽度。

  query2table("select * from table;");

我有一个更新的版本query2AjaxTable(),它在一个类中很好地包装了所有内容并添加了jQuery排序&amp;动画 - 但尚未准备好发布。

如果我的愚蠢的小功能对你没有帮助,那么在你的困境中,也许别人会觉得它很有用......