Example: another shipping label
A third shipping label, styled differently from the first one: three stacked blocks — ship from/to, contents, and a tracking barcode — separated by rule lines instead of full borders around every cell.
Output
Section titled “Output”
<?php
require 'vendor/autoload.php';
use Kehet\ImagickLayoutEngine\Containers\ColumnContainer;use Kehet\ImagickLayoutEngine\Containers\GridContainer;use Kehet\ImagickLayoutEngine\Containers\RowContainer;use Kehet\ImagickLayoutEngine\Enums\Gravity;use Kehet\ImagickLayoutEngine\Enums\ImageMode;use Kehet\ImagickLayoutEngine\Items\Image;use Kehet\ImagickLayoutEngine\Items\Text;use Kehet\ImagickLayoutEngine\Items\TextWrap;
function fieldLabel(string $text): Text{ $draw = draw(fill: '#4b5563'); $draw->setFont('DejaVu-Sans'); $item = new Text($draw, $text, initialFontSize: 18, gravity: Gravity::TOP_LEFT); $item->setLetterSpacing(2);
return $item;}
function fieldValue(string $text, int $size = 26): TextWrap{ $draw = draw(fill: 'black'); $draw->setFont('DejaVu-Sans-Bold');
return new TextWrap($draw, $text, initialFontSize: $size, gravity: Gravity::TOP_LEFT);}
$width = 900;$height = 960;
$imagick = new Imagick;$imagick->newImage($width, $height, new ImagickPixel('white'));
$divider = draw(stroke: 'black', strokeWidth: 3);
$root = new ColumnContainer;$root->setBorder(draw(stroke: 'black', strokeWidth: 5));$root->setPadding(30);
// ---------------------------------------------------------------------// Block 1: free-text ship from / ship to// ---------------------------------------------------------------------$block1 = new ColumnContainer;$block1->setBorderBottom($divider);$block1->setPadding(0, 0, 20, 0);$block1->setGap(16);
$block1->addItem(fieldLabel('SHIP FROM'), forceSize: 24);$block1->addItem( fieldValue("ACME Distribution Ltd\nTeollisuuskatu 9\n00510 Helsinki, Finland", 22), forceSize: 80);
$shipToRow = new RowContainer;$shipToLabelCol = new ColumnContainer;$shipToLabelCol->setGap(10);$shipToLabelCol->addItem(fieldLabel('SHIP TO'), forceSize: 24);$shipToLabelCol->addItem( fieldValue("Nordic Retail Group\nWarehouse 4, Logistikvagen 22\n164 40 Kista, Sweden", 30));$shipToRow->addItem($shipToLabelCol);
$poCol = new ColumnContainer;$poCol->setGap(10);$poCol->addItem(fieldLabel('PURCHASE ORDER'), forceSize: 24);$poCol->addItem(fieldValue('4471258', 30));$shipToRow->addItem($poCol, forceSize: 220);
$block1->addItem($shipToRow, forceSize: 140);
$root->addItem($block1, forceSize: 320);
// ---------------------------------------------------------------------// Block 2: contents, as a label/value grid// ---------------------------------------------------------------------$block2 = new ColumnContainer;$block2->setBorderBottom($divider);$block2->setPadding(20, 0);$block2->setGap(16);
$block2->addItem(fieldLabel('CONTENTS'), forceSize: 24);$block2->addItem(fieldValue('Organic Cranberry Juice 1 L x 24', 28), forceSize: 40);
$detailsGrid = new GridContainer;$detailsGrid->setTemplateColumns(null, null);$detailsGrid->setGap(14, 30);
$details = [ ['label' => 'PRODUCT CODE', 'value' => '10614141122763'], ['label' => 'QUANTITY', 'value' => '24 EA'], ['label' => 'BATCH/LOT', 'value' => 'LOT2547'], ['label' => 'BEST BEFORE', 'value' => '2026-12-31'],];
foreach ($details as $detail) { $cell = new ColumnContainer; $cell->setGap(2); $cell->addItem(fieldLabel($detail['label']), forceSize: 22); $cell->addItem(fieldValue($detail['value'], 24)); $detailsGrid->addItem($cell);}
$block2->addItem($detailsGrid, forceSize: 160);
$root->addItem($block2, forceSize: 260);
// ---------------------------------------------------------------------// Block 3: tracking barcode, always last so it's the easiest thing on// the label for a handheld scanner to find// ---------------------------------------------------------------------$block3 = new ColumnContainer;$block3->setPadding(20, 0, 0, 0);$block3->setGap(10);
$block3->addItem(fieldLabel('TRACKING NUMBER'), forceSize: 24);$block3->addItem(new Image(__DIR__.'/example-code-128.png', ImageMode::FIT), forceSize: 190);
$trackingDraw = draw(fill: 'black');$trackingDraw->setFont('DejaVu-Sans-Bold');$tracking = new Text($trackingDraw, '3 0614141 812345678 6', initialFontSize: 30, gravity: Gravity::CENTER);$tracking->setLetterSpacing(2);$block3->addItem($tracking, forceSize: 44);
$root->addItem($block3);
$root->draw($imagick, 0, 0, $width, $height);
$imagick->setImageFormat('png');$imagick->writeImage(__DIR__.'/pallet-label.png');Each block is a plain ColumnContainer; the rule lines between them are just setBorderBottom() on blocks 1
and 2, rather than a full border on every cell or a separate Rectangle divider. The contents block uses a
GridContainer for its label/value pairs, and the tracking number reuses the same placeholder barcode image as
the other label guides.
Template
Section titled “Template”The same layout as a template. The fieldLabel()/fieldValue() helpers have no template equivalent, so their styling (fill, font, fontSize, letterSpacing) is repeated on every label/value node below, and setBorderBottom() becomes a border object with only a bottom key:
{ "type": "column", "border": {"stroke": "black", "strokeWidth": 5}, "padding": 30, "children": [ { "type": "column", "border": {"bottom": {"stroke": "black", "strokeWidth": 3}}, "padding": {"top": 0, "right": 0, "bottom": 20, "left": 0}, "gap": 16, "size": 320, "children": [ {"type":"text","text":"SHIP FROM","fill":"#4b5563","font":"DejaVu-Sans","fontSize":18,"letterSpacing":2,"size":24}, {"type":"text-wrap","text":"ACME Distribution Ltd\nTeollisuuskatu 9\n00510 Helsinki, Finland","fill":"black","font":"DejaVu-Sans-Bold","fontSize":22,"size":80}, { "type": "row", "size": 140, "children": [ { "type": "column", "gap": 10, "children": [ {"type":"text","text":"SHIP TO","fill":"#4b5563","font":"DejaVu-Sans","fontSize":18,"letterSpacing":2,"size":24}, {"type":"text-wrap","text":"Nordic Retail Group\nWarehouse 4, Logistikvagen 22\n164 40 Kista, Sweden","fill":"black","font":"DejaVu-Sans-Bold","fontSize":30} ] }, { "type": "column", "gap": 10, "size": 220, "children": [ {"type":"text","text":"PURCHASE ORDER","fill":"#4b5563","font":"DejaVu-Sans","fontSize":18,"letterSpacing":2,"size":24}, {"type":"text-wrap","text":"4471258","fill":"black","font":"DejaVu-Sans-Bold","fontSize":30} ] } ] } ] }, { "type": "column", "border": {"bottom": {"stroke": "black", "strokeWidth": 3}}, "padding": {"top": 20, "right": 0, "bottom": 20, "left": 0}, "gap": 16, "size": 260, "children": [ {"type":"text","text":"CONTENTS","fill":"#4b5563","font":"DejaVu-Sans","fontSize":18,"letterSpacing":2,"size":24}, {"type":"text-wrap","text":"Organic Cranberry Juice 1 L x 24","fill":"black","font":"DejaVu-Sans-Bold","fontSize":28,"size":40}, { "type": "grid", "templateColumns": [null, null], "gap": [14, 30], "size": 160, "children": [ { "type": "column", "gap": 2, "children": [ {"type":"text","text":"PRODUCT CODE","fill":"#4b5563","font":"DejaVu-Sans","fontSize":18,"letterSpacing":2,"size":22}, {"type":"text-wrap","text":"10614141122763","fill":"black","font":"DejaVu-Sans-Bold","fontSize":24} ] }, { "type": "column", "gap": 2, "children": [ {"type":"text","text":"QUANTITY","fill":"#4b5563","font":"DejaVu-Sans","fontSize":18,"letterSpacing":2,"size":22}, {"type":"text-wrap","text":"24 EA","fill":"black","font":"DejaVu-Sans-Bold","fontSize":24} ] }, { "type": "column", "gap": 2, "children": [ {"type":"text","text":"BATCH/LOT","fill":"#4b5563","font":"DejaVu-Sans","fontSize":18,"letterSpacing":2,"size":22}, {"type":"text-wrap","text":"LOT2547","fill":"black","font":"DejaVu-Sans-Bold","fontSize":24} ] }, { "type": "column", "gap": 2, "children": [ {"type":"text","text":"BEST BEFORE","fill":"#4b5563","font":"DejaVu-Sans","fontSize":18,"letterSpacing":2,"size":22}, {"type":"text-wrap","text":"2026-12-31","fill":"black","font":"DejaVu-Sans-Bold","fontSize":24} ] } ] } ] }, { "type": "column", "padding": {"top": 20, "right": 0, "bottom": 0, "left": 0}, "gap": 10, "children": [ {"type":"text","text":"TRACKING NUMBER","fill":"#4b5563","font":"DejaVu-Sans","fontSize":18,"letterSpacing":2,"size":24}, {"type":"image","file":"example-code-128.png","mode":"fit","size":190}, {"type":"text","text":"3 0614141 812345678 6","fill":"black","font":"DejaVu-Sans-Bold","fontSize":30,"gravity":"center","letterSpacing":2,"size":44} ] } ]}