Как добавить секцию с различными элементами на макрос шаблонного процессора в phpWord
Однажды, в один прекрасный солнечный день...
Мне понадобилось добавить секцию на переменную шаблонного процессора.
И секцию непростую, в ней должны были содержаться заголовки, таблицы и текст в зависимости от входящих данных.
Для этого подходит метод setComplexBlock()
(ссылка на док'у), но если этому методу передать объект секции, то выпадет ошибка об отсутствии данного класса в пространстве имён Writer'а для Word2007
Fatal error: Uncaught Error:
Class 'PhpOffice\PhpWord\Writer\Word2007\Element\Section'
not found
И там действительно отсутствует этот класс:

Можно отдельно создать экземпляр объекта таблицы, заголовка, текста (там есть много других объектов) и добавить только его, но не более.
И для того чтобы сделать то, что нам нужно. Необходимо провернуть "финт ушами".
Мы сделаем подмену и передадим вместо секции кастомный контейнер.
Для этого достаточно создать класс кастомного контейнера, который по сути своей является секцией.
namespace CustomContainer;
class Container extends \PhpOffice\PhpWord\Element\Section
{
public function __construct($section)
{
parent::__construct($section->getSectionId());
$this->elements = $section->getElements();
}
}
Обязательно подключим этот класс и библиотеку phpWord с помощью композер. Как установить композер пояснено в других статьях. Здесь мы не будем останавливаться на этом
require_once('vendor/autoload.php');
require_once ('CustomContainer/CustomContainer.php');
Для примера создадим объект PhpWord и добавим в него секцию
$newDocumentWithSection = new \PhpOffice\PhpWord\PhpWord();
$newSection = $newDocumentWithSection->addSection();
Наполним секцию каким-нибудь сомнительным содержимым
$newTitle = $newSection->addTitle('someTitle');
$newTable = $newSection->addTable([
'borderSize' => 12,
'borderColor' => 'green',
'width' => 6000,
'unit' => PhpOffice\PhpWord\SimpleType\TblWidth::TWIP
]);
$newTable->addRow();
$newTable->addCell(150)->addText('Cell A1');
$newTable->addCell(150)->addText('Cell A2');
$newTable->addCell(150)->addText('Cell A3');
$newTable->addRow();
$newTable->addCell(150)->addText('Cell B1');
$newTable->addCell(150)->addText('Cell B2');
$newTable->addCell(150)->addText('Cell B3');
Создадим новый "контейнер" на основе нашей секции.
$newCustomContainerWithSection = new \CustomContainer\Container($newSection);
Далее создадим экземпляр шаблонного процессора и передадим в метод setComplexBlock()
новый подменный "контейнер".
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('templateWithGeneratedSection.docx');
$templateProcessor->setComplexBlock('macro', $newCustomContainerWithSection);
Напоследок сохраним данные
$templateProcessor->saveAs('DocumentWithGeneratedSection.docx');
В результате видим следующее:
Было:

Стало:

Поставленная задача выполнена.
Ссылка на код с работающим примером
Ссылка на оригинальный англоязычный issue-github.
Пока что это является временным решением данной проблемы.