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

Symfony4+Webpack Encore版本化后,PHP中如何访问静态资源生成PDF?

嘿,这个场景我太熟悉了——用Webpack Encore做资源版本化确实能解决前端缓存的大问题,但碰到PHP端(比如TCPDF这种需要直接读取本地文件的工具)就容易卡壳。不过别担心,有几个完美的解决方案,既能保留版本化的优势,又能让PHP顺利拿到正确的图片路径:

方案1:利用Webpack Encore的Manifest文件(最通用)

Encore在构建时会生成一个manifest.json文件,里面存着所有资源原文件名和版本化后文件名的映射关系。PHP只要读取这个文件,就能拿到正确的路径。

步骤1:确保Encore配置正确

首先在webpack.config.js里开启版本化和manifest生成,注意setManifestKeyPrefix要和你的public路径匹配:

// webpack.config.js
const Encore = require('@symfony/webpack-encore');

Encore
  // ... 其他基础配置(比如设置output路径、启用babel等)
  .setPublicPath('/build')
  .setManifestKeyPrefix('build/') // 关键:确保manifest里的路径前缀正确
  .enableVersioning(Encore.isProduction()) // 只在生产环境开启版本化(可选,但推荐)
  // 如果你的图片不需要在JS里引用,用copyFiles让Encore处理它们
  .copyFiles({
    from: './assets/images',
    to: 'images/[path][name].[hash:8].[ext]', // 给图片加上hash版本号
    pattern: /\.(png|jpg|jpeg|svg)$/
  })
;

module.exports = Encore.getWebpackConfig();

步骤2:PHP读取Manifest获取路径

你可以自己写个简单的服务,或者直接在需要的地方读取manifest。这里推荐用Symfony的依赖注入写个服务,复用性更高:

// src/Service/AssetResolver.php
namespace App\Service;

use Symfony\Component\HttpKernel\KernelInterface;

class AssetResolver
{
    private $manifestData;
    private $projectDir;

    public function __construct(KernelInterface $kernel)
    {
        $this->projectDir = $kernel->getProjectDir();
        $manifestPath = $this->projectDir.'/public/build/manifest.json';
        
        // 读取manifest内容(生产环境可以缓存这个数据,避免每次读取文件)
        if (file_exists($manifestPath)) {
            $this->manifestData = json_decode(file_get_contents($manifestPath), true);
        }
    }

    public function getVersionedPath(string $originalPath): string
    {
        // 如果manifest不存在(比如开发环境没构建),直接返回原路径
        if (!$this->manifestData) {
            return '/build/'.$originalPath;
        }

        $manifestKey = 'build/'.$originalPath;
        // 从manifest里拿版本化后的路径,找不到就 fallback 到原路径
        return isset($this->manifestData[$manifestKey]) 
            ? '/'.$this->manifestData[$manifestKey] 
            : '/build/'.$originalPath;
    }
}

步骤3:在TCPDF里使用

在生成PDF的代码里注入这个服务,拿到正确的绝对路径(TCPDF需要服务器本地绝对路径):

// 比如在某个Controller或者PDF生成服务里
use App\Service\AssetResolver;
use TCPDF;

public function generatePdf(AssetResolver $assetResolver)
{
    $pdf = new TCPDF();
    // 获取版本化后的相对路径
    $logoRelativePath = $assetResolver->getVersionedPath('images/logo.png');
    // 转成服务器绝对路径
    $logoAbsolutePath = $this->projectDir.'/public'.$logoRelativePath;
    // 或者用$_SERVER['DOCUMENT_ROOT']拼接:
    // $logoAbsolutePath = $_SERVER['DOCUMENT_ROOT'].$logoRelativePath;

    // 插入图片到PDF
    $pdf->Image($logoAbsolutePath, 10, 10, 30, 0, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false);
    
    // ... 其他PDF生成逻辑
    return $pdf->Output('document.pdf', 'I');
}

方案2:用Symfony官方Asset组件(更省心)

Symfony的Asset组件已经原生支持读取manifest文件,不用自己写服务,直接用官方封装好的工具:

步骤1:安装Asset组件(如果没装)

composer require symfony/asset

步骤2:配置manifest路径

在config/packages/framework.yaml里添加Asset的配置:

# config/packages/framework.yaml
framework:
    assets:
        json_manifest_path: '%kernel.project_dir%/public/build/manifest.json'

步骤3:在PHP里使用

直接注入Package类或者用AssetInterface来获取路径:

use Symfony\Component\Asset\PackageInterface;
use TCPDF;

public function generatePdf(PackageInterface $assetPackage)
{
    // 获取版本化后的路径
    $logoRelativePath = $assetPackage->getUrl('build/images/logo.png');
    $logoAbsolutePath = $_SERVER['DOCUMENT_ROOT'].$logoRelativePath;

    $pdf = new TCPDF();
    $pdf->Image($logoAbsolutePath, 10, 10, 30);
    
    // ... 其他逻辑
}

如果是从Twig模板生成PDF内容,还可以直接用Twig的asset()函数拿到正确路径,比如:

{# 在Twig模板里 #}
<img src="{{ asset('build/images/logo.png') }}" />

然后把渲染后的HTML传给TCPDF即可。

开发环境小技巧

开发环境下如果不想每次修改图片都重新构建,可以直接用Encore dev server的路径,比如:

if ($this->getParameter('kernel.environment') === 'dev') {
    // 用dev server的地址,不用版本化
    $logoAbsolutePath = 'http://localhost:8080/build/images/logo.png';
} else {
    // 生产环境用manifest获取版本化路径
    $logoAbsolutePath = $_SERVER['DOCUMENT_ROOT'].$assetPackage->getUrl('build/images/logo.png');
}

内容的提问来源于stack exchange,提问作者Kristen Joseph-Delaffon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:24:05