mukadi/chartjs-builder
直接从SQL查询生成漂亮的图表(PHP)
Requires
- php: ^8.0
README
直接从SQL查询生成漂亮和完全定制的图表。mukadi/chartjs-builder库使用Chart.js显示图表,并使用PDO查询数据库中的数据。
1. 安装
运行 php composer.phar require mukadi/chartjs-builder
如果您不使用composer管理依赖(您应该使用!),您可以直接从仓库下载库,并将库自动加载文件包含到您的代码中,所有包类都将可用
require 'path-to-the-library/autoload.php';
2. 工厂
Mukadi\Chart\Factory\ChartFactory
是用于从SQL查询创建图表的主要包类。此类需要一个有效的PDO连接作为构造函数参数
use Mukadi\Chart\Factory\ChartFactory; $connection = new \PDO('sqlite:/Users/foo/Projects/bar.db'); $factory = new ChartFactory($connection);
2.1. 图表类型
一旦实例化Factory
对象,您就可以开始构建您的图表。首先要做的事情是指定您想要的图表类型,支持的类型有:
- 柱状图
- 饼图
- 极坐标面积图
- 折线图
- 环形图和
- 雷达图
- 散点图
- 气泡图
$chart = $factory ->createChartBuilder() ->asBar() // asPie(), asPolarArea(), asLine() etc... ...
2.2. 查询
一旦实例化Factory
对象,您可以为图表设置查询,该查询将生成图表
$chart = $factory ->createChartBuilder() ->asBar() ->query('SELECT COUNT(*) total, AVG(prix) prix, console FROM jeux_video GROUP BY console') // SQL query
2.3. 标签
在查询配置之后,您可以设置图表标签(显示在x轴上)
$chart = $factory ->createChartBuilder() ->asBar() ->query('SELECT COUNT(*) total, AVG(prix) prix, console FROM jeux_video GROUP BY console') // SQL query ->labels('console') // mapped to the console column # or you can provide array of predefined values ->labels(['NES', 'Game Cube', 'PSOne']) # you can also apply transformation to the labels before been displayed on the chart ->labels('console', fn($c) => strtoupper($c)) // transform all console name to uppercase
注意:气泡图和散点图不支持标签,该方法对此类图表没有影响且不会抛出错误
2.4. 数据集
$chart = $factory ->createChartBuilder() ->asBar() ->query('SELECT COUNT(*) total, AVG(prix) prix, console FROM jeux_video GROUP BY console') ->labels('console') ->dataset("Total") # dataset labels ->data('total') # dataset mapped to the "total" column ->options([ 'backgroundColor' => RandomColorFactory::randomRGBColor() ]) ->end() # you can add many datasets as you want ->dataset("Prix moyen") ->asLine() # you can set a different chart type to a dataset and create mixed chart ->data('prix') ->useRandomBackgroundColor() # dataset color helper ->end() # build and return the chart ->build() ->getChart() ;
散点图和气泡图的行为不同,以下是构建此类图表的方法
$scatter = $factory ->createChartBuilder() ->asScatter() ->query("SELECT prix, nbre_joueurs_max, console from jeux_video jv where console = :console") ->dataset("Prix") ->data("nbre_joueurs_max", "prix") # you have to specify the values mapped to the X and Y axis in that order ->useRandomBackgroundColor(false) ->end() # build and return the chart ->build() ->getChart() ; $bubble = $factory ->createChartBuilder() ->asBubble() ->query("SELECT prix, nbre_joueurs_max, ventes from jeux_video jv where console = :console") ->dataset("Prix") ->data("nbre_joueurs_max", "prix", "ventes") # you have to specify the values mapped to the X, Y axis and the radius in that order ->options([ 'backgroundColor' => RandomColorFactory::randomRGBColor(), ]) ->end() # build and return the chart ->build() ->getChart() ;
通过指定:获取数据的列、用作数据集标签的文本以及可选的选项数组(有关可用选项,请参阅chart.js文档)来设置数据集。对于图表标签,只需设置查询数据的列或将字符串数组直接放入其中。
2.5. 数据集辅助工具
2.6. 构建并渲染图表
最后但同样重要的是,您必须在视图中构建和渲染图表。对于构建图表,提供一个ID并设置图表类型,可选地设置一些选项(有关可用选项,请参阅chart.js文档)
# Build the chart $chart = $factory ->createChartBuilder() ... ->build() ->getChart() # or you can pass chart options like this ->getChart([ 'scales' => [ 'x' => [ 'grid' => ['offset' => true] ], ] ]) ; //You can also add or override the chart options after being built. In this example you remove the onClick behavior of legend $chart->pushOptions([ 'legend' => [ 'onClick' => null, ] ]);
对于在页面中渲染图表,只需进行echo操作
echo $chart;
别忘了在您的页面上包含库
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.2.1/chart.umd.min.js"></script> <script src="dist/mukadi.chart.min.js"></script>
就这样!
3. 高级主题
3.1. 使用参数化查询
use Mukadi\Chart\Factory\ChartFactory; $connection = new \PDO('sqlite:/Users/foo/Projects/bar.db'); $factory = new ChartFactory($connection); $chart = $factory ->createChartBuilder() ->asBar() ->query('SELECT COUNT(*) total, AVG(prix) prix, console FROM jeux_video WHERE possesseur = :possesseur GROUP BY console') # prepared statement ->labels('console') ->dataset("Total") ->data('total')->useRandomBackgroundColor() ->end() ->dataset("Prix moyen") ->data('prix')->useRandomBackgroundColor() ->end() ->build() # setting the parameters after the build() method invokation ->setParameter(':possesseur',"Kapiamba") ->getChart()
3.2. 图表定义
在构建图表时,我们可能会很快就有很多代码行污染我们的控制器/页面(特别是如果它是一个仪表板,例如)。图表定义是一种优雅的方法,可以在单独的类中构建您的图表,因此您可以得到更易于阅读的代码,并且还可以重用图表(当与参数化查询结合使用时,这是一个非常强大的功能)。
每个图表定义都必须实现Mukadi\Chart\ChartDefinitionInterface
接口(当然!:-D)
use Mukadi\Chart\ChartDefinitionBuilderInterface; class VideoGame implements ChartDefinitionInterface { public function define(ChartDefinitionBuilderInterface $builder): void { $sql = "SELECT COUNT(*) total, AVG(prix) prix, console FROM jeux_video WHERE possesseur = :possesseur GROUP BY console"; $builder ->asPolarArea() ->query($sql) ->labels('console') ->dataset("Total") ->data('total')->useRandomBackgroundColor() ->end() ->dataset("Prix moyen") ->data('prix')->useRandomBackgroundColor() ->end() ; } }
在您的控制器/页面中,您只需编写以下内容:
... $chart = $factory ->createFromDefinition(new VideoGame()) ->setParameter(':possesseur', 'Florent') ->getChart() ; # you can reuse the same definition for another owner just like this $chart2 = $factory ->createFromDefinition(VideoGame::class) # you can also use the FQCN instead of an instance ->setParameter(':possesseur', 'Michel') # different parameter value ->getChart() ;
您可以直接在图表定义中设置查询参数和图表选项
use Mukadi\Chart\ChartDefinitionBuilderInterface; class VideoGame implements ChartDefinitionInterface { public function define(ChartDefinitionBuilderInterface $builder): void { $sql = "SELECT COUNT(*) total, AVG(prix) prix, console FROM jeux_video WHERE possesseur = :possesseur GROUP BY console"; $builder ->asPolarArea() ->query($sql)->setParameter(':possesseur', 'Michel') # set the parameters value ->labels('console') ->dataset("Total") ->data('total')->useRandomBackgroundColor() ->end() ->dataset("Prix moyen") ->data('prix')->useRandomBackgroundColor() ->end() # set the chart options ->setOptions([ 'plugins' => [ "title" => [ 'display' => true, 'text' => "My video game chart", 'font' => ['size' => 16] ] ] ]) ; } }
因此,在您的控制器/页面中,只需构建您的图表
... $chart = $factory ->createFromDefinition(VideoGame::class) ->getChart() ;
3.3. 自定义定义提供者
在内部,Mukadi\Chart\Factory\ChartFactory
类使用一个实现 Mukadi\Chart\DefinitionProviderInterface
的类来通过完全限定类名(FCQN)检索图表定义,但这种实现非常简单,只能与不带参数构造函数的图表定义类一起工作。因此,如果你的定义类有依赖关系,我们必须自己构建它,并将实例提供给工厂。
在某些情况下,自己构建定义实例可能很复杂,或者当你将此任务委托给外部组件(例如依赖注入容器)时。在这种情况下,你可能希望工厂依赖于相同的组件来为你构建图表定义。
首先,实现 Mukadi\Chart\DefinitionProviderInterface
接口。
use Mukadi\Chart\ChartDefinitionInterface; use Mukadi\Chart\DefinitionProviderInterface; class MyCustomDefinitionProvider implements DefinitionProviderInterface { public function provide(string $fcqn): ChartDefinitionInterface { # implements your log here and return the instance return new $theChartDefinitionInstance; } }
其次,重写默认实现。
$connection = new \PDO('sqlite:/Users/foo/Projects/bar.db'); $factory = (new ChartFactory($connection))->overrideDefinitionProvider($myCustomProviderInstance);
你可能还想将所有工厂纳入你的依赖注入策略中,为此,只需通过实现 Mukadi\Chart\ChartFactoryInterface
或扩展 Mukadi\Chart\Factory\AbstractChartFactory
来创建自己的工厂,你可以参考 MukadiChartJsBundle,这是一个针对 Symfony 框架的当前库的集成。