Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11468 глав6256 карточек справочника
Дерево руководства

Глава 403 · С первых объектов и простейшего сохранения изображения

Gmagick: изображение, рисунок, цвет и обработка ошибок

Три роли объектов, полный указатель их методов, независимые копии и две отдельные ветви исключений с реальными результатами.

Связать изображение, команды рисования и объект цвета

Нужно нарисовать простую карточку. Для понимания объектов удобно разделить роли: Gmagick — само изображение, GmagickDraw — список действий и настройки кисти, GmagickPixel — описание цвета. Объект цвета не привязан к координате холста и сам ничего не закрашивает. Команды рисования тоже нужно применить к изображению.

$color = new GmagickPixel('#245f7a');
$draw = new GmagickDraw();
$draw->setFillColor($color);
$draw->rectangle(30, 35, 210, 125);
$image->drawImage($draw);

$image — светлый холст, созданный через newImage, как в первом примере. setFillColor связывает текущие настройки Draw с цветом; rectangle описывает прямоугольник от 30,35 до 210,125. drawImage превращает команды в пиксели текущего изображения. Ни одна из этих строк не сохраняет файл: для этого отдельно вызывается writeImage. Полный пример создаёт все три объекта самостоятельно, сохраняет состояния до/после и измеряет цвет внутри и снаружи фигуры. Аналогия «холст — список действий — краска» объясняет роли, но объект Gmagick также может хранить несколько кадров, а Pixel содержит компоненты/прозрачность, не банку физической краски.

Gmagick хранит светлый холст. Команды ещё не применены.
Gmagick хранит светлый холст. Команды ещё не применены.
GmagickPixel задал синий цвет, GmagickDraw — прямоугольник, drawImage применил команды к Gmagick.
GmagickPixel задал синий цвет, GmagickDraw — прямоугольник, drawImage применил команды к Gmagick.

Самостоятельный пример с входами и результатами

Связать изображение, команды рисования и объект цветаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm104-foundation-fixture.php';
gmRestore();

$image = new Gmagick();
$image->newImage(240,160,'#efe9d6','PNG');
gmPng($image,'gm104-obj-roles-blank.png');
$color = new GmagickPixel('#245f7a');
$draw = new GmagickDraw();
$draw->setFillColor($color);
$draw->rectangle(30,35,210,125);
$image->drawImage($draw);
gmPng($image,'gm104-obj-roles-card.png');

$checks=[
    'three_distinct_roles'=>$image instanceof Gmagick && $draw instanceof GmagickDraw && $color instanceof GmagickPixel,
    'center_filled'=>gmRgb('gm104-obj-roles-card.png',120,80)===[36,95,122],
    'outside_kept'=>gmRgb('gm104-obj-roles-card.png',5,5)===[239,233,214],
    'drawing_changed_image'=>!gmSame('gm104-obj-roles-blank.png','gm104-obj-roles-card.png')
];
gmReport('gm104-obj-roles',["gmagick.newimage", "gmagick.drawimage", "gmagickpixel.construct", "gmagickdraw.setfillcolor", "gmagickdraw.rectangle"],["gm104-obj-roles-blank.png", "gm104-obj-roles-card.png"],$checks,$errors??[],[]);
echo "roles: image=canvas draw=commands pixel=color\nResult=blue rectangle on light background; center RGB=36,95,122\n";
Ожидаемый результат
roles: image=canvas draw=commands pixel=color
Result=blue rectangle on light background; center RGB=36,95,122

Скачайте архив, распакуйте в отдельный каталог и выполните php example.php с Gmagick. Короткий фрагмент выше показывает само действие. Полный пример добавляет служебный gm104-foundation-fixture.php: он восстанавливает вложенные входы с SHA256, сохраняет PNG/JPEG и измерения metrics.json. Эти проверки нужны для воспроизводимости урока, а не для каждого обычного вызова API. Результаты и дополнительные JSON появятся после запуска. Вход workshop.ppm имеет собственный генератор make-input.py; где нужен DejaVuSans.ttf, вложены шрифт и лицензия.

Если вызван rectangle, но файл остаётся пустым, проверьте drawImage и то, какой объект вы затем сохраняете. Если нужен один кадр или целая последовательность, переходите к соответствующим методам Gmagick в каталоге ниже.

Полный официальный указатель Gmagick: 141 описаний. Каждая ссылка открывает уже существующую подробную карточку с параметрами, результатом и примерами. Эта обзорная глава не создаёт вторые конкурирующие карточки методов.

Все методы Gmagick (141)

Связанные основы: переменная, класс, объект и ->, массив и ключ, try/catch.

Прочитать цвет и явно применить его новую версию

В интерфейсе выбран цвет, а программе нужно получить его компоненты и построить два варианта плашки. GmagickPixel умеет хранить и менять цвет. Прочитаем компоненты в диапазоне 0..1 и переведём их в привычные RGB8 0..255; затем явно передадим новое значение в Draw перед второй фигурой.

$color = new GmagickPixel('#245f7a');
$red = $color->getColorValue(Gmagick::COLOR_RED);
echo round($red * 255); // 36
$color->setColor('#d25b2d');

Gmagick::COLOR_RED — именованная константа выбора канала, :: обращается к константе класса. getColorValue возвращает нормированную компоненту; round округляет её после умножения на 255. Это не координаты пикселя. Строка getColor() зависит от Quantum-сборки: в проверенной Q16 для первого цвета наблюдалось rgb(9252,24415,31354), поэтому строку нельзя автоматически читать как RGB8. В полном примере уже записанные команды первой фигуры остаются с первым цветом; второй setFillColor явно задаёт новый цвет для следующей фигуры.

Две плашки: первая RGB 36,95,122; вторая RGB 210,91,45. Новое значение Pixel передано в Draw явно перед второй фигурой.
Две плашки: первая RGB 36,95,122; вторая RGB 210,91,45. Новое значение Pixel передано в Draw явно перед второй фигурой.

Самостоятельный пример с входами и результатами

Прочитать цвет и явно применить его новую версиюСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm104-foundation-fixture.php';
gmRestore();

$pixel = new GmagickPixel('#245f7a');
$channels = [Gmagick::COLOR_RED,Gmagick::COLOR_GREEN,Gmagick::COLOR_BLUE];
$before = array_map(fn($channel)=>(int)round($pixel->getColorValue($channel)*255),$channels);
$image = gmCanvas();
$draw = new GmagickDraw();
$draw->setFillColor($pixel);
$draw->rectangle(20,35,105,125);
$pixel->setColor('#d25b2d');
$after = array_map(fn($channel)=>(int)round($pixel->getColorValue($channel)*255),$channels);
$draw->setFillColor($pixel);
$draw->rectangle(135,35,220,125);
$image->drawImage($draw);
gmPng($image,'gm104-obj-pixel-color-swatches.png');
gmJson('gm104-obj-pixel-color-colors.json',['first_rgb8'=>$before,'second_rgb8'=>$after,'native_string'=>$pixel->getColor()]);

$checks=[
    'first_rgb8'=>$before===[36,95,122],
    'second_rgb8'=>$after===[210,91,45],
    'left_pixel'=>gmRgb('gm104-obj-pixel-color-swatches.png',60,80)===[36,95,122],
    'right_pixel'=>gmRgb('gm104-obj-pixel-color-swatches.png',170,80)===[210,91,45]
];
gmReport('gm104-obj-pixel-color',["gmagickpixel.construct", "gmagickpixel.setcolor", "gmagickpixel.getcolorvalue", "gmagickpixel.getcolor", "gmagickdraw.setfillcolor", "gmagickdraw.rectangle", "gmagick.drawimage"],["gm104-obj-pixel-color-swatches.png"],$checks,$errors??[],[]);
echo "pixel: first RGB8=36,95,122 second RGB8=210,91,45\nTwo saved swatches=verified colors.json=written\n";
Ожидаемый результат
pixel: first RGB8=36,95,122 second RGB8=210,91,45
Two saved swatches=verified colors.json=written

Скачайте архив, распакуйте в отдельный каталог и выполните php example.php с Gmagick. Короткий фрагмент выше показывает само действие. Полный пример добавляет служебный gm104-foundation-fixture.php: он восстанавливает вложенные входы с SHA256, сохраняет PNG/JPEG и измерения metrics.json. Эти проверки нужны для воспроизводимости урока, а не для каждого обычного вызова API. Результаты и дополнительные JSON появятся после запуска. Вход workshop.ppm имеет собственный генератор make-input.py; где нужен DejaVuSans.ttf, вложены шрифт и лицензия.

Чтобы измерить цвет в конкретном месте картинки, сначала получите соответствующий пиксель изображения, а не создавайте новый Pixel и не ждите, что он связан с холстом. В служебной проверке берётся копия изображения, вырезается участок 1×1 и читается его гистограмма. Исходник сохраняется; API Imagick нельзя механически переносить в Gmagick.

Полный официальный указатель GmagickPixel: 6 описаний. Каждая ссылка открывает уже существующую подробную карточку с параметрами, результатом и примерами. Эта обзорная глава не создаёт вторые конкурирующие карточки методов.

Все методы GmagickPixel (6)

Связанные основы: переменная, класс, объект и ->, массив и ключ, try/catch.

Из реальной задачи разработчика

PHP GMagick: how to get pixel color?. Разработчик хочет получить цвет конкретного пикселя и пытается перенести метод Imagick в Gmagick. Объясняем отличие объекта цвета от координаты изображения. Измеряем пиксель через независимую копию 1×1 и нормированные компоненты; не предполагаем, что строка getColor всегда содержит RGB8.

Увидеть, когда команды Draw становятся пикселями

Хотим собрать рисунок из нескольких фигур, а затем применить его одним действием. Пока мы вызываем методы GmagickDraw, меняется список команд, но не пиксели холста. Это частая причина ситуации «все строки выполнены, картинка пустая». Сохраним реальный холст до drawImage и после него.

$draw = new GmagickDraw();
$draw->setFillColor(new GmagickPixel('#d25b2d'));
$draw->ellipse(170, 80, 42, 42, 0, 360);
$image->drawImage($draw);

У ellipse первые два числа задают центр, следующие два — радиусы, 0 и 360 — полный оборот. Без последней строки на $image ничего не нарисуется. Полная программа добавляет синий прямоугольник, создаёт две PNG-квитанции и сравнивает сигнатуру пикселей до команд, после команд и после применения. GmagickDraw не является самостоятельным PNG и не заменяет объект Gmagick. Настройки рисования действуют на добавляемые команды; для новой независимой задачи понятнее создать новый Draw.

После rectangle и ellipse в Draw: сам холст ещё пуст. Команды описаны, но drawImage не вызван.
После rectangle и ellipse в Draw: сам холст ещё пуст. Команды описаны, но drawImage не вызван.
После drawImage: синий прямоугольник и оранжевый круг появились в пикселях холста.
После drawImage: синий прямоугольник и оранжевый круг появились в пикселях холста.

Самостоятельный пример с входами и результатами

Увидеть, когда команды Draw становятся пикселямиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm104-foundation-fixture.php';
gmRestore();

$image = gmCanvas();
$before = $image->getImageSignature();
$draw = new GmagickDraw();
$draw->setFillColor(new GmagickPixel('#245f7a'));
$draw->rectangle(24,30,104,130);
$draw->setFillColor(new GmagickPixel('#d25b2d'));
$draw->ellipse(170,80,42,42,0,360);
$afterCommands = $image->getImageSignature();
gmPng($image,'gm104-obj-draw-buffer-pending.png');
$image->drawImage($draw);
gmPng($image,'gm104-obj-draw-buffer-rendered.png');

$checks=[
    'commands_do_not_mutate_canvas'=>$before===$afterCommands,
    'render_mutates_canvas'=>$image->getImageSignature()!==$before,
    'rectangle_center'=>gmRgb('gm104-obj-draw-buffer-rendered.png',60,80)===[36,95,122],
    'ellipse_center'=>gmRgb('gm104-obj-draw-buffer-rendered.png',170,80)===[210,91,45]
];
gmReport('gm104-obj-draw-buffer',["gmagickdraw.setfillcolor", "gmagickdraw.rectangle", "gmagickdraw.ellipse", "gmagick.drawimage"],["gm104-obj-draw-buffer-pending.png", "gm104-obj-draw-buffer-rendered.png"],$checks,$errors??[],[]);
echo "draw: commands-created canvas=unchanged\nAfter drawImage: rectangle+ellipse=visible\n";
Ожидаемый результат
draw: commands-created canvas=unchanged
After drawImage: rectangle+ellipse=visible

Скачайте архив, распакуйте в отдельный каталог и выполните php example.php с Gmagick. Короткий фрагмент выше показывает само действие. Полный пример добавляет служебный gm104-foundation-fixture.php: он восстанавливает вложенные входы с SHA256, сохраняет PNG/JPEG и измерения metrics.json. Эти проверки нужны для воспроизводимости урока, а не для каждого обычного вызова API. Результаты и дополнительные JSON появятся после запуска. Вход workshop.ppm имеет собственный генератор make-input.py; где нужен DejaVuSans.ttf, вложены шрифт и лицензия.

Перенесите сохранение PNG перед drawImage: получится первый пустой вариант. Верните сохранение после применения. Так можно определить момент, когда изображение действительно изменяется, не перебирая случайные параметры фигуры.

Полный официальный указатель GmagickDraw: 34 описаний. Каждая ссылка открывает уже существующую подробную карточку с параметрами, результатом и примерами. Эта обзорная глава не создаёт вторые конкурирующие карточки методов.

Все методы GmagickDraw (34)

Связанные основы: переменная, класс, объект и ->, массив и ключ, try/catch.

Сделать два результата, сохранив исходный объект

Сервису нужны маленькое превью и серый вариант одной схемы, но исходник должен остаться цветным и полным. В PHP присваивание объекта другой переменной не создаёт независимую копию. Для раздельных результатов используем clone и записываем каждый под собственным именем.

$source = new Gmagick(__DIR__ . '/workshop.ppm');
$alias = $source;
$preview = clone $source;
$preview->thumbnailImage(120, 80, true);

$alias и $source указывают на тот же объект; операция через любую из них изменяла бы его. clone создаёт отдельный объект Gmagick, поэтому уменьшение $preview не меняет размеры $source. В полном примере ещё одна копия преобразуется в серую с помощью именованного IMGTYPE_GRAYSCALE. Это уже изменение изображения, а не просто серый вид интерфейса. objects.json связывает сравнение объектов и размеры; три настоящих изображения показывают результат.

Оригинальный объект остаётся цветным и размером 240 × 160.
Оригинальный объект остаётся цветным и размером 240 × 160.
Независимая копия уменьшена до 120 × 80.
Независимая копия уменьшена до 120 × 80.
Другая независимая копия: серый вариант 240 × 160. Оригинал не переписан.
Другая независимая копия: серый вариант 240 × 160. Оригинал не переписан.

Самостоятельный пример с входами и результатами

Сделать два результата, сохранив исходный объектСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm104-foundation-fixture.php';
gmRestore();

$source = new Gmagick(__DIR__.'/workshop.ppm');
$alias = $source;
$preview = clone $source;
$preview->thumbnailImage(120,80,true);
$gray = clone $source;
$gray->setImageType(Gmagick::IMGTYPE_GRAYSCALE);
gmPng($source,'gm104-obj-clone-source-source.png');
gmPng($preview,'gm104-obj-clone-source-preview.png');
gmPng($gray,'gm104-obj-clone-source-gray.png');
$receipt = ['assignment_is_same_object'=>$alias===$source,'clone_is_different'=>$preview!==$source,
    'source_size'=>[$source->getImageWidth(),$source->getImageHeight()],
    'preview_size'=>[$preview->getImageWidth(),$preview->getImageHeight()]];
gmJson('gm104-obj-clone-source-objects.json',$receipt);

$checks=[
    'assignment_alias'=>$alias===$source,
    'independent_clone'=>$preview!==$source && $gray!==$source,
    'original_dimensions'=>$source->getImageWidth()===240 && $source->getImageHeight()===160,
    'preview_dimensions'=>$preview->getImageWidth()===120 && $preview->getImageHeight()===80,
    'original_pixels'=>gmSame('workshop.ppm','gm104-obj-clone-source-source.png'),
    'grayscale_channels'=>($g=gmRgb('gm104-obj-clone-source-gray.png',50,50))[0]===$g[1] && $g[1]===$g[2]
];
gmReport('gm104-obj-clone-source',["gmagick.construct", "gmagick.thumbnailimage", "gmagick.setimagetype", "gmagick.writeimage"],["gm104-obj-clone-source-source.png", "gm104-obj-clone-source-preview.png", "gm104-obj-clone-source-gray.png"],$checks,$errors??[],$receipt);
echo "objects: assignment=same-object clone=independent\nSource=240x160 preserved preview=120x80 grayscale=separate\n";
Ожидаемый результат
objects: assignment=same-object clone=independent
Source=240x160 preserved preview=120x80 grayscale=separate

Скачайте архив, распакуйте в отдельный каталог и выполните php example.php с Gmagick. Короткий фрагмент выше показывает само действие. Полный пример добавляет служебный gm104-foundation-fixture.php: он восстанавливает вложенные входы с SHA256, сохраняет PNG/JPEG и измерения metrics.json. Эти проверки нужны для воспроизводимости урока, а не для каждого обычного вызова API. Результаты и дополнительные JSON появятся после запуска. Вход workshop.ppm имеет собственный генератор make-input.py; где нужен DejaVuSans.ttf, вложены шрифт и лицензия.

Попробуйте заменить clone $source на $source при создании preview: после уменьшения исходный объект тоже станет маленьким. Не запускайте обе версии в производственной цепочке ради проверки — этот самостоятельный учебный вход позволяет увидеть разницу без потери оригинала.

Связанные основы: переменная, класс, объект и ->, массив и ключ, try/catch.

Поймать ошибку изображения и сохранить диагностическую причину

Файл отсутствует. Нужны две разные вещи: понятное сообщение вызывающей программе и подробности для разработчика. Поймаем именно GmagickException, сохраним сообщение/код/место/стек локально, затем покажем успешную обработку исправленного входа. Обработка исключения сама не создаёт отсутствующую фотографию.

try {
    $image = new Gmagick(__DIR__ . '/missing-image.png');
} catch (GmagickException $error) {
    echo $error->getMessage();
}

$error — объект исключения, который создала библиотека. getMessage возвращает текст причины; getCode — код библиотеки, не HTTP-статус. В реальном интерфейсе лучше короткий собственный статус, а путь и стек оставить в закрытом журнале. Полный пример сохраняет status.json и diagnostic.json, вызывает остальные унаследованные getters и оборачивает причину в RuntimeException через параметр previous. Исходная причина остаётся доступна через getPrevious; строковое представление получается через (string)$error. После выбора исправного файла создаётся показанное превью.

После исправления выбран вход workshop.ppm и создано превью 120 × 80. Исключение само не ремонтирует файл: программа повторяет работу с другим, исправным входом.
После исправления выбран вход workshop.ppm и создано превью 120 × 80. Исключение само не ремонтирует файл: программа повторяет работу с другим, исправным входом.

Самостоятельный пример с входами и результатами

Поймать ошибку изображения и сохранить диагностическую причинуСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm104-foundation-fixture.php';
gmRestore();

$caught = null;
try {
    new Gmagick(__DIR__.'/missing-image-104.png');
} catch (GmagickException $error) {
    $caught = $error;
}
if ($caught === null) { throw new RuntimeException('Expected missing-input error'); }
$publicStatus = ['status'=>'input_not_readable','message'=>'Choose an existing readable image'];
$diagnostic = ['class'=>get_class($caught),'message'=>$caught->getMessage(),'code'=>$caught->getCode(),
    'file'=>$caught->getFile(),'line'=>$caught->getLine(),'trace'=>$caught->getTrace(),
    'trace_text'=>$caught->getTraceAsString(),'previous'=>$caught->getPrevious(),
    'as_string'=>(string)$caught];
$wrapped = new RuntimeException('Catalog import failed',0,$caught);
gmJson('gm104-obj-image-error-status.json',$publicStatus);
gmJson('gm104-obj-image-error-diagnostic.json',$diagnostic);
$recovered = new Gmagick(__DIR__.'/workshop.ppm');
$recovered->thumbnailImage(120,80,true);
gmPng($recovered,'gm104-obj-image-error-recovered.png');
$errors=['missing_image'=>['ok'=>false,'class'=>get_class($caught),'message'=>$caught->getMessage()]];

$checks=[
    'specific_exception'=>$caught instanceof GmagickException,
    'not_pixel_exception'=>!($caught instanceof GmagickPixelException),
    'base_exception'=>$caught instanceof Exception,
    'diagnostic_message'=>$diagnostic['message']!=='',
    'diagnostic_location'=>$diagnostic['line']>0 && $diagnostic['file']!=='',
    'previous_chain'=>$wrapped->getPrevious()===$caught,
    'recovery'=>$recovered->getImageWidth()===120
];
gmReport('gm104-obj-image-error',["gmagick.construct", "gmagick.thumbnailimage", "gmagick.writeimage"],["gm104-obj-image-error-recovered.png"],$checks,$errors??[],$publicStatus);
echo "image-error: GmagickException caught; status+diagnostic saved\nOriginal cause retained as previous; repaired-input preview=120x80\n";
Ожидаемый результат
image-error: GmagickException caught; status+diagnostic saved
Original cause retained as previous; repaired-input preview=120x80

Скачайте архив, распакуйте в отдельный каталог и выполните php example.php с Gmagick. Короткий фрагмент выше показывает само действие. Полный пример добавляет служебный gm104-foundation-fixture.php: он восстанавливает вложенные входы с SHA256, сохраняет PNG/JPEG и измерения metrics.json. Эти проверки нужны для воспроизводимости урока, а не для каждого обычного вызова API. Результаты и дополнительные JSON появятся после запуска. Вход workshop.ppm имеет собственный генератор make-input.py; где нужен DejaVuSans.ttf, вложены шрифт и лицензия.

Ошибка одного изображения может быть обработана локально, но TypeError не следует объявлять повреждённым файлом: это ошибка вызова. Выбирайте catch по нужной категории, а общий Throwable используйте только там, где действительно нужна общая граница обработки с сохранением причины.

class GmagickException extends Exception
class GmagickPixelException extends Exception

Это схема наследования, не код для повторного объявления встроенных классов. В проверенной реализации расширения эти два класса final; наследовать собственную ошибку от них не требуется. Для дополнительного контекста создайте RuntimeException с исходной ошибкой в previous, как в примере. Базовый Exception реализует Throwable. Код ошибки, текст, место создания и цепочка причин читаются через методы.

Унаследованное состояниеДоступ / смыслКак прочитать
$messageprotected; текст причиныgetMessage()
$codeprotected; код исключенияgetCode()
$fileprotected; файл созданияgetFile()
$lineprotected; строка созданияgetLine()
$traceprivate в Exception; массив кадров стекаgetTrace()
$previousprivate в Exception; предшествующий Throwable либо nullgetPrevious()
$stringprivate в Exception; строковое представление стека(string) $error / __toString()
Унаследованный методЧто даёт
__construct($message = "", $code = 0, $previous = null)Создаёт исключение. message — строка, code — int, previous — Throwable либо null. Для штатных сбоев Gmagick объект создаёт библиотека.
getMessage(): stringТекст причины.
getCode(): intКод причины; не HTTP-код ответа.
getFile(): stringПуть к месту создания исключения.
getLine(): intНомер строки создания.
getTrace(): arrayКадры стека как массив.
getTraceAsString(): stringСтек в читаемом текстовом виде.
getPrevious(): ?ThrowableПредыдущая причина либо null.
__toString(): stringСтроковое представление объекта с диагностикой.
__clone(): voidЗакрытый метод Exception: клонирование исключения не является доступной операцией.

Методы getMessage/getCode/getFile/getLine/getTrace/getTraceAsString/getPrevious final; их поведение не переопределяют в потомке. В Reflection PHP 8.3 также виден служебный __wakeup, связанный с восстановлением объекта; он не нужен для обработки файла и не вызывается вручную. Короткая официальная страница PixelException не перечисляет свойства отдельно, но свойства базового Exception и механизм getters относятся и к этой ветви. Подробно: исключения, try/catch и цепочка previous.

Связанные основы: переменная, класс, объект и ->, массив и ключ, try/catch.

Отделить неверный цвет от ошибки файла и ошибки типа

Пользователь выбрал неизвестное имя цвета. Это ошибка Pixel, а не чтения изображения. Поймаем GmagickPixelException, явно применим согласованный резервный цвет и вернём признак fallback_used. Дополнительно сравним неверное имя, ошибку setColor и передачу массива вместо строки.

try {
    $color = new GmagickPixel('not-a-color');
} catch (GmagickPixelException $error) {
    $color = new GmagickPixel('#245f7a');
}

GmagickPixelException и GmagickException — две отдельные ветви, каждая наследует Exception. catch (GmagickException) не поймает ошибку Pixel. Массив вместо имени цвета даёт TypeError, который наследует Error и относится к общему Throwable, но не Exception. В полном примере неверный цвет отклоняется библиотекой, fallback используется по явно заданной политике приложения, а факт замены записывается в errors.json. Для задач, где молчаливое изменение фирменного цвета недопустимо, вместо резервного цвета верните пользователю ошибку и попросите исправить ввод.

Непонятное имя цвета отклонено; приложение явно выбрало согласованный резервный #245f7a и сообщило об этом. Это политика данного примера, не скрытое поведение Gmagick.
Непонятное имя цвета отклонено; приложение явно выбрало согласованный резервный #245f7a и сообщило об этом. Это политика данного примера, не скрытое поведение Gmagick.

Самостоятельный пример с входами и результатами

Отделить неверный цвет от ошибки файла и ошибки типаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm104-foundation-fixture.php';
gmRestore();

$errors = [];
try {
    $color = new GmagickPixel('not-a-color-104');
} catch (GmagickPixelException $error) {
    $errors['invalid_color'] = ['ok'=>false,'class'=>get_class($error),'message'=>$error->getMessage()];
    $color = new GmagickPixel('#245f7a');
}
$errors['invalid_set'] = gmTry(fn()=>(new GmagickPixel('#245f7a'))->setColor('not-a-color-104'));
$errors['wrong_type'] = gmTry(fn()=>new GmagickPixel([]));
$image = gmCanvas();
$draw = new GmagickDraw();
$draw->setFillColor($color);
$draw->rectangle(30,35,210,125);
$image->drawImage($draw);
gmPng($image,'gm104-obj-pixel-error-fallback.png');
$status = ['selected_color'=>'#245f7a','fallback_used'=>isset($errors['invalid_color']),
    'pixel_exception_parent'=>get_parent_class('GmagickPixelException'),
    'image_exception_parent'=>get_parent_class('GmagickException'),
    'same_exception_branch'=>is_subclass_of('GmagickPixelException','GmagickException')];
gmJson('gm104-obj-pixel-error-errors.json',$status);

$checks=[
    'fallback_reported'=>$status['fallback_used']===true,
    'pixel_parent_exception'=>$status['pixel_exception_parent']==='Exception',
    'image_parent_exception'=>$status['image_exception_parent']==='Exception',
    'separate_exception_branches'=>$status['same_exception_branch']===false,
    'visible_fallback_color'=>gmRgb('gm104-obj-pixel-error-fallback.png',120,80)===[36,95,122]
];
gmReport('gm104-obj-pixel-error',["gmagickpixel.construct", "gmagickpixel.setcolor", "gmagickdraw.setfillcolor", "gmagickdraw.rectangle", "gmagick.drawimage"],["gm104-obj-pixel-error-fallback.png"],$checks,$errors??[],$status);
echo "color-error: invalid name/set=GmagickPixelException array=TypeError\nFallback=#245f7a reported; PixelException is not GmagickException\n";
Ожидаемый результат
color-error: invalid name/set=GmagickPixelException array=TypeError
Fallback=#245f7a reported; PixelException is not GmagickException

Скачайте архив, распакуйте в отдельный каталог и выполните php example.php с Gmagick. Короткий фрагмент выше показывает само действие. Полный пример добавляет служебный gm104-foundation-fixture.php: он восстанавливает вложенные входы с SHA256, сохраняет PNG/JPEG и измерения metrics.json. Эти проверки нужны для воспроизводимости урока, а не для каждого обычного вызова API. Результаты и дополнительные JSON появятся после запуска. Вход workshop.ppm имеет собственный генератор make-input.py; где нужен DejaVuSans.ttf, вложены шрифт и лицензия.

Примените другой разрешённый резервный цвет и проверьте центр сохранённого прямоугольника. В интерфейсе сохраняйте статус замены: успешная запись PNG ещё не означает, что запрошенный цвет был принят.

Полный унаследованный интерфейс — message/code/file/line/trace/previous/string и методы Exception — разобран рядом с GmagickException. Он относится и к GmagickPixelException; различаются категория ошибки и место её возникновения, а не смысл getMessage или getPrevious.

Связанные основы: переменная, класс, объект и ->, массив и ключ, try/catch.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.