如何修复Kanboard中的Helper函数以从JSON API获取指定数据
问题描述
我在Kanboard中使用Helper函数展示数据,需要实现两个功能:
- 从JSON API返回的货币(代码/汇率)结果中,为每个已设置的货币代码获取实时汇率;
- 显示最后更新日期——只需显示一次。
Helper文件代码
<?php namespace Kanboard\Plugin\CostControl\Helper; use Kanboard\Core\Base; class LiveRateHelper extends Base { /***** RESPONSE JSON EXAMPLE { "result": "success", "provider": "https://www.exchangerate-api.com", "documentation": "https://www.exchangerate-api.com/docs/free", "terms_of_use": "https://www.exchangerate-api.com/terms", "time_last_update_unix": 1680393752, "time_last_update_utc": "Sun, 02 Apr 2023 00:02:32 +0000", "time_next_update_unix": 1680481582, "time_next_update_utc": "Mon, 03 Apr 2023 00:26:22 +0000", "time_eol_unix": 0, "base_code": "GBP", "rates": { "GBP": 1, "AED": 4.536918, "AFN": 107.049854, "ZWL": 128.90737, } } *****/ public static function getLiveRate($application_currency, $rate_currency) { // Fetching JSON $req_url = 'https://open.er-api.com/v6/latest/'.$application_currency; $response_json = file_get_contents($req_url); // Continuing if we got a result if(false !== $response_json) { // Try/catch for json_decode operation try { // Decoding $response = json_decode($response_json); // Check for success if('success' === $response->result) { $last_updated = $response->time_last_update_utc; $key == $rate_currency; $base_currency = $application_currency; foreach ($response->rates as $key => $value) { $currency_rate = $key .' '. $value; } return $currency_rate; } } catch(Exception $e) { // Handle JSON parse error... return 'Error retrieving live rate'; } } } }
模板调用代码
<div class="panel"> <strong><?= t('Base Currency: %s', $application_currency) ?></strong> </div> <?php if (! empty($rates)): ?> <table class="table-striped"> <tr class=""> <th class="column-35"><?= t('Currency') ?></th> <th class=""><?= t('Rate') ?></th> <th class=""> Last Modified</th> <th class="">Live Daily Rate</th> </tr> <?php foreach ($rates as $rate): ?> <tr class=""> <td class=""> <span class="currency-coins-icon"></span> <strong><?= $this->text->e($rate['currency']) ?></strong> </td> <td class=""> <?= n($rate['rate']) ?> </td> <td class="live-rate"> <?= $this->helper->liveRateHelper->getLiveRate($application_currency, $rate_currency = $this->text->e($rate['currency'])) ?> </td> </tr> <?php endforeach ?> </table> <?php endif ?>
当前问题
application_currency变量正常工作,能基于设置的基准货币获取汇率;$last_updated = $response->time_last_update_utc无法在模板中调用显示;- 返回的货币代码和值始终是JSON中的最后一个货币(ZWL)及其汇率:模板中
<?= $this->text->e($rate['currency']) ?>显示正常,但$rate_currency参数似乎未正确传递给Helper函数,否则不会总是返回最后一个货币。
解决方案
1. 重构Helper函数,优化逻辑并支持缓存
修改Helper,加入缓存避免重复请求API,同时拆分方法分别获取汇率和更新时间:
<?php namespace Kanboard\Plugin\CostControl\Helper; use Kanboard\Core\Base; class LiveRateHelper extends Base { private static $apiCache = null; // 缓存API响应,减少重复请求 // 获取完整API数据(含汇率和更新时间) public static function getRateData($baseCurrency) { if (self::$apiCache !== null) { return self::$apiCache; } $reqUrl = 'https://open.er-api.com/v6/latest/' . $baseCurrency; $responseJson = file_get_contents($reqUrl); if ($responseJson !== false) { try { $response = json_decode($responseJson); if ($response->result === 'success') { self::$apiCache = [ 'lastUpdated' => $response->time_last_update_utc, 'rates' => $response->rates ]; return self::$apiCache; } } catch (\Exception $e) { return [ 'error' => '解析API数据失败', 'lastUpdated' => '', 'rates' => [] ]; } } return [ 'error' => '无法获取API数据', 'lastUpdated' => '', 'rates' => [] ]; } // 获取单个货币的实时汇率 public static function getSingleRate($baseCurrency, $targetCurrency) { $data = self::getRateData($baseCurrency); return isset($data['rates']->$targetCurrency) ? round($data['rates']->$targetCurrency, 2) : 'N/A'; } // 获取最后更新时间 public static function getLastUpdated($baseCurrency) { $data = self::getRateData($baseCurrency); return $data['lastUpdated'] ?? ''; } }
2. 修改模板,调用新方法并显示更新时间
<div class="panel"> <strong><?= t('Base Currency: %s', $application_currency) ?></strong> <?php $lastUpdated = $this->helper->liveRateHelper->getLastUpdated($application_currency); ?> <?php if (!empty($lastUpdated)): ?> <span class="small" style="margin-left: 10px;"> <?= t('Last updated: %s', $lastUpdated) ?> </span> <?php endif ?> </div> <?php if (! empty($rates)): ?> <table class="table-striped"> <tr class=""> <th class="column-35"><?= t('Currency') ?></th> <th class=""><?= t('Rate') ?></th> <th class="">Last Modified</th> <th class="">Live Daily Rate</th> </tr> <?php foreach ($rates as $rate): ?> <tr class=""> <td class=""> <span class="currency-coins-icon"></span> <strong><?= $this->text->e($rate['currency']) ?></strong> </td> <td class=""> <?= n($rate['rate']) ?> </td> <td class="live-rate"> <?= $this->helper->liveRateHelper->getSingleRate($application_currency, $this->text->e($rate['currency'])) ?> </td> </tr> <?php endforeach ?> </table> <?php endif ?>
关键修改说明
- 加入缓存机制:用静态变量缓存API响应,避免循环中重复请求,提升性能
- 修复汇率获取逻辑:直接通过
$response->rates->$targetCurrency获取指定货币汇率,解决返回最后一个货币的问题 - 拆分功能方法:将获取完整数据、单个汇率、更新时间拆分为独立方法,逻辑更清晰
- 实现单次更新时间显示:在模板顶部一次性获取并展示更新时间,满足需求
内容的提问来源于stack exchange,提问作者aljawaid
相关产品推荐
相关产品推荐

