Создание необязательных слоёв содержимого (OCG)
Помещайте содержимое в именованные группы необязательного содержимого (OCG), которые часто называют слоями. Программа просмотра PDF может переключать каждый слой на панели слоёв, а один слой по умолчанию остаётся скрытым. Этот рецепт следует примеру examples/26-layers.php.
OCG — это словарь группы необязательного содержимого по ISO 32000-2 со значением Type /OCG. NextPDF заключает помеченное содержимое слоя между BDC/EMC и использует тег помеченного содержимого OC.
Установка
Заголовок раздела «Установка»composer require nextpdf/core:^3Дополнительное расширение не требуется. API слоёв стабилен начиная с версии 1.0.0 и работает на матрице обратной совместимости 8.1–8.4.
Концептуальный обзор
Заголовок раздела «Концептуальный обзор»startLayer($name, $visible) открывает OCG. Всё, что вы рисуете до соответствующего endLayer(), принадлежит этой группе. $name — это подпись, которую программа просмотра PDF показывает на панели слоёв. ISO 32000-2 требует, чтобы у OCG был ключ Name — строка, видимая пользователю. Передача $visible: false регистрирует группу в конфигурации по умолчанию в состоянии OFF, поэтому программа просмотра скрывает её, пока пользователь не включит слой.
Видимость зависит от поддержки в программе просмотра. Для словаря принадлежности к необязательному содержимому (OCMD) политика видимости по умолчанию — AnyOn. Слой виден, если любая из указанных групп находится в состоянии ON. Скрытый слой скрывается только по соглашению программы просмотра. Он не удаляется, не защищается и не является ни редактированием для удаления данных, ни средством защиты. Чтобы удалить содержимое, не рисуйте его.
Состав API
Заголовок раздела «Состав API»PHPDoc автоматически формирует перечень API. В этом рецепте используются два метода:
startLayer(string $name, bool $visible = true): static— открывает именованный OCG;$visible: falseскрывает его по умолчанию.endLayer(): static— закрывает последний открытый слой (парный сstartLayer()).
Пример кода — быстрый старт
Заголовок раздела «Пример кода — быстрый старт»<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->addPage();
$doc->startLayer('Content', visible: true);$doc->setFont('helvetica', '', 12);$doc->cell(0, 8, 'Always-visible body content.', newLine: true);$doc->endLayer();
$doc->startLayer('Debug Grid', visible: false); // hidden until toggled$doc->setDrawColor(200, 200, 200);for ($x = 0.0; $x <= 210.0; $x += 10.0) { $doc->line($x, 0, $x, 297);}$doc->endLayer();
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/layers.pdf');Пример кода — рабочая версия
Заголовок раздела «Пример кода — рабочая версия»Используйте этот полный пример, готовый к запуску в тестовом окружении. Он учитывает NEXTPDF_COOKBOOK_OUTPUT и не вносит собственной энтропии.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\Alignment;use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Layer Examples (OCG)');$doc->addPage();
// Layer 1 — background, visible by default.$doc->startLayer('Background', visible: true);$doc->setFillColor(230, 240, 250);$doc->rect(10, 10, 190, 277, 'F');$doc->endLayer();
// Layer 2 — watermark, visible by default; can be toggled off.$doc->startLayer('Watermark', visible: true);$doc->setFont('helvetica', 'B', 54);$doc->setTextColor(200, 200, 200);$doc->startTransform();$doc->rotate(45, 105, 148);$doc->setXY(30, 135);$doc->cell(150, 20, 'DRAFT', align: Alignment::Center);$doc->stopTransform();$doc->endLayer();
// Layer 3 — main content, visible by default.$doc->startLayer('Content', visible: true);$doc->setTextColor(0);$doc->setFont('helvetica', 'B', 20);$doc->setXY(10, 15);$doc->cell(0, 14, 'Layer Examples (OCG)', newLine: true);$doc->ln(4);$doc->setFont('helvetica', '', 11);$doc->multiCell(0, 7, 'This document contains four optional content groups. ' . "Toggle them in your reader's Layers panel.");$doc->endLayer();
// Layer 4 — debug grid, hidden by default.$doc->startLayer('Debug Grid', visible: false);$doc->setDrawColor(180, 180, 180);$doc->setLineWidth(0.15);for ($x = 0.0; $x <= 210.0; $x += 10.0) { $doc->line($x, 0, $x, 297);}for ($y = 0.0; $y <= 297.0; $y += 10.0) { $doc->line(0, $y, 210, $y);}$doc->endLayer();
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/layers.pdf';$doc->save($out);
echo "Created layers.pdf\n";Граничные случаи и подводные камни
Заголовок раздела «Граничные случаи и подводные камни»- Для каждого
startLayer()добавляйте парныйendLayer(). Незакрытый слой оставляет висящийBDCбезEMCи делает структуру документа некорректной. Сопоставляйте каждый открывающий вызов с закрывающим. - Скрытый слой не удаляется.
visible: falseскрывает содержимое только по соглашению программы просмотра. Метки и любой текст остаются в файле и могут быть восстановлены. Это не редактирование для удаления данных. Для конфиденциальных данных просто не рисуйте их. - Поддержка панели слоёв различается. Для переключения нужна программа просмотра, которая предоставляет доступ к необязательному содержимому. Конвейеры печати и упрощённые средства просмотра могут всегда показывать или всегда скрывать слои, отключённые по умолчанию.
- Вложенность. Вложенные слои разрешены, но видимость каждой внутренней группы остаётся независимой. Не считайте, что внешний слой в состоянии OFF скрывает внутреннюю группу в состоянии ON, если вы не настроили политику принадлежности.
Производительность
Заголовок раздела «Производительность»Каждый слой добавляет один словарь OCG и пару BDC/EMC вокруг своих меток. Накладные расходы пренебрежимо малы. Затраты растут вместе с содержимым внутри слоёв, а не с числом слоёв, поэтому всё с запасом укладывается в бюджет 2000 мс / 64 МБ.
Замечания по безопасности
Заголовок раздела «Замечания по безопасности»Видимость необязательного содержимого зависит от поддержки в программе просмотра и не является контролем доступа. Скрытие слоя не шифрует, не редактирует для удаления данных и не удаляет его содержимое. Любой может снова включить слой или извлечь его байты. Никогда не используйте скрытый слой для сокрытия конфиденциального текста; вместо этого полностью опускайте такое содержимое. Этот рецепт не разбирает входные данные и не делает сетевых запросов.
Соответствие
Заголовок раздела «Соответствие»| Утверждение | Спецификация | Пункт | идентификатор ссылки (reference_id) |
|---|---|---|---|
Словарь OCG имеет Type /OCG. | ISO 32000-2 | §8.11.2 | |
Ключ OCG Name — обязательная подпись, видимая пользователю. | ISO 32000-2 | §8.11.2 | |
Необязательное содержимое заключается между BDC/EMC с тегом OC. | ISO 32000-2 | §8.11.3.2 | |
| Политики OCMD — AllOn/AnyOn/AnyOff/AllOff (по умолчанию AnyOn). | ISO 32000-2 | §8.11.4.3 |
Профиль воспроизводимости — структурный. Поле /ID в трейлере и атомы даты меняются при каждом сохранении. Тестовое окружение удаляет эти атомы и сравнивает структуру, нормализованную qpdf. Этот рецепт описывает, как NextPDF формирует такую структуру. Он не утверждает общее соответствие ISO 32000-2.
Коммерческий контекст
Заголовок раздела «Коммерческий контекст»Неприменимо. Группы необязательного содержимого — это возможность Core без ограничений для Premium.