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

Дерево руководства
Глава 131 · От строк к межпроцессному обмену
Shmop: общий блок байтов и полный справочник
Все шесть функций и класс Shmop: режимы, смещения, неполная запись, формат пакета и жизненный цикл.
Общий блок байтов: что это и зачем
Локальный сборщик телеметрии подготовил пакет байтов, а PHP обработчик должен его прочитать. Если оба процесса работают в одной ОС и договорились о формате, они могут использовать общий сегмент памяти. shmop предоставляет именно чтение и запись байтов по позиции. В отличие от sysvshm, здесь нет ключей PHP переменных и автоматической сериализации массива.
- Общий блок: позиции 0…7
- Позиции 0…3: A42| — код товара
- Позиции 4…7: 0007 — текстовое число
- read(0,4) получил A42|
- read(4,4) получил 0007
Модель — линейка с ячейками размером в один байт. Вы сами договариваетесь, где начинается поле и как распознаётся конец. Это не массив с ключами, не поток с автоматически растущим курсором и не база данных. Условный пример использует ASCII, чтобы одна буква занимала один байт; русский текст UTF-8 требует считать байты отдельно от символов.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$packet = 'A42|0007';
$written = shmop_write($block, $packet, 0);
if ($written !== strlen($packet)) throw new RuntimeException('Пакет записан не целиком');
echo shmop_read($block, 0, 4), "\n";
echo shmop_read($block, 4, 4), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
A42|
0007
$block — ручка блока, строка $packet — содержимое, 0 — первая позиция. strlen считает байты. Третий аргумент read — сколько байтов взять, третий аргумент write — откуда писать. finally помечает собственный сегмент к удалению и освобождает объект.
Установка, платформы, объекты и файлы примеров
При сборке PHP расширение включается --enable-shmop; у пакетной установки проверьте совместимый модуль своего дистрибутива. На Windows существует php_shmop.dll и реализация через Windows mappings. В PHP 8.0 функция open возвращает объект Shmop вместо resource. Наличие shmop не означает наличия sysvsem: это независимые расширения.
| Часть настройки | Смысл |
|---|---|
| Проверка | extension_loaded("shmop") / function_exists("shmop_open") именно в используемом SAPI. CLI и PHP-FPM могут иметь разные ini. |
| INI / константы | У shmop нет собственного набора runtime ini директив и предопределённых констант. Размер задаётся при создании, системные лимиты относятся к ОС. |
| Windows / Unix | Права Unix 0600 и жизненный цикл IPC_RMID нельзя без проверки перенести на mappings Windows. Тестируемые примеры здесь создают только приватные блоки key=0 внутри одного процесса. |
| Общее окружение | Одинаковый key в разных IPC namespaces/контейнерах не означает один блок. Две физические машины не разделяют System V shared memory. |
| Объект | Shmop — непрозрачная ручка без публичных методов/свойств. Освобождается автоматически после исчезновения всех PHP ссылок. |
<?php
function lessonBytes(int $capacity = 256): Shmop {
$block = shmop_open(0, 'n', 0600, $capacity);
if ($block === false) throw new RuntimeException('Не создан учебный блок');
return $block;
}
Ожидаемый результат
Объявлена функция lessonBytes; блок создастся только при её вызове.
key=0 означает IPC_PRIVATE. Каждый вызов создаёт отдельный блок и не подключается к чужому. Вне этого файла примеры оборачивают работу в try/finally. При Windows процессы проверки дополнительно завершаются и освобождают собственные mapping handles. Это контекстный пример для указанной среды; здесь проверен синтаксис, многопроцессное выполнение не заявляется.
Четыре режима и владение жизненным циклом
Для независимых участников нужен согласованный ненулевой key, например через ftok. Key не уникален автоматически и не является секретом авторизации. Владелец создаёт новый блок режимом n и не удаляет чужой, если n вернул отказ. Читатель открывает существующий a, писатель w. Режим c удобен для open-or-create, но не сообщает, кто создал блок: первый писатель не должен без протокола обнулять уже существующие данные.
| Режим | Поведение |
|---|---|
| a | Открыть существующий только для чтения; permissions=0, size=0. |
| w | Открыть существующий для чтения/записи; permissions=0, size=0. |
| c | Создать либо открыть существующий read/write. Положительный size нужен для режима создания; существующий блок не расширяется. |
| n | Создать новый эксклюзивно; существующий ненулевой key даёт отказ. key=0 — специальное создание приватного блока. |
На Unix попытка открыть существующий меньший сегмент через c с большим size может дать EINVAL. Это не команда увеличить память. Для изменения ёмкости нужен отдельный новый сегмент, перенос под согласованной блокировкой, переключение участников и последующее удаление старого. Не делайте delete/open поверх активных readers.
Длина, кодировка и граница сообщения
Объём блока и длина полезного сообщения — разные числа. Если сначала записать восемь байтов, а потом два в offset=0, оставшиеся шесть не исчезнут. Для двоичного протокола храните точную длину. trim/rtrim не является универсальным решением: нулевой байт может быть частью легальных данных.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$json = json_encode(['sku' => 'A42', 'qty' => 7], JSON_THROW_ON_ERROR);
$length = strlen($json);
$header = pack('N', $length);
$packet = $header . $json;
if (strlen($packet) > shmop_size($block)) throw new LengthException('Пакет не помещается');
if (shmop_write($block, $packet, 0) !== strlen($packet)) throw new RuntimeException('Короткая запись');
$decodedHeader = unpack('Nlength', shmop_read($block, 0, 4));
$payloadLength = $decodedHeader['length'];
if ($payloadLength < 1 || $payloadLength > shmop_size($block) - 4) throw new RuntimeException('Неверная длина');
$payload = shmop_read($block, 4, $payloadLength);
$stock = json_decode($payload, true, 512, JSON_THROW_ON_ERROR);
if (!is_array($stock) || !is_string($stock['sku'] ?? null) || !is_int($stock['qty'] ?? null)) {
throw new RuntimeException('Неверная структура');
}
echo $stock['sku'], ': ', $stock['qty'], "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
A42: 7
pack("N") — четырёхбайтовое беззнаковое целое в сетевом порядке байтов; unpack восстанавливает его. Все стороны должны согласовать этот формат. Этот пример однопроцессный: одна memcpy запись не обещает атомарности целого пакета при конкуренции.
Для реального обмена добавьте версию формата, допустимый предел длины, явную инициализацию и один общий механизм блокировки для writers и readers. Сначала захват, затем чтение длины и тела в одном участке, затем освобождение. Отдельная запись «готово» не делает произвольный протокол атомарным. Нельзя объявлять отсутствие гонок только потому, что длина записана последней. Синхронизация и memory ordering требуют гарантированного общего примитива.
Освобождение ссылки, delete и устаревший close
С PHP 8 shmop_close устарела и ничего не делает. Для прекращения собственного доступа освободите все ссылки на объект: unset одной переменной недостаточно, если тот же объект хранится в другой. Для удаления системного блока нужен shmop_delete владельцем до освобождения его последней ручки. Unix может держать помеченный сегмент, пока другие участники подключены. Windows mappings имеют собственные правила lifetime; успешный delete не является переносимым обещанием немедленного пересоздания того же key.
Общий блок не долговечен как база данных. Планируйте восстановление после перезапуска, срок жизни данных и остановку участников. Не вызывайте delete при каждом чтении — это решение владельца после координации. Для завершения примеров key0 гарантирует изоляцию; для проекта храните договор key/владельца/версии, а не список всех ресурсов ОС для массового удаления.
Стоимость, альтернативы и задания
| Потребность | Что выбрать/измерять |
|---|---|
| PHP массивы между процессами | sysvshm сам сериализует переменные, но тоже требует lock; shmop нужен, когда вы управляете форматом байтов. |
| Команда обработчику | Очередь сообщений либо socket часто выражает запрос/ответ яснее, чем ручная общая структура. |
| Состояние магазина после перезапуска | База данных/надёжное хранилище; блок памяти не заменяет транзакции и долговечность. |
| Большой пакет | read создаёт PHP строку длиной N, write копирует данные. Учитывайте копирование/декодирование и пиковую память. |
| Частые мелкие операции | Считайте overhead блокировок, число копий, размер пакета и время ожидания; нет универсальной гарантии превосходства над кешем/БД. |
Практика: замените второй write в карточке write на запись по offset=strlen первой строки — получится склейка без перекрытия. Затем сократите JSON payload: при framing читатель возьмёт только новую длину, старый хвост не попадёт в JSON. Для текста «Привет» сравните strlen с числом символов; не разрезайте UTF-8 на произвольном байте. Следующие темы: IPC и семафоры, локальные sockets, байтовые строки.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
shmop_openСоздать блок или подключиться с нужными правами доступа.
PHP 4.0.4+ · shmop
shmop_open(int $key, string $mode, int $permissions, int $size): Shmop|falseСоздать блок или подключиться с нужными правами доступа.
Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.
Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.
| Договор | Значение |
|---|---|
| key | IPC ключ; 0 новый приватный блок. Для общего ненулевого key проверяйте ftok/namespace/владение. |
| mode | Одна буква a read-only existing, w read/write existing, c open-or-create, n exclusive create. |
| permissions | Восьмеричные биты при создании, 0 для a/w. |
| size | Положительные байты для c/n; 0 при a/w. Не увеличивает existing block. |
| Отказ | false и E_WARNING от ОС; неверный mode/size создания — ValueError. PHP8 вернул объект вместо resource. |
- key0 + n + 0600 + 128
- ОС создала отдельный блок
- open → Shmop
- size проверяет реальную ёмкость
Нужно место для небольшого бинарного пакета. Все четыре аргумента обязательны: key выбирает системный сегмент, mode определяет создание/доступ, permissions — Unix права, size — запрошенную ёмкость в байтах. Режим n с приватным key0 подходит для самостоятельного эксперимента.
<?php
declare(strict_types=1);
$block = shmop_open(0, 'n', 0600, 128);
if ($block === false) throw new RuntimeException('Не создан блок');
try { echo shmop_size($block) >= 128 ? "Места достаточно\n" : "Проверьте размер\n"; }
finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Места достаточно
0600 — восьмеричные права. Фактический размер узнают функцией size; пример не угадывает платформенные накладные расходы и не использует чужой key.
<?php
declare(strict_types=1);
try { shmop_open(0, 'rw', 0600, 128); }
catch (ValueError $error) { echo "Нужна одна буква режима: a, w, c или n\n"; }
Ожидаемый результат
Нужна одна буква режима: a, w, c или n
rw похоже на файловый режим, но shmop принимает ровно одну допустимую букву. Нулевая ёмкость запрещена для c/n; у a/w при открытии существующего используют size=0.
<?php
declare(strict_types=1);
$key = ftok(__DIR__ . '/app.ipc', 'B');
if ($key === -1 || $key === 0) throw new RuntimeException('Нет общего ключа');
$block = shmop_open($key, 'a', 0, 0);
if ($block === false) throw new RuntimeException('Владелец ещё не создал блок либо нет доступа');
try { echo shmop_read($block, 0, 4), "\n"; }
finally { unset($block); }
Ожидаемый результат
A42| — если владелец учебного Unix сервиса создал согласованный блок с таким заголовком.
Только ваш выделенный IPC namespace и файл app.ipc, общий с владельцем. Читатель не удаляет сегмент. Если для actual payload нужны согласованные чтения, вокруг чтения применяется общий lock. Это контекстный пример для указанной среды; здесь проверен синтаксис, многопроцессное выполнение не заявляется.
Рядом: shmop_size, shmop_write, shmop_delete.
shmop_sizeУзнать ёмкость блока в байтах.
PHP 4.0.4+ · shmop
shmop_size(Shmop $shmop): intУзнать ёмкость блока в байтах.
Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.
Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.
| Договор | Значение |
|---|---|
| shmop | Валидный объект open. |
| Результат | Размер сегмента, не длина payload и не свободное место. |
| Версия | В PHP8 аргумент Shmop, прежде resource. |
- open запросил блок
- size вернул доступный объём
- strlen посчитал пакет
- сравнили до записи
Узнать ёмкость нужно до размещения пакета. Это весь блок, включая незаполненную область; функция ничего не знает о том, сколько байтов последняя запись считала полезными. Собственную длину payload храните в согласованном формате.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$payload = 'A42|0007';
$capacity = shmop_size($block);
echo strlen($payload) <= $capacity ? "Пакет помещается\n" : "Пакет слишком большой\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Пакет помещается
Сравниваются байты. Проверка не резервирует блок для текущего процесса; конкурентные writers всё равно должны иметь общий lock.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$before = shmop_size($block);
shmop_write($block, 'OK', 0);
$after = shmop_size($block);
echo $before === $after ? "Ёмкость прежняя\n" : "Ёмкость изменилась\n";
echo 'Полезных байтов сейчас: ', strlen('OK'), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Ёмкость прежняя
Полезных байтов сейчас: 2
Чтение всей ёмкости вернуло бы также незанятый/старый хвост. Это не способ узнать длину нового сообщения.
Рядом: shmop_open, shmop_read, shmop_write.
shmop_readСкопировать выбранные байты в PHP строку.
PHP 4.0.4+ · shmop
shmop_read(Shmop $shmop, int $offset, int $size): stringСкопировать выбранные байты в PHP строку.
Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.
Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.
| Договор | Значение |
|---|---|
| offset | Байтовое смещение от 0 до ёмкости включительно. |
| size | Байты; 0 означает остаток блока. Положительный размер не должен пересекать конец. |
| Результат | Binary-safe string, включая нули. В PHP8 диапазоны нарушены → ValueError. |
- Пакет A42|0007
- offset=4, size=4
- прочитаны байты 0007
- преобразованы после проверки формата
Чтобы прочитать код товара, указывают начало поля и его длину. Результат — PHP строка, которая умеет хранить нулевые байты. Чтение не удаляет данные и не изменяет позицию следующего чтения: каждый offset задаётся заново.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
shmop_write($block, 'A42|0007', 0);
$quantityText = shmop_read($block, 4, 4);
echo 'Количество: ', (int)$quantityText, "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Количество: 7
В согласованном учебном ASCII формате поле 4…7 содержит четыре десятичные цифры. Для внешних данных проверяйте формат до (int), иначе мусор может превратиться в неожиданное число.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$capacity = shmop_size($block);
shmop_write($block, 'END', $capacity - 3);
echo shmop_read($block, $capacity - 3, 0), "\n";
echo strlen(shmop_read($block, $capacity, 0)), "\n";
try { shmop_read($block, $capacity, 1); }
catch (ValueError $error) { echo "За границей блока\n"; }
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
END
0
За границей блока
size=0 означает «до конца», а не всегда пустую строку. Только offset в самом конце даёт пустой результат; запрос хотя бы одного байта за концом запрещён.
offset и size неотрицательны, offset ≤ capacity, offset+size ≤ capacity. В PHP8 нарушение вызывает ValueError, а не старое false. Не передавайте непроверенную длину из заголовка: прежде убедитесь, что она помещается. Чтение нескольких полей по отдельности может смешать версии при параллельной записи; даже одна read не объявлена атомарным снимком произвольного пакета.
Рядом: shmop_size, shmop_write.
shmop_writeЗаменить байты и узнать фактически записанное количество.
PHP 4.0.4+ · shmop
shmop_write(Shmop $shmop, string $data, int $offset): intЗаменить байты и узнать фактически записанное количество.
Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.
Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.
| Договор | Значение |
|---|---|
| data | Binary-safe строка; PHP массив сперва нужно закодировать по договору. |
| offset | От 0 до capacity. offset=capacity законен и даёт 0 записанных байтов. |
| Результат | min(strlen(data), capacity-offset). Проверяйте полную длину. |
| Ошибки PHP8.5 | Неверный offset — ValueError; read-only attachment — Error; неправильный тип — TypeError. |
- В блоке ABCDEFGH
- write OK с offset0
- заменены только A и B
- итог OKCDEFGH
Запись заменяет байты по указанному offset. Она не добавляет данные в конец автоматически, не обнуляет оставшийся хвост и не расширяет блок. Возвращается число действительно записанных байтов; при нехватке места хвост строки не записывается, поэтому сравнение с strlen обязательно.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
shmop_write($block, 'ABCDEFGH', 0);
shmop_write($block, 'OK', 0);
echo shmop_read($block, 0, 8), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
OKCDEFGH
Если новое сообщение должно быть только OK, читатель обязан знать длину 2. Для фиксированного текстового поля можно явно дополнить поле согласованным padding, но это правило формата, не автоматизм write.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$capacity = shmop_size($block);
$payload = 'ABCDEF';
$written = shmop_write($block, $payload, $capacity - 3);
echo 'Записано: ', $written, ' из ', strlen($payload), "\n";
echo shmop_read($block, $capacity - 3, 3), "\n";
echo shmop_write($block, 'X', $capacity), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Записано: 3 из 6
ABC
0
Запись внутри допустимого offset может быть короткой без исключения. В самом конце остаётся ноль места: вернётся 0. Перед изменением целого пакета лучше заранее проверить capacity и защищать операцию общим lock.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$first = 'A42|';
$second = '0007';
$packetLength = strlen($first) + strlen($second);
if ($packetLength > shmop_size($block)) throw new LengthException('Не помещается');
if (shmop_write($block, $first, 0) !== strlen($first)) throw new RuntimeException('Первая запись короткая');
if (shmop_write($block, $second, strlen($first)) !== strlen($second)) throw new RuntimeException('Вторая запись короткая');
echo shmop_read($block, 0, $packetLength), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
A42|0007
Смещение второй строки — число байтов первой. Два write не становятся одной атомарной операцией: другие процессы должны читать их под общей блокировкой либо по иному корректному протоколу публикации.
PHP 8.5.11 при записи в read-only объект выбрасывает Error, хотя краткая таблица manual объединяет этот случай с ValueError диапазона. offset вне 0…capacity вызывает ValueError. У Shmop нет встроенного compare-and-swap; read → увеличить число → write без синхронизации теряет обновления. Для UTF-8 strlen и offsets относятся к байтам: частичная запись может оборвать символ.
Рядом: shmop_read, shmop_size.
shmop_deleteПометить системный сегмент к удалению владельцем.
PHP 4.0.4+ · shmop
shmop_delete(Shmop $shmop): boolПометить системный сегмент к удалению владельцем.
Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.
Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.
| Договор | Значение |
|---|---|
| shmop | Ручка принадлежащего приложению сегмента. |
| Результат | true запрос принят, false и warning при системном отказе, например нет полномочий владельца. |
| Lifetime | Unix удаление завершается после последнего detach. Windows mappings имеют иной жизненный цикл. |
- Владелец остановил группу
- delete запросил удаление
- последние объекты освободились
- Unix удалил сегмент
Когда закончилась вся группа участников, владелец освобождает системный ресурс. На Unix функция помечает сегмент к удалению; физически он сохраняется, пока остаются подключения. Поэтому слово delete не означает, что переменная Shmop тут же стала null или память немедленно исчезла у всех читателей.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes();
try {
if (!shmop_delete($block)) throw new RuntimeException('Не отмечен к удалению');
echo "Владелец запросил удаление\n";
} finally { unset($block); }
Ожидаемый результат
Владелец запросил удаление
Только приватный блок текущего эксперимента. unset освобождает единственную ссылку PHP; на Windows окончательный lifetime дополнительно связан с mapping handles процесса.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes();
try {
try { throw new RuntimeException('Неверный пакет'); }
finally { shmop_delete($block); unset($block); echo "Учебный ресурс завершён\n"; }
} catch (RuntimeException $error) { echo "Ошибка обработки учтена\n"; }
Ожидаемый результат
Учебный ресурс завершён
Ошибка обработки учтена
В production один reader не удаляет общий блок в своём finally; это делает владелец после остановки всей группы. Здесь ресурс был создан только ради примера.
Рядом: shmop_open, shmop_close.
shmop_closeУстаревший вызов закрытия: в PHP8 не оказывает действия.
PHP 4.0.4+ · shmop
shmop_close(Shmop $shmop): void // deprecated since PHP 8.0Устаревший вызов закрытия: в PHP8 не оказывает действия.
Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.
Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.
| Договор | Значение |
|---|---|
| Аргумент | В PHP8 Shmop, в старых версиях resource. |
| Результат | void; в PHP8 NOP с уведомлением об устаревании. |
| Замена | Освободить все ссылки на объект. Для владельца системного ресурса отдельно shmop_delete. |
- Старый код вызвал close
- PHP8 сообщает deprecated
- объект всё ещё доступен
- lifetime завершает освобождение последней ссылки
Эта функция нужна читателю для понимания старого кода, а не для нового шаблона cleanup. Начиная с PHP8.0 она deprecated и ничего не делает: объект освобождается автоматически, когда на него больше нет ссылок. Старое resource-закрытие из PHP7 переносится не механически.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
shmop_write($block, 'OK', 0);
set_error_handler(static fn() => true, E_DEPRECATED);
try { shmop_close($block); }
finally { restore_error_handler(); }
echo shmop_read($block, 0, 2), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
OK
Deprecation подавлена только для исторического демонстрационного вызова. После него объект остаётся рабочим. В новом коде такой вызов удаляют, а не скрывают предупреждение на всём сайте.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes();
$reader = $block;
unset($block);
try {
shmop_write($reader, 'OK', 0);
echo shmop_read($reader, 0, 2), "\n";
} finally { shmop_delete($reader); unset($reader); }
Ожидаемый результат
OK
Присваивание объекта создало ещё одну ссылку на ту же ручку, не копию сегмента. unset первой переменной не закрывает объект, пока он доступен через $reader.
Рядом: shmop_delete, shmop_open.
ShmopНепрозрачная ручка блока байтов PHP8.
PHP 8.0+ · shmop
final class ShmopНепрозрачная ручка блока байтов PHP8.
Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.
Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.
| Договор | Значение |
|---|---|
| Создание | shmop_open → Shmop|false. new запрещён. |
| Работа | Передать объект в shmop_read/write/size/delete. |
| Ограничения | Нет публичных пользовательских членов; не сериализуется/не клонируется. |
| Освобождение | Автоматическое после последней ссылки; не заменяет delete системного сегмента. |
- open вернул Shmop
- read скопировал байты в строку
- объект передали другой переменной
- последний unset освобождает attachment
Shmop — final класс расширения, введённый в PHP8 вместо resource. У него нет пользовательских методов, свойств и открытого конструктора. Он обозначает attachment к системному блоку. Данные по-прежнему читаются функциями shmop_read/write, а не $block->data.
<?php
declare(strict_types=1);
require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
echo $block instanceof Shmop ? "Объект Shmop\n" : "Другой тип\n";
echo is_resource($block) ? "resource\n" : "Это уже не resource\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Объект Shmop
Это уже не resource
Обновление PHP7→8 требует изменить resource checks. Проверка типа не подтверждает формат данных и наличие требуемой блокировки.
<?php
declare(strict_types=1);
try { new Shmop(); }
catch (Error $error) { echo "Используйте shmop_open\n"; }
Ожидаемый результат
Используйте shmop_open
Непосредственное создание запрещено: объект должен получить действующий attachment. Сериализация, клонирование и добавление динамических свойств тоже не поддержаны.
Рядом: shmop_open, shmop_close, shmop_delete.
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


