You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 00:07:07