PHP调用Matomo API批量获取并展示全量指标数据的方法
问题根源
你当前只能逐个展示单个指标的核心原因有两点:
TabMetrique.php内的getMetrique()函数写死返回$metrique[9],无论传入什么参数都只会固定调用第10个(数组索引从0开始)的访问数接口- 主程序仅构造了1次API请求,没有遍历预先定义的11个指标项逐个拉取对应数据
实现逻辑
不需要复杂封装,直接在构造API请求的逻辑外层套一层循环,遍历所有配置好的指标即可,单次循环内固定执行3步操作:
- 拼接当前指标对应的Matomo API请求URL
- 发起HTTP请求,解析返回的JSON数据
- 根据当前指标的返回结构渲染输出内容
注意Matomo不同API的返回结构存在差异:比如设备、地区这类维度列表接口会返回带label字段的多维数组,访问汇总类接口可能直接返回数值,需要做简单的结构判断兼容。
修正后的代码
1. 调整TabMetrique.php配置文件
把原来写死返回值的函数改掉,支持获取单个指标和全量指标列表:
<?php // 指标配置数组 $metrique = [ 0 => 'DevicesDetection.getModel', // 设备型号 1 => 'UserCountry.getCountry', // 国家 2 => 'UserCountry.getContinent', // 大洲 3 => 'UserCountry.getRegion', // 省份/地区 4 => 'UserCountry.getCity', // 城市 5 => 'UserId.getUsers', // 用户ID 6 => 'UserLanguage.getLanguage', // 语言 7 => 'VisitFrequency.get', // 回访用户数据 8 => 'VisitsSummary.get', // 访问汇总 9 => 'VisitsSummary.getVisits', // 访问次数 10 => 'VisitsSummary.getUniqueVisitors' // 独立访客数 ]; /** * 根据索引获取对应指标API方法名 * @param int $index 指标索引 * @return string */ function getMetrique(int $index): string { global $metrique; return isset($metrique[$index]) ? $metrique[$index] : ''; } /** * 获取所有配置的指标列表 * @return array */ function getAllMetriques(): array { global $metrique; return $metrique; } ?>
2. 调整主程序逻辑
把原来单次请求的逻辑套入全量指标遍历循环,同时兼容不同API的返回结构:
<?php include 'TabMetrique.php'; $token_auth = '*********'; $matomo_base_url = "http://localhost/matomo/"; $site_id = 1; $period = 'month'; $date = '2022-05-14'; print("<h1>Métrique Matomo</h1>\n"); // 遍历所有配置的指标,逐个拉取数据 foreach (getAllMetriques() as $metric_name) { // 拼接当前指标的API请求URL $url = $matomo_base_url . "?module=API&method=".$metric_name; $url .= "&idSite=".$site_id; $url .= "&period=".$period."&date=".$date; $url .= "&format=JSON"; $url .= "&token_auth=".$token_auth; $fetched = file_get_contents($url); $content = json_decode($fetched, true); // 无数据跳过当前指标 if (!$content) { print("<p>指标 <b>".htmlspecialchars($metric_name, ENT_QUOTES, 'UTF-8')."</b> 无数据</p><br>\n"); continue; } print("<h3>指标:".htmlspecialchars($metric_name, ENT_QUOTES, 'UTF-8')."</h3>\n"); print("<div style='margin-left:20px'>"); // 判断返回结构:如果是单值(比如直接返回访问数数字) if (!is_array($content)) { print("数值:".htmlspecialchars($content, ENT_QUOTES, 'UTF-8')."<br>\n"); } else { // 列表型返回,遍历行 foreach ($content as $key => $row) { // 处理带label的列表项 if (is_array($row) && isset($row['label'])) { $item_label = htmlspecialchars($row["label"], ENT_QUOTES, 'UTF-8'); $hits = isset($row['nb_visits']) ? $row['nb_visits'] : (isset($row['value']) ? $row['value'] : 0); print("<b>".$item_label."</b> (".$hits." visits)<br>\n"); } else { // 处理键值对类型的返回(比如VisitFrequency.get返回的结构) if (is_array($row)) { print(htmlspecialchars($key, ENT_QUOTES, 'UTF-8').":"); foreach ($row as $sub_key => $sub_val) { print(htmlspecialchars($sub_key, ENT_QUOTES, 'UTF-8')." = ".htmlspecialchars($sub_val, ENT_QUOTES, 'UTF-8')." ; "); } print("<br>\n"); } else { print(htmlspecialchars($key, ENT_QUOTES, 'UTF-8')." = ".htmlspecialchars($row, ENT_QUOTES, 'UTF-8')."<br>\n"); } } } } print("</div><br>\n"); } ?>
补充说明
- 你原代码里
if ($content == $row)的判断逻辑完全无效,因为$content是整个返回数组,$row是遍历的子项,二者类型、值都不可能相等,上述修正代码已经移除该无效判断,按返回结构做了自动兼容 - 后续新增指标时,直接在
TabMetrique.php的$metrique数组里追加对应Matomo API方法名即可,主程序不需要修改会自动遍历拉取 - 如果指标数量较多觉得请求慢,可以改用Matomo批量API接口,把多个方法合并到一次HTTP请求中,减少请求耗时。
内容的提问来源于stack exchange,提问作者Le Roux Mael
相关产品推荐
相关产品推荐

