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

扩展PHPWord Word2007 Writer类:自定义部件及原始XML添加问题

扩展PHPWord Word2007 Writer实现自定义Chart部件并支持原始XML输入

问题背景

我尝试扩展PHPWord的Word2007 Writer类,向writerParts数组添加自定义Part类,但直接继承Writer\Word2007后调用save($filename)会生成空白Word文档。

初始自定义Writer代码

namespace App\WordGen\Custom\Writer;

use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Writer\Word2007;
use PhpOffice\PhpWord\Writer\WriterInterface;

class WordGen extends Word2007 implements WriterInterface {
    public function __construct(PhpWord $phpWord) {
        parent::__construct($phpWord);

        if (class_exists('\\App\\WordGen\\Custom\\Writer\\Chart')) {
            $part = new Chart();
            $part->setParentWriter($this);
            $this->writerParts['chart'] = $part;
        }
    }
}

同时我还实现了类似PHPWord IOFactory的自定义抽象Writer类,用于返回WordGen对象。

测试报错

使用php artisan tinker测试时,能看到writerPart已成功修改,但执行保存时触发错误:

> $writer = $reportGen->getWriter();
= App\ReportGen\Custom\Writer\WordGen {#5028}

> $writer->save('\\var\\srv\\www\\reporter\\doctest.docx');

   Error  Call to a member function setMedia() on null.

问题定位与修复

排查后发现是父构造函数在自定义命名空间下查找PhpOffice类,导致原有部件未初始化。于是修改构造函数,不再调用父构造,改为手动循环加载PhpOffice库命名空间下的部件:

foreach (array_keys($this->parts) as $partName) {
    $phpWordClass = '\\PhpOffice\\PhpWord\\Writer\\Word2007\\Part\\' . $partName;
    if (class_exists($phpWordClass)) {
        /** @var \PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart $part Type hint */
        $part = new $phpWordClass();
        $part->setParentWriter($this);
        $this->writerParts[strtolower($partName)] = $part;
    }
}

if (class_exists('\\App\\WordGen\\Custom\\Writer\\Chart')) { 
    // 自定义Chart部件初始化逻辑
}

当前需求

现在我希望实现直接添加原始XML生成图表,而非通过write()函数基于样式构建。为此我已经自定义了继承PhpOffice Chart元素的Chart类,并添加了布尔属性$hasRawXml和存储XML字符串的$rawXml属性,求具体实现方法。

内容的提问来源于stack exchange,提问作者Cyfer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:45:53