This is:
Being able to create a block with an array of variables (aka foreach in templating).
In the docx "template":
Guests:
${CLONEME}
Forname: ${FORENAME}
Lastname: ${LASTNAME}
${/CLONEME}
In the code:
$templateProcessor->cloneBlock('CLONEME', [
['FORENAME' => 'John', 'LASTNAME' => 'Donut'],
['FORENAME' => 'Cat', 'LASTNAME' => 'Stefano']
]);
I want to start a discussion about this before I might implement it and send a PR.
Why don't you just loop through the array and set the values?
Well this way I can have the formatting and text in the template and fill the data in the code. I don't see how this would be possible. Especially with two times the same macro FORENAME and two times LASTNAME.
The result of the code above is:
Forname: John
Lastname: Donut
Forname: Cat
Lastname: Stefano
How would you achieve that with a foreach loop?
When using setValue, you use a third parameter and set it to 1
$templateProcessor->setValue(
'FORENAME', $forename, 1
);
That way it will only replace the first value it finds. So first you use cloneBlock and clone the blocks, and after that run your foreach and only replace the first variable at a time.
If anybody else is wondering how to do this:
$repeatdata = [
['FORENAME' => 'John', 'LASTNAME' => 'Donut'],
['FORENAME' => 'Cat', 'LASTNAME' => 'Stefano']
];
$templateProcessor->cloneBlock('CLONEME', count($repeatdata));
foreach ($repeatdata as $repeatitem){
foreach ($repeatitem as $search => $replace){
$templateProcessor->setValue($search, $replace, 1);
}
}
Thanks @rkorebrits! This is way cleaner.
Perfect, that's pretty much how I use it also (although without the second foreach, but assign one by one). Also prefer it like this without preparing the data as it's cleaner to have conditional logic in the foreach imho.
Please close the ticket if resolved :-)
I found two edge-cases where the solution above does not work (but with my PR):
${MYCAT}
Name: ${NAME}
${/MYCAT}
${MYDOG}
Name: ${NAME}
${/MYDOG}
This only works accidentally if the data is in the correct order (CAT before DOG). Otherwise Cat will be replaced with dogs name since the block context is missing,
${MYCAT}
Her name is "${NAME}". ${NAME} is the best cat in the world,
${/MYCAT}
Obviously only the first one is being replaced.
CAT_NAME and DOG_NAMEIn a path syntax the CAT.NAME and DOG.NAME makes sense. Yes, the second is worse and I don't even have a workaround for that.
Most helpful comment
When using
setValue, you use a third parameter and set it to1That way it will only replace the first value it finds. So first you use cloneBlock and clone the blocks, and after that run your foreach and only replace the first variable at a time.