Grocy第三方集成大全:Open Food Facts对接实战

Grocy第三方集成大全:Open Food Facts对接实战

【免费下载链接】grocy ERP beyond your fridge - Grocy is a web-based self-hosted groceries & household management solution for your home 【免费下载链接】grocy 项目地址: https://gitcode.com/GitHub_Trending/gr/grocy

引言:告别手动录入的食材管理革命

你是否还在为手动输入食材信息到Grocy而烦恼?每添加一个新产品就要填写名称、分类、保质期等一堆字段,不仅耗时还容易出错。本文将带你一步到位解决这个痛点——通过Open Food Facts(开放食品事实)的API对接,实现条形码扫描自动填充产品信息,让家庭库存管理效率提升10倍。

读完本文你将掌握:

  • Grocy插件系统的工作原理
  • Open Food Facts API对接全流程
  • 从配置到调试的实战技巧
  • 常见问题的解决方案与优化建议

技术背景:Grocy插件架构解析

插件系统核心组件

Grocy通过BaseBarcodeLookupPlugin抽象类实现第三方集成能力,所有条形码查询插件都需继承此类并实现ExecuteLookup方法。其核心架构如下:

mermaid

数据流向时序图

当用户扫描条形码时,系统执行以下流程:

mermaid

实战部署:从零开始的对接步骤

1. 环境准备与依赖检查

确保你的Grocy环境满足以下要求:

  • PHP 7.4+ (推荐8.0+)
  • cURL扩展启用
  • 可访问互联网(用于API调用)

通过Composer安装依赖:

composer install --no-dev

2. 配置文件修改

编辑config-dist.php(生产环境使用data/config.php),设置默认条形码插件:

// 在配置文件中找到并修改此行
Setting('STOCK_BARCODE_LOOKUP_PLUGIN', 'OpenFoodFactsBarcodeLookupPlugin');

// 可选:设置默认位置和单位
DefaultUserSetting('product_presets_location_id', 1); // 使用第一个位置
DefaultUserSetting('product_presets_qu_id', 1); // 使用第一个单位

3. 插件工作原理深度解析

OpenFoodFactsBarcodeLookupPlugin.php核心代码解析:

protected function ExecuteLookup($barcode)
{
    // 构建API请求URL,过滤非数字字符
    $cleanBarcode = preg_replace('/[^0-9]/', '', $barcode);
    $url = "https://world.openfoodfacts.org/api/v2/product/{$cleanBarcode}";
    
    // 请求产品数据(仅获取必要字段)
    $response = $this->webClient->request('GET', $url, [
        'fields' => 'product_name,image_url,product_name_' . substr(GROCY_LOCALE, 0, 2),
        'headers' => ['User-Agent' => 'Grocy/4.5.0 (https://grocy.info)']
    ]);
    
    $data = json_decode($response->getBody());
    if ($response->getStatusCode() != 200 || $data->status != 1) {
        return null; // 未找到产品
    }
    
    // 处理多语言产品名称
    $productNameField = 'product_name_' . substr(GROCY_LOCALE, 0, 2);
    $productName = $data->product->product_name;
    if (!empty($data->product->$productNameField)) {
        $productName = $data->product->$productNameField;
    }
    
    return [
        'name' => $productName,
        'location_id' => $this->locationId,
        'qu_id_purchase' => $this->quId,
        'qu_id_stock' => $this->quId,
        '__qu_factor_purchase_to_stock' => 1,
        '__barcode' => $barcode,
        '__image_url' => $data->product->image_url ?? ''
    ];
}

4. 数据库集成流程

StockService处理插件返回数据的关键代码:

public function ExternalBarcodeLookup($barcode, $addFoundProduct)
{
    $plugin = $this->LoadExternalBarcodeLookupPlugin();
    $pluginOutput = $plugin->Lookup($barcode);
    
    if ($pluginOutput && $addFoundProduct) {
        // 下载产品图片
        if (!empty($pluginOutput['__image_url'])) {
            try {
                $response = $this->webClient->request('GET', $pluginOutput['__image_url']);
                $fileName = "product_{$barcode}.jpg";
                file_put_contents($this->getFilesService()->GetFilePath('productpictures', $fileName), $response->getBody());
                $pluginOutput['picture_file_name'] = $fileName;
            } catch (\Exception $e) {
                // 忽略图片下载错误
            }
        }
        
        // 保存产品到数据库
        $newProductRow = $this->getDatabase()->products()->createRow($pluginOutput);
        $newProductRow->save();
        
        // 创建条形码关联
        $this->getDatabase()->product_barcodes()->createRow([
            'product_id' => $newProductRow->id,
            'barcode' => $pluginOutput['__barcode']
        ])->save();
    }
    
    return $pluginOutput;
}

高级配置:定制化与性能优化

API请求优化

默认插件使用全球节点,国内用户可修改为中国节点加速访问:

// 在OpenFoodFactsBarcodeLookupPlugin.php中修改API URL
$response = $webClient->request('GET', 'https://cn.openfoodfacts.org/api/v2/product/' . $barcode);

缓存策略实现

为减少API调用次数,可添加缓存层(需手动实现):

// 在ExecuteLookup方法中添加缓存逻辑
protected function ExecuteLookup($barcode)
{
    $cacheKey = 'off_' . $barcode;
    $cachedData = $this->getCacheService()->Get($cacheKey);
    if ($cachedData) {
        return json_decode($cachedData, true);
    }
    
    // ... 原有API调用代码 ...
    
    $this->getCacheService()->Set($cacheKey, json_encode($pluginOutput), 86400); // 缓存24小时
    return $pluginOutput;
}

字段映射自定义

默认插件仅映射基本字段,如需扩展营养成分等数据,可修改返回数组:

return [
    'name' => $productName,
    'location_id' => $locationId,
    'qu_id_purchase' => $quId,
    'qu_id_stock' => $quId,
    '__qu_factor_purchase_to_stock' => 1,
    '__barcode' => $barcode,
    '__image_url' => $imageUrl,
    // 添加自定义字段
    'calories' => $data->product->nutriments->energy_kcal ?? null,
    'carbohydrates' => $data->product->nutriments->carbohydrates ?? null
];

故障排除:常见问题与解决方案

对接常见错误排查表

错误现象可能原因解决方案
扫描无反应插件未启用检查配置文件STOCK_BARCODE_LOOKUP_PLUGIN设置
API返回404条形码无效确认产品在Open Food Facts数据库中存在
中文名称乱码编码问题确保PHP文件保存为UTF-8无BOM格式
图片无法保存权限不足检查data/productpictures目录写入权限
请求超时网络问题切换API节点或增加超时时间

调试技巧

启用详细日志记录(在config-dist.php中):

Setting('LOG_LEVEL', 'debug');

查看日志文件:

tail -f data/logs/grocy.log

使用API测试工具验证响应:

curl "https://world.openfoodfacts.org/api/v2/product/978020137962"

总结与展望

通过本文介绍的方法,你已成功实现Grocy与Open Food Facts的无缝集成,告别了繁琐的手动录入。这不仅提升了日常使用效率,更为食材管理带来了数据丰富度的飞跃。

后续改进方向

  1. 批量导入功能:开发基于产品分类的批量导入工具
  2. 本地数据库缓存:建立本地产品数据库减少API依赖
  3. 营养成分分析:利用导入的营养数据实现饮食建议功能
  4. 用户贡献机制:允许将本地产品数据反馈至Open Food Facts

扩展阅读与资源

如果你在实施过程中遇到问题,欢迎在GitHub仓库提交Issue或参与社区讨论。高效食材管理,从自动化数据录入开始!


【免费下载链接】grocy ERP beyond your fridge - Grocy is a web-based self-hosted groceries & household management solution for your home 【免费下载链接】grocy 项目地址: https://gitcode.com/GitHub_Trending/gr/grocy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值