{"id":19925148,"url":"https://github.com/sa2kasov/php-reference-guide","last_synced_at":"2026-05-07T05:32:06.664Z","repository":{"id":59102707,"uuid":"534381521","full_name":"sa2kasov/php-reference-guide","owner":"sa2kasov","description":"Reference Guide of PHP with MySQL, OOP, and other","archived":false,"fork":false,"pushed_at":"2022-10-29T21:14:00.000Z","size":67,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-06T02:18:31.126Z","etag":null,"topics":["mysql","php","php-oop","php-reference","sqlite3"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sa2kasov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-09-08T20:25:01.000Z","updated_at":"2022-11-10T21:22:40.000Z","dependencies_parsed_at":"2023-01-20T15:10:30.421Z","dependency_job_id":null,"html_url":"https://github.com/sa2kasov/php-reference-guide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sa2kasov/php-reference-guide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sa2kasov%2Fphp-reference-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sa2kasov%2Fphp-reference-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sa2kasov%2Fphp-reference-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sa2kasov%2Fphp-reference-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sa2kasov","download_url":"https://codeload.github.com/sa2kasov/php-reference-guide/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sa2kasov%2Fphp-reference-guide/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32724487,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-07T02:14:30.463Z","status":"ssl_error","status_checked_at":"2026-05-07T02:14:29.405Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mysql","php","php-oop","php-reference","sqlite3"],"created_at":"2024-11-12T22:20:37.412Z","updated_at":"2026-05-07T05:32:06.648Z","avatar_url":"https://github.com/sa2kasov.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg\n      src=\"https://www.php.net/images/logos/new-php-logo.svg\"\n      width=\"400\"\n      alt=\"PHP Logo\"\n    /\u003e\n\u003c/p\u003e\n\n# Справочное руководство по PHP\n\n### Содержание\n\n1. [Предыстория](#Предыстория)\n2. [Интерпретатор PHP](#Интерпретатор-PHP)\n   1. [Связка с веб-сервером Apache](#Связка-с-веб-сервером-Apache)\n3. [Синтаксис языка](#Синтаксис-языка)\n   1. [PHP–теги](#PHP–теги)\n   2. [Комментарии](#Комментарии)\n4. [Hello, World!](#Hello,-World!)\n5. [Переменные](#Переменные)\n   1. [Экранирование переменных](#Экранирование-переменных)\n   2. [Присвоение по ссылке](#Присвоение-по-ссылке)\n6. [Ошибки](#Ошибки)\n7. [Типы данных](#Типы-данных)\n   1. [Boolean](#boolean)\n   2. [Integer и Float](#Integer-и-Float)\n   3. [String](#String)\n      1. [Синтаксис heredoc и nowdoc](#Синтаксис-heredoc-и-nowdoc)\n      2. [Доступ к символу в строке](#Доступ-к-символу-в-строке)\n   4. [NULL](#NULL)\n8. [Операторы](#Операторы)\n   1. [Арифметические](#Арифметические)\n   2. [Строковые](#Строковые)\n   3. [Операторы сравнения](#Операторы-сравнения)\n   4. [Логические операторы](#Логические-операторы)\n9. [Полезные функции](#Полезные-функции)\n10. [Управляющие конструкции](#Управляющие-конструкции)\n    1. [if](#if)\n    2. [if..else..](#ifelse)\n    3. [if..elseif..else..](#ifelseifelse)\n    4. [Альтернативный синтаксис](#Альтернативный-синтаксис)\n    5. [Тернарный оператор](#Тернарный-оператор)\n    6. [switch](#switch)\n    7. [try..catch](#trycatch)\n11. [Массивы](#Массивы)\n    1. [Нумерованный массив](#Нумерованный-массив)\n    2. [Ассоциативный массив](#Ассоциативный-массив)\n    3. [Многомерный массив](#Многомерный-массив)\n    4. [Работа с массивами](#Работа-с-массивами)\n       1. [Печать массива](#Печать-массива)\n       2. [Подсчёт элементов массива](#Подсчёт-элементов-массива)\n       3. [Встраивание массива в строки](#Встраивание-массива-в-строки)\n       4. [Перемещение указателя массива](#Перемещение-указателя-массива)\n12. [Константы](#Константы)\n    1. [Магические константы](#Магические-константы)\n13. [Циклы](#Циклы)\n    1. [for](#for)\n    2. [while](#while)\n    3. [do..while](#dowhile)\n    4. [foreach](#foreach)\n14. [Функции](#Функции)\n    1. [Объявление и вызов](#Объявление-и-вызов)\n    2. [Аргументы функции](#Аргументы-функции)\n    3. [Аргументы по умолчанию](#Аргументы-по-умолчанию)\n    4. [Области видимости переменных](#Области-видимости-переменных)\n    5. [Статические переменные](#Статические-переменные)\n    6. [Рекурсия](#Рекурсия)\n    7. [Функции управления функциями](#Функции-управления-функциями)\n15. [Классы и объекты](#Классы-и-объекты)\n    1. [Описание класса](#Описание-класса)\n    2. [Области видимости](#Области-видимости)\n    3. [Конструкторы и деструкторы](#Конструкторы-и-деструкторы)\n    4. [Клонирование объектов](#Клонирование-объектов)\n    5. [Наследование](#Наследование)\n    6. [Перегрузка методов](#Перегрузка-методов)\n    7. [Перебор свойств объекта](#Перебор-свойств-объекта)\n    8. [Константы класса](#Константы-класса)\n    9. [Абстрактные классы и методы](#Абстрактные-классы-и-методы)\n    10. [Интерфейсы](#Интерфейсы)\n    11. [Финальные классы и методы](#Финальные-классы-и-методы)\n    12. [Статические свойства и методы](#Статические-свойства-и-методы)\n    13. [Ключевое слово instanceof](#Ключевое-слово-instanceof)\n    14. [Автоматическая загрузка классов](#Автоматическая-загрузка-классов)\n    15. [Магические методы](#Магические-методы)\n    16. [Разыменование объектов](#Разыменование-объектов)\n    17. [Уточнение типа класса](#Уточнение-типа-класса)\n16. [Cookies](#Cookies)\n    1. [Создание Cookie](#Создание-Cookie)\n    2. [Чтение Cookie](#Чтение-Cookie)\n    3. [Удаление Cookie](#Удаление-Cookie)\n17. [Сессии](#Сессии)\n18. [HTTP-заголовки](#HTTP-заголовки)\n19. [Файлы](#Файлы)\n    1. [Получение сведений о файлах](#Получение-сведений-о-файлах)\n    2. [Открытие и закрытие](#Открытие-и-закрытие)\n    3. [Режимы работы с файлами](#Режимы-работы-с-файлами)\n    4. [Чтение файла](#Чтение-файла)\n    5. [Запись в файл](#Запись-в-файл)\n    6. [Манипуляции с курсором](#Манипуляции-с-курсором)\n    7. [Прямая работа с данными](#Прямая-работа-с-данными)\n    8. [Управление файлами](#Управление-файлами)\n    9. [Директории (каталоги)](#Директории-каталоги)\n    10. [Загрузка файлов на сервер](#Загрузка-файлов-на-сервер)\n    11. [Разбор файлов на сервере](#Разбор-файлов-на-сервере)\n20. [Работа с почтой](#Работа-с-почтой)\n21. [Базы данных и SQL](#Базы-данных-и-SQL)\n    1. [Введение в SQL](#Введение-в-SQL)\n    2. [Примеры SQL-запросов](#Примеры-SQL-запросов)\n22. [MySQL](#MySQL)\n    1. [Работа с MySQL в консоли](#Работа-с-MySQL-в-консоли)\n    2. [Создание базы данных и таблиц](#Создание-базы-данных-и-таблиц)\n    3. [Модуль MySQLi](#Модуль-MySQLi)\n23. [SQLite](#SQLite)\n    1. [Поддержка SQLite в PHP](#Поддержка-SQLite-в-PHP)\n    2. [Создание базы, таблиц и выборка данных](#Создание-базы-таблиц-и-выборка-данных)\n\n\n## Предыстория\n\n**PHP** – расшифровывается как _PHP: Hypertext Preprocessor_ (рекурсивный акроним), язык общего назначение активно применяемый в веб-разработке. Берёт начало в 1994 году когда датский программист [Расмус Лердорф](https://ru.wikipedia.org/wiki/%D0%9B%D0%B5%D1%80%D0%B4%D0%BE%D1%80%D1%84,_%D0%A0%D0%B0%D1%81%D0%BC%D1%83%D1%81) разработал на языке C набор CGI-скриптов обрабатывающие HTML-документы для учёта посетителей его онлайн-резюме. Первый релиз состоялся 8 июня 1995 году.\n\nЯзык подвергся значительной переработке когда в 1997 году два израильских программиста, [Энди Гутманс](https://ru.wikipedia.org/wiki/%D0%93%D1%83%D1%82%D0%BC%D0%B0%D0%BD%D1%81,_%D0%AD%D0%BD%D0%B4%D0%B8) и [Зеев Сураски](https://ru.wikipedia.org/wiki/%D0%A1%D1%83%D1%80%D0%B0%D1%81%D0%BA%D0%B8,_%D0%97%D0%B5%D0%B5%D0%B2), полностью переписали код интерпретатора. Новая версия языка PHP 3.0 была выпущена в июне 1998 года. С тех пор язык привлёк много сторонников, внёсшие вклад над разработкой новых модулей и API. Сегодня язык разрабатывается группой энтузиастов и распространяется под собственной лицензией в рамках проекта с открытым исходным кодом.\n\n## Интерпретатор PHP\n\nМестоположение интерпретатора можно узнать по информации выдаваемой функцией `phpinfo()`. В системе Windows путь к директории, где установлен PHP можно узнать в `Переменные среды` системы, путь к интерпретатору будет в списке переменной среды `Path`.\n\nСтандартный при поставке PHP содержит больше \u003e9000 функций. При разработке нет необходимости в таком количестве функций, поэтому часть стандартных функций вшиты в ядро, а часть функций (расширений) находятся в папке `ext`. В зависимости от необходимости мы можем подключать то или иное расширение.\n\n`php.ini` – главный конфигурационный файл настроек PHP. При установке нужно при необходимости переименовать файл `php.ini-production` или `php.ini-development` в `php.ini`.\n\nНастройки PHP делятся на три группы где их можно изменять:\n1. Это непосредственно файл `php.ini`. На shared-хостинге, как правило, не дают прямой доступ к файлу `php.ini`, лишь выносят часть их настроек в панель управления хостингом;\n2. `.htaccess` – настройки распространяются ко всем подпапкам, кроме тех, у которых есть свой файл `.htaccess`;\n3. Прямо в коде. Например:\n\n```php\n\u003c?php php_flag short_open_tag off ?\u003e\n```\n\n### Связка с веб-сервером Apache\n\nЧтобы подключить PHP к веб-серверу Apache, нужно указать Apache, где находится файл `php.ini` одним из следующим способом:\n\n1. Прописать путь к файлу php.ini в значение:\n  * С помощью директивы `PHPIniDir` указать путь к файлу `php.ini` в главном конфигурационном файле Apache `httpd.conf` (в версиях Apache 2 и выше);\n  * Системной переменной `PHPRC`;\n  * Ключа реестра `IniFilePath` в ветвях:\n    * HKEY_LOCAL_MACHINE\\SOFTWARE\\PHP\\x.y.z\\ (5.4.8)\n    * HKEY_LOCAL_MACHINE\\SOFTWARE\\PHP\\x.y\\ (5.4.8)\n    * HKEY_LOCAL_MACHINE\\SOFTWARE\\PHP\\x\\ (5.4.8)\n    * HKEY_LOCAL_MACHINE\\SOFTWARE\\PHP\\\n\n2. Скопировать файл `php.ini` в директорию:\n  * PHP;\n  * Сервера;\n  * ОС Windows (например, C:\\Windows).\n\nУзнать какой именно файл `php.ini` зачитывается можно с помощью той же функцией `phpinfo()` в строке `Loaded Configuration File`.\n\n## Синтаксис языка\n\n### PHP–теги\n\nВсе, что находится между открывающими и закрывающими php-тегами – есть код на PHP. Каждая инструкция заканчивается точкой с запятой.\n\n**Рекомендуется к использованию:**\n\n```php\n\u003c?php инструкция; ?\u003e\n```\n\n**Короткая запись**\n\nДля этого тега параметр `short_open_tag` в `php.ini` должен быть установлен как `on`. Такая конструкция может быть нежелательной из-за того, что декларация XML также начинается с `\u003c?` и заканчивается `?\u003e`:\n\n```php\n\u003c? код PHP ?\u003e\n```\n\n**Вместо вопросов проценты**\n\nВ свое время, чтобы переманить на свою сторону программистов на ASP.NET были введены такие открывающиеся/закрывающие теги PHP. Для этого параметр `asp_tags` должен быть включен:\n\n```php\n\u003c% код PHP %\u003e\n```\n\n### Комментарии\n\nВ классическом программировании принято чтобы комментарии составляли 30% от кода. Однострочные комментарии начинаются с двумя слэшами `//`. Блочные комментарии заключаются между `/*` и `*/`.\n\n```php\n\u003c?php \n# однострочный комментарий\n// однострочный комментарий\n?\u003e\n\n\u003c?php\n/*\nэто блочный комментарий\n*/\n?\u003e\n```\n\n## Hello, World!\n\nЗа вывод строковых данных на экран в PHP используется функция `echo`, которая выводит одну и более строк. Языковая конструкция `print` также печатает данные на экран. В отличие от `echo` она умеет принимать только один параметр и всегда возвращает 1.\n\n```php\n\u003c?php\necho \"Привет, это просто текст\";\nprint \"Привет, это просто текст\";\nprint(\"так тоже можно\");\n\n// Здесь четыре раза вызывается echo\necho '\u003ch1\u003e', 'Hello, ', 'world!', '\u003c/h1\u003e';\n\n// Короткая запись (сокращенное echo)\n// Для этого должен быть включён флаг short_open_tag\n\u003c?='Hello, world!'?\u003e\n?\u003e\n```\n\n## Переменные\n\nПеременная — именованная ячейка памяти.\n\n* Все имена переменных должны начинаться со знака доллара `$`;\n* Первым символом после `$` должна быть буква или символ подчеркивания. Далее, в имени переменной могут присутствовать буквы, цифры и символ подчеркивания;\n* Имена переменных чувствительны к регистру.\n\nЕсть несколько подходов к написанию переменных. В C (Си) подобных языках переменные пишут с маленькой буквы, в Basic с заглавной. Нужно определить свой стиль написания переменной. Если переменная состоит из двух слов, то можно записать так: `user_name` или методом \"верблюжьей нотацией\" `userName` (`UserName`). Последняя чаще может встречаться в крупных проектах в таких, как WordPress.\n\n**Присвоение значения переменной и её удаление**\n\n```php\n\u003c?php\n// Переменной $var присваивается значение John\n$var = 'John';\n\n// Переменной $num присваивается значение 99\n$num = 99;\n\n// Переменной $num присваивается результат выражения, т.е. 10\n$num = 5 + 5;\n?\u003e\n```\n\nПосле завершения конструкции PHP значения переменных стираются из памяти, но бывают ситуации, когда переменные нужно удалить до того, как закончится код.\n\n```php\n\u003c?php\n$user = \"John\";\necho $user;\n\n// Удаление из памяти переменную $user\nunset($user);\n\n// Уведомление (PHP Notice) о том, что переменная неопределена\necho $user;\n?\u003e\n```\n\n### Экранирование переменных\n\nИмена переменных можно помещать в строки (тип данных String рассматривается в разделе [Типы данных](#String)). В строках заключенные одинарными кавычками переменные отображаются как простой текст. Однако в двойных кавычках переменная подставит своё значение.\n\n```php\n\u003c?php\n$beer = 'Heineken';\n\n// Выведет переменную beer,\n// т.к. апостроф не допустимый символ в именах переменных\necho \"$beer's taste is great\u003cbr\u003e\";\n\n// Переменной $beers не существует\necho \"He drank some $beers\u003cbr\u003e\";\n?\u003e\n```\n\nЕсли имя переменной сливается в строке с другими символами, и интерпретатор может допустить лишние символы как часть имени переменной, то такую переменную следует экранировать заключив её имя в конструкции `${name}` или `{$name}`.\n\n```php\n// Экранирование переменных одним из двух способов\necho \"He drank some ${beer}s\u003cbr\u003e\"; // первый способ\necho \"He drank some {$beer}s\u003cbr\u003e\"; // второй способ\n```\n\n### Присвоение по ссылке\n\nВ переменную может быть присвоено значение по ссылке. Это значит, что создаваемая переменная не будет иметь своё собственное значение, а будет ссылаться на оригинальную переменную. Другими словами, являться собой ярлыком, псевдонимом другой переменной.\n\n```php\n\u003c?php\n$a = 10;\n$b = \u0026$a; // Ссылка на переменную $a\necho $b; // -\u003e 10\n?\u003e\n```\n\nШирокое применение это находит, например, в [циклах](#foreach), когда мы хотим изменить значения массива на месте прямо в теле цикла.\n\n```php\n$inputs = [ ... ]; // Условная переменная-массив\n\nforeach($inputs as \u0026$input) {\n  $input['checked'] = true; // Изменяется исходный массив\n}\n```\n\n## Ошибки\n\n* Если мы не видим ошибки на строке который указывает нам браузер, то ошибку следует искать строчкой выше;\n* Когда у нас выпадает много ошибок, нужно искать и исправлять ошибки сверху вниз, а не снизу вверх.\n\nУ PHP есть четыре уровня ошибок (предупреждений):\n1. **PARSE** – ошибка при парсинге. PHP не сразу выполняет полученный код, а сперва проверяет на предмет синтаксических ошибок;\n   Если синтаксических ошибок не обнаружено, то код начинает выполняться...\n2. **FATAL ERROR** – в этом случае нам выведется ошибка и выполнение кода прекратится;\n3. **WARNING** – предупреждение. Выведет ошибку, но выполнение кода продолжится;\n4. **NOTICE** – уведомление.\n\nМы можем запретить выводить показ об ошибке в браузере выполнив `error_reporting(0);`. По умолчанию все константы уровней ошибок (кроме NOTICE) будут выводиться в браузере. На практике сначала проверяют код на предмет серьезных ошибок, и только потом если таких ошибок не обнаружено, включают `error_reporting(E_ALL)`.\n\n## Типы данных\n\nPHP поддерживает 10 простых типов:\n\n* Четыре скалярных типа:\n  * boolean (логический)\n  * integer (целые числа)\n  * float (вещественные (плавающие) числа)\n  * string (строковый тип)\n\n* Два смешанных типа:\n  * array (массив)\n  * object (объект)\n  * callable\n  * iterable\n\n* Два специальных типа:\n  * resource\n  * NULL\n\nВ этом разделе рассмотрим только скалярные типы и специальный тип `NULL`. \n\n### Boolean\n\nПростейший тип, выражающий истинность значения. Это может быть либо `true` или `false`.\nПри преобразовании в логический тип, следующие значения рассматриваются как `false`:\n* само значение `false`;\n* Целое 0 (ноль);\n* Вещественное число (с плавающей точкой) 0.0 (ноль);\n* Пустая строка и строка `\"0\"`;\n* Пустой массив;\n* Специальный тип `NULL` (включая неустановленные переменные).\n\nВсе остальные значения рассматриваются как `true`.\n\n### Integer и Float\n\n```php\n\u003c?php\n// Целые числа\n$int = 123; // Целое десятичное число\n$int = -23; // Целое отрицательное число\n$int = 0123; // Восьмиричное число (начинается с 0)\n$int = 0x1A; // Шестнадцатиричное число\n\n// Вещественные числа\n$flt = 1.23; // Дробное число\n$flt = 1.2e3; // экспоненциальная запись\n$flt = 7E-10;\n?\u003e\n```\n\n### String\n\nСтроки заключаются в двойные и одинарные кавычки, а также доступен синтаксис `heredoc` рассматриваемый дальше.\n\n```php\n\u003c?php\n$str = \"Текстовая строка\"; // в двойных кавычках\necho $str;\n?\u003e\n```\n\nВ строках с двойными кавычками допустимо использовать специальные символы, некоторые из них:\n\n- \\n - перевод на новую строку;\n- \\r - возврат каретки;\n- \\t - горизонтальная табуляция;\n- \\\\ - обратный слеш;\n- \\$ - знак доллара;\n- \\\" - двойная кавычка;\n\n```php\n\u003c?php\n$str = 'Текстовая строка'; // в одинарных кавычках\necho 'Переменная $str - ' . $str; // -\u003e Переменная $str - Текстовая строка\n?\u003e\n```\n\nРазница между двойными и одинарными кавычками в том, что в двойных переменные и спец. символы обрабатываются, а в одинарных нет.\n\n### Синтаксис heredoc и nowdoc\n\nКонструкция **heredoc** и **nowdoc** начинаются с тремя знаками `\u003c\u003c\u003c` после которого следует идентификатор, а затем перевод строки. После этого идёт сама строка, а потом этот же идентификатор, закрывающий вставку.\n\nЗакрывающий идентификатор может иметь отступ в виде пробела или табуляции. В этом случае отступ будет удалён из всех строк в строке документа.\n\n```php\n\u003c?php\necho \u003c\u003c\u003cLABEL\nПример строки, охватывающей несколько строк, с использованием\nheredoc-синтаксиса.\n\nЭто очень похоже на использование HTML-тега \u003cPRE\u003e,\nт.е. сохраняются пробелы, отступы, переходы на новую строку,\nтабуляции, также сюда можно подставлять переменные, использовать\nспециальные символы.\nLABEL;\n?\u003e\n```\n\n**Определение строк с помощью синтаксиса nowdoc**\n\n**nowdoc** — это то же самое для строк в одинарных кавычках, что и heredoc для строк в двойных кавычках. **nowdoc** похож на **heredoc**, но внутри него не осуществляется никаких подстановок. Эта конструкция идеальна для внедрения PHP-кода или других больших блоков текста без необходимости его экранирования.\n\n**nowdoc** указывается той же последовательностью `\u003c\u003c\u003c`, что используется в **heredoc**, но последующий за ней идентификатор заключается в одинарные кавычки, например, `\u003c\u003c\u003c'EOT'`.\n\n```php\n\u003c?php\necho \u003c\u003c\u003c'LABEL'\nстрока nowdoc\nLABEL;\n?\u003e\n```\n\nНекоторые правила касающиеся типа string **heredoc** и **nowdoc**:\n\n* Строка с открывающим идентификатором не содержит после него никаких других символов, включая пробел;\n* Закрывающий идентификатор до версии PHP 7.3.0 должен начинаться с первой позиции строки;\n* Строка с закрывающим идентификатором не содержит других символов (включая пробел), за исключением точки с запятой.\n\n### Доступ к символу в строке\n\nМы можем получить доступ к любому символу в строке объявленной в переменной `$str` передав номер позиции символа в квадратных `[]` или фигурных `{}` скобках. Отсчёт позиции символов начинается с нуля.\n\n```php\n\u003c?php\n$str = \"Hello, world!\";\n\n// Получение первого символа строки\n$first = $str{0}; // Возвращает позицию первого символа, т.е. H\n\n// То же самое можно сделать используя квадратные скобки\n$first = $str[0]; // Возвращает позицию первого символа, т.е. H\n\n// Получение третьего символа строки\n$third = $str{2}; // Возвращает l\n\n// Получение последнего символа строки\n$last = strlen($str); // Возвращает количество символов (отсчет с 1)\n$sym = $str{$last - 1}; // Возвращает ! знак\nprint \"$sym\"; // Печатает ! знак\n?\u003e\n```\n\n### NULL\n\nПеременная считается NULL если:\n\n* Ей была присвоена константа `NULL`;\n* Ей ещё не было присвоено какое-либо значение;\n* Она была удалена с помощью `unset()`.\n\n## Операторы\n\nОператоры принимают одно или несколько значений и вычисляют на их основе новое значение. Под вычислением может происходить сравнение двух значений, их арифметическое вычисление, присваивание и т.д.\n\nОператоры бывают _унарные_ – принимают только одно значение, например `!` (логическое отрицание), `++` (инкремент) и др. и _бинарные_ – принимают два значения (большинство операторов именно такие). Также существует один [_тернарный оператор_](#Тернарный-оператор), принимающий три значения.\n\n### Арифметические\n\n```php\n\u003c?php\n$a + $b; // Сумма $a и $b\n$a - $b; // Разность $a и $b\n$a * $b; // Произведение $a и $b\n$a / $b; // Частное от деления $a на $b\n$a % $b; // Целочисленный остаток от деления $a на $b\n$a += $b; // Тоже, что и $a = $a + $b.\n\n// Остальные операторы работают аналогично\n$a = '5Word';\n$b = $a * 10; // От переменной $a возмется 5 и результат будет 50\n\n$a = 'Строка';\n$b = $a * 10; // Переменная $a приведется к нулю и результат будет 0\n?\u003e\n```\n\n### Строковые\n\n```php\n\u003c?php\n$word1 = \"Привет!\";\n$word2 = $word1 . \" Мир\"; // Конкатенация (возвращает \"Привет! Мир\")\n\n$word1 .= \" Мир\"; // Конкатенация сокращенная (возвращает \"Привет! Мир\")\n\n$word3 = \"Я\";\n$word4 = \"люблю\";\nprint $word3 . \" \" . word4 . \" \" . \"кофе!\";\necho $word3, ' ', $word4, ' ', 'чай!';\n?\u003e\n```\n\n### Операторы сравнения\n\n```php\n\u003c?php\n$a == $b // -\u003e true если $a равно $b\n$a === $b // -\u003e true если тип операндов совпадает и $a равно $b\n$a != $b // -\u003e true если $a не равно $b\n$a !== $b // -\u003e true если типы не совпадают и $a не равно $b\n$a \u003e $b // -\u003e true если $a строго больше $b\n$a \u003c $b // -\u003e true если $a строго меньше $b\n$a \u003e= $b // -\u003e true если $a больше или равно $b\n$a \u003c= $b // -\u003e true если $a меньше или равно $b\n?\u003e\n```\n\n### Логические операторы\n\n```php\n\u003c?php\n$a and $b // -\u003e true если $a и $b true\n$a or $b // -\u003e true если $a или $b true\n!$a // -\u003e true если $a не true\n\n// Сначала вычислится сравнение $a и $b,\n// и только потом их результат сравнится с $c\n$a and $b and $c\n\n// Сначала вычислится сравнение $b и $c,\n// и только потом их результат сравнится с $a\n$a and ($b and $c) эквивалентно $a and $b \u0026\u0026 $c\n\n// Сначала вычислится сравнение $b или $c,\n// и только потом их результат сравнится с $a\n$a and ($b or $c) эквивалентно $a and $b || $c\n?\u003e\n```\n\nОператоры `\u0026\u0026` (логическое умножение), `||` (логическое сложение) приоритетнее операторов `and` и `or`.\n\n## Полезные функции\n\n- `isset(имя_переменной)` – возвращает `true`, если существует переменная или `false`, если переменная не определена или ей присвоено `NULL` (что в принципе одно и то же);\n\n- `empty(имя_переменной)` – возвращает `true`, если значение переменной пустая строка `\"\"`, `NULL`, переменная не определена ($x), пустой массив ($x = array()), значение `false` ($x = false), значение `0` ($x = 0;) или ($x = \"0\"). Возвращает `false`, если значение переменной `true` ($x = true), значение `\u003e` или `\u003c` 0;\n\n- `gettype(имя_переменной)` – возвращает тип переменной (boolean, string, integer, double(float), NULL). Например:\n\n```php\n\u003c?php\n$variable = \"100darov\";\necho gettype($variable); // Возвращает string\n?\u003e\n```\n\n- `settype(имя_переменной, \"тип\")` – конвертирует переменную в другой тип. Например:\n\n```php\n\u003c?php\n$variable = \"100darov\";\nsettype($variable, \"integer\"); // Возвращает integer\n?\u003e\n```\n\n- Временное приведение к типу\n\nЕсли мы хотим вывести только 100, но также хотим чтобы значение `\"100darov\"` в переменной `$variable` осталось — нужно написать в скобках нужный тип данных перед именем переменной без пробелов:\n\n```php\n\u003c?php\n$variable = \"100darov\";\necho (integer)$variable; // -\u003e 100\n?\u003e\n```\n\n## Управляющие конструкции\n\nОсновные конструкции PHP это _условные операторы_ (if, else), _оператор выбора_ (switch) и _циклы_ (for, foreach, while, do..while). Внутри конструкции `switch` и некоторых циклов могут быть использованы ключевые слова (return, break, continue).\n\n### if\n\nЕсли условие в скобках истинно, но выполнится инструкция.\n\n```php\n\u003c?php\n$var = true;\nif ($var) echo \"Инструкция выполнится, в $var истинное значение\";\n?\u003e\n```\n\nЕсли необходимо выполнить несколько инструкций, то заключаем их в операторные скобки.\n\n```php\nif (условие) {\n  инструкция 1;\n  инструкция 2;\n}\n?\u003e\n```\n\n### if..else..\n\nЕсли условие в `if` окажется истинным, то выполнятся только инструкции 1 и 2, иначе выполняются инструкции 3 и 4.\n\n```php\n\u003c?php\nif (условие) {\n  инструкция 1;\n  инструкция 2;\n} else {\n  инструкция 3;\n  инструкция 4;\n}\n?\u003e\n```\n\n### if..elseif..else..\n\nЕсли `условие 1` истинно, то выполнится только `инструкция 1`, все остальные `elseif` и `else` интерпретатор проверять не станет. Аналогично и с `условием 2`, во всех остальных случаях выполнится `инструкция 3` в блоке `else`.\n\n`Инструкция 4` выполнится в любом случае, сразу после разрешения конструкции выше.\n\n```php\n\u003c?php\nif (условие 1) {\n  инструкция 1;\n}\nelseif (условие 2) {\n  инструкция 2;\n} else {\n  инструкция 3;\n}\n\nинструкция 4;\n?\u003e\n```\n\n### Альтернативный синтаксис\n\nЗакрытие блока `?\u003e`, это еще не есть закрытие кода. Очень легко запутаться в фигурных скобках, поэтому для удобства PHP предлагает альтернативный синтаксис для некоторых его управляющих структур, а именно: `if`, `while`, `for`, `foreach` и `switch`.\n\n```php\n\u003c?php if (условие 1): ?\u003e\n  код условия 1\n\u003c?php elseif (условие 2): ?\u003e\n  код условия 2\n\u003c?php else: ?\u003e\n  код блока else\n\u003c?php endif; ?\u003e\n?\u003e\n```\n\n### Тернарный оператор\n\nТернарный оператор это то же условие `if..else`, но с более коротким синтаксисом. Сначала проверяется условие в скобках, если оно истинно, то выполняется инструкция после знака `?`, иначе после знака `:`.\n\nСкобки вокруг условия факультативны, но предпочтительней их ставить для лучшей читаемости кода.\n\n```php\n\u003c?php\necho ($a \u003e 1) ? \"a больше единицы\" : \"a меньше единицы\";\n$b = ($a \u003e 1) ? \"One\" : \"Zero\"; // Значение присвоится переменной $b\n?\u003e\n```\n\n### switch\n\nОператор `switch` можно представить как ещё одну разновидность оператора `if..elseif..else`. В случаях, когда необходимо сравнивать одну и ту же переменную (или выражение) со множеством значений.\n\nКонструкция `switch/case` использует нестрогое сравнение `==`.\n\nОператор `continue` прерывает все последующие итерации. Следующая за `continue` инструкция и далее уже не будут выполнены. Может также быть использована в циклических структурах и выполнять там ту же функцию.\n\n`break` прерывает выполнение текущей структуры `switch` и выходит за операторные скобки. Может также применяться в таких циклических конструкциях как `for`, `foreach`, `while`, `do..while`.\n\n`continue` и `break` принимают числовой параметр, сообщающей интерпретатору какое кол-во вложенных структур надо прервать. Поведение работы этих операторов в циклических структурах описано далее на примере работы цикла [**while**](#while).\n\nВ случае если ни один из вариантов не подошел, то будет исполнено то, что в блоке `default`.\n\n```php\n\u003c?php\nswitch (выражение) {\n  case 0: инструкция 1;\n  case 1: инструкция 2;\n  case 2:\n    инструкция 3;\n    continue;\n  case 3: инструкция 4;\n  case 4:\n    инструкция 5;\n    break;\n  case 5: инструкция 6;\n  case 6: инструкция 7;\n  default:\n    инструкция 8;\n}\n?\u003e\n```\n\n**Пример использования `switch`**\n\nК примеру необходимо вычислить значение директивы `post_max_size` в байтах. Значение любой директивы в PHP можно получить/установить с помощью функций:\n\n* `ini_get('имя_директивы')` — данная функция всегда возвращает значение в строковом типе;\n* `ini_set('имя_директивы', \"on | of | значение\")` — включение/выключение/изменение директивы Runtime (прямо в коде).\n\nДопустим мы имеем код со следующей реализацией:\n\n```php\n\u003c?php\n$result = ini_get(\"post_max_size\"); // -\u003e 8M\n$letter = $result{strlen($result) - 1}; // -\u003e M\n$size = (integer)$result; // -\u003e 8\n\nswitch ($letter) {\n  case \"G\": $size = $size * 1024 * 1024 * 1024; break;\n  case \"M\": $size = $size * 1024 * 1024; break;\n  case \"K\": $size = $size * 1024; break;\n  default: $size;\n}\n\necho \"POST_MAX_SIZE = \" . $size . \" bytes\";\n?\u003e\n```\n\nВот как выглядит код после оптимизации. Пример демонстрирует случай, когда такое использование `switch` особенно оправдано.\n\n```php\n\u003c?php\n$result = ini_get(\"post_max_size\"); // -\u003e 8M\n$letter = $result{strlen($result) - 1}; // -\u003e M\n$size = (int)$result; // -\u003e 8\n\n// Альтернативный фигурным скобкам синтаксис\nswitch ($letter):\n\tcase \"G\": $size *= 1024; // -\u003e 8 589 934 592\n\tcase \"M\": $size *= 1024; // -\u003e 8 388 608\n\tcase \"K\": $size *= 1024; // -\u003e 8 192\nendswitch;\n?\u003e\n```\n\n### try..catch..\n\nКонструкция `try..catch..` используется для обработки исключений и отслеживания ошибок. Ошибку в случае возникновения перехватывает `catch`, информацию об ошибке можно извлечь из класса `Exception`.\n\n```php\n\u003c?php\nclass User {\n  public $name, $last_name, $age, $sex;\n\n  function __construct($name = '', $lastName = '', $age = 0, $sex = '') {\n    try {\n      if($name == '' or $lastName == '' or $age == 0 or $sex == '')\n        throw new Exception('Введены не все данные!');\n      $this-\u003ename = $name;\n      $this-\u003elast_name = $last_name;\n      $this-\u003eage = $age;\n      $this-\u003esex = $sex;\n    }\n    catch(Exception $error) {\n      // Сообщение об ошибке\n      echo $error-\u003egetMessage(); // -\u003e \"Введены не все данные!\"\n      // Строка на которой произошла ошибка\n      echo $error-\u003egetLine();\n      // Файл, в котором произошла ошибка\n      echo $error-\u003egetFile();\n    }\n  }\n}\n\n$user = new User(); // $error object\n?\u003e\n```\n\n## Массивы\n\n_Массив_ — упорядоченный набор данных, где каждый элемент массива имеет свой ключ и значение. Массив может быть создан языковой конструкцией `array()` или с помощью короткого синтаксиса `[]`. Ключи массива могут быть либо целочисленным типом [Integer](#Integer-и-Float), либо [String](#String). Значение же может быть любым типом.\n\n### Нумерованный массив\n\n_Нумерованные массивы_ — это массивы, у которых ключи являются числа.\n\n```php\n\u003c?php\n$arr = [0 =\u003e '1st', 1 =\u003e '2nd', 3 =\u003e '3rd'];\n\n// Значение \"4th\" теперь будет имет порядковый номер 10\n$arr[10] = '4th';\n?\u003e\n```\n\n### Ассоциативный массив\n\n_Ассоциативный массив_ — это когда вместо индексов (номеров) назначают строковые осмысленные имена.\n\n```php\n\u003c?php\n$user = Array(\n  \"Jane\",\n  \"Doe\",\n  20,\n  // Значение \"guest\" теперь будет имет порядковый номер (индекс) 55\n  55 =\u003e \"guest\",\n  true\n);\n?\u003e\n```\n\nУ ниже приведённых двух элементов массива будет одинаковая структура, хоть они и были созданы разными способами. \n\n```php\n\u003c?php\n$cars['tesla'] = Array(\n  'model' =\u003e \"Model S Plaid\",\n  'speed' =\u003e 321,\n  'doors' =\u003e 4,\n  'year' =\u003e \"2022\"\n);\n\n$cars['mercedes-benz']['model'] = 'Mercedes-Benz EQC';\n$cars['mercedes-benz']['speed'] = 180;\n$cars['mercedes-benz']['doors'] = 4;\n$cars['mercedes-benz']['year'] = \"2022\";\n?\u003e\n```\n\n### Многомерный массив\n\n_Многомерный массив_ — массив, где элементы в свою очередь могут сами являться массивами и содержать в себе сколько угодно вложенных массивов. Пример многомерного массива:\n\n```php\n\u003c?php\n$contents = array(\n\"Введение\",\n\"Часть I\" =\u003e array(\n  \"Глава I\" =\u003e array(\n    \"Глава 1.1\",\n    \"Глава 1.2\",\n    \"Глава 1.3\",\n    ),\n  \"Глава II\",\n  \"Глава III\",\n  ),\n\"Часть II\",\n\"Часть III\" =\u003e array(\n  \"Глава I\" =\u003e array(\n    \"Глава 1.1\",\n    \"Глава 1.2\",\n    \"Глава 1.3\",\n    ),\n  \"Глава II\",\n  \"Глава III\" =\u003e array(\n    \"Глава 1.1\",\n    \"Глава 1.2\",\n    \"Глава 1.3\",\n    ),\n  \"Глава IV\",\n  ),\n\"Часть IV\",\n\"Заключение\",\n);\n?\u003e\n```\n\n### Работа с массивами\n\nОбъявлять массив предпочтительней с помощью языковой конструкцией `array()`, но добавлять новые ячейки в уже имеющийся массив удобней с помощью квадратных скобок `$myArray[] = 'добавление'`.\n\n#### Печать массива\n\nМожно просмотреть индексы массива и соответствующие им значения с помощью функции `print_r()`. Для сохранения форматирования вывод был обрамлён тегами `\u003cpre\u003e`.\n\n```php\necho '\u003cpre\u003e', print_r($user), '\u003c/pre\u003e';\n```\n\nФункция `var_dump()` также печатает массив, в отличие от предыдущей данные массива печатаются с дополнительной информацией — с указанием длины массива, индекса, тип значения и само значение, а также длину строки, если значение строковое. `var_dump()` также можно применить и к обычной переменной и в случаях, когда необходимо более подробно посмотреть массив.\n\n```php\necho \"\u003cpre\u003e\", var_dump($cars), \"\u003c/pre\u003e\";\n\n// Результат выполнения\narray(1) {\n  [\"tesla\"]=\u003e\n  array(4) {\n    [\"model\"]=\u003e\n    string(13) \"Model S Plaid\"\n    [\"speed\"]=\u003e\n    int(321)\n    [\"doors\"]=\u003e\n    int(4)\n    [\"year\"]=\u003e\n    string(4) \"2022\"\n}\n```\n\n#### Подсчёт элементов массива\n\nПодсчет количества элементов массива или количества свойств объекта\nвыполняет функция `count($myArray)`.\n\nЕсли в качестве второго параметра передать `true`, т.е сделать так `count(myArray, 1)`, то функция подсчитает все вложенные элементы, если это многомерный массив.\n\n#### Встраивание массива в строки\n\nВывести ячейки массива внутри двойных кавычек можно двумя способами:\n\n* Экранировать переменные:\n\n```php\n\u003c?php\necho \"Меня зовут {$user['name']}! Мне {$user['age']} лет\";\n?\u003e\n```\n\n* Обращаться к ячейкам массива без кавычек:\n\n```php\n\u003c?php\necho \"Меня зовут $user[name]! Мне $user[age] лет\";\n?\u003e\n```\n\n#### Перемещение указателя массива\n\nМожно передвигать указатель массива (вверх-вниз) с помощью специальных функций:\n\n```php\n\u003c?php\n// Исходный маассив\n$menu['Блюдо']['Суп1'] = \"Борщ\";\n$menu['Блюдо']['Суп2'] = \"Щи\";\n$menu['Блюдо']['Суп3'] = \"Рассольник\";\n$menu['Блюдо']['Салат1'] = \"Венегрет\";\n$menu['Блюдо']['Салат2'] = \"Оливье\";\n$menu['Блюдо']['Салат3'] = \"Под шубой\";\n\n// Возвратить текущий элемент массива\ncurrent($menu['Блюдо']); // -\u003e Борщ\n\n// Переход на следующую позицию\nnext($menu['Блюдо']); // -\u003e Щи\n\n// Переход на предыдущую позицию\nprev($menu['Блюдо']); // -\u003e Борщ\n\n// Переход к последнему элементу\nend($menu['Блюдо']); // -\u003e Под шубой\n\n// Возвращает ключ из ассоциативного массива\nkey($menu['Блюдо']); // -\u003e Салат3\n?\u003e\n```\n\n## Константы\n\n_Константы_ — те же самые переменные, но только значения в них неизменны.\n\n* У констант нет приставки в виде знака доллара;\n* Константы можно определить только с помощью функции `define()`, а не присваиванием значения;\n* Константы доступны в любом месте, без учета области видимости;\n* Константы не могут быть переопределены или аннулированы после первоначального объявления;\n* Константы не встраивают в строки с двойными кавычками, их нужно конкатенировать.\n\nКонстанты задаются следующей функцией:\n\n```php\n\u003c?php define('имя_константы', значение); ?\u003e\n```\n\nКонстанту можно проверить следующей функцией:\n\n```php\n\u003c?php\ndefined(\"имя_константы\"); // -\u003e true, если такая константа уже есть\n\n// нечувствительная к регистру константа\ndefine(\"имя_константы\", значение, true);\n?\u003e\n```\n\nПередав `true` третьим параметром мы разрешаем константе быть регистро-независимой (не рекомендуется).\n\nИмена констант принято писать большими буквами (но допускается и строчными). Единожды созданная константа существует до конца кода. Константе нельзя заново присвоить какое-нибудь значение, её нельзя удалить (с помощью функции `unset()`).\n\nКонстанты обычно заводятся по двум причинам:\n\n1. Удобней помнить имя константы. Например, константы `E_ALL`, `E_ERROR` и др. за такими константами на самом деле стоит определенное значение (число). И гораздо удобней запомнить имя константы, чем то число, которое стоит за ней;\n2. В процессе работы мы заводим переменную значение которой впоследствии можно ненамеренно переназначить. С использованием констант эта проблема отпадает, т.к. её значение всегда остаётся неизменным.\n\n### Магические константы\n\nВ PHP есть 9 псевдоконстант, которые меняют своё значение в зависимости от контекста, где они используются.\n\n|          Имя          | Описание                                                                                                                                                                                                                                            |\n|:---------------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n|   **\\_\\_LINE\\_\\_**    | Текущий номер строки в файле.                                                                                                                                                                                                                       |\n|   **\\_\\_FILE\\_\\_**    | Полный путь и имя текущего файла с развёрнутыми симлинками. Если используется внутри подключаемого файла, то возвращается имя данного файла.                                                                                                        |\n|    **\\_\\_DIR\\_\\_**    | Директория файла. Если используется внутри подключаемого файла, то возвращается директория этого файла. Это эквивалентно вызову dirname(**\\_\\_FILE\\_\\_**). Возвращаемое имя директории не оканчивается на слеш, за исключением корневой директории. |\n| **\\_\\_FUNCTION\\_\\_**  | Имя функции или `{closure}` в случае анонимной функции.                                                                                                                                                                                             |\n|   **\\_\\_CLASS\\_\\_**   | Имя класса. Это имя содержит название пространства имён, в котором класс был объявлен (например, `Foo\\Bar`). При использовании в методах трейтов \\_\\_CLASS\\_\\_ является именем класса, в котором эти методы используется.                           |\n|   **\\_\\_TRAIT\\_\\_**   | Имя трейта. Это имя содержит название пространства имён, в котором трейт был объявлен (например, Foo\\Bar).                                                                                                                                          |\n|  **\\_\\_METHOD\\_\\_**   | Имя метода класса.                                                                                                                                                                                                                                  |\n| **\\_\\_NAMESPACE\\_\\_** | Имя текущего пространства имён.                                                                                                                                                                                                                     |\n| **ClassName::class**  | Полное имя класса.                                                                                                                                                                                                                                  |\n\n**Пример использования в классах**\n\n```php\n\u003c?php\nclass myClass{\n  function getMethod(){\n    echo __METHOD__:\n  }\n\n  function getClass(){\n    echo __CLASS__;\n  }\n}\n\n$myObject = new myClass();\n$myObject-\u003egetMethod; // myClass::getMethod\n$myObject-\u003egetClass; // myClass\n?\u003e\n```\n\n## Циклы\n\nPHP поддерживает несколько различных циклических структур управления.\n\n### for\n\nСинтаксис цикла `for`:\n\n```php\n\u003c?php\nfor (часть A; часть B; часть C) {\n  инструкция 1;\n  инструкция 2;\n  ...\n}\n?\u003e\n```\n\nПараметры цикла `for` (в круглых скобках) можно разделить на три части, которые в свою очередь разделяются `;`, т.е. в данном случае точка с запятой выступают как разделитель, а не как окончание выражения или инструкции.\n\n* Выражения, находящиеся в `части A`, PHP просто выполняет, и как правило, там инициализируется счетчик (т.е. мы назначаем какую-то переменную и говорим что она будет счетчик);\n* `Часть B` (или так называемый встроенный `if`), здесь проверяется истинность, и в случае, если там `true`, то PHP заходит в тело цикла;\n* Содержимое `части C` PHP, как и в случае с `частью A` просто выполняет и как правило, там мы изменяем наш счетчик.\n\nВ каждом из этих трех частей мы можем использовать не одно выражение, а сколько угодно, но в этом случае поскольку точка с запятой служит разделителем частей в конструкции for, разделять выражения следует запятой.\n\nКогда интерпретатор PHP встречает цикл `for`, первое что он делает — заходит в `часть A` и делает все что там написано. Сюда он попадает только один раз. Потом он перемещается в `часть B` и если там `true`, то PHP выполняет тело цикла. Затем выполняется `часть C`. Таким образом, далее цикл работает как по треугольнику: `часть B` =\u003e тело цикла =\u003e `часть C`, до тех пор, пока условие в `части B` не окажется ложным.\n\nНапример: вывести нечетные числа от 0 до 50.\n\n```php\n\u003c?php\n$str = \"Привет! Мир\";\nfor($j=0, $cnt = strlen($str); $j \u003c $cnt; $j++) {\n  echo $str{$j}, \"\u003cbr\u003e\";\n}\n?\u003e\n```\n\nВ цикле `for` любую из частей можно опустить. Пример классического бесконечного цикла:\n\n```php\n\u003c?php\nfor(;;) {\n  print $a . \"\u003cbr\u003e\";\n}\n?\u003e\n```\n\n### while\n\nСинтаксис:\n\n```php\n\u003c?php\nwhile(условие) {\n  инструкция 1;\n  инструкция 2;\n}\n?\u003e\n```\n\nЕсли условие истинно, то выполняется тело цикла. Цикл `for` и `while` взаимозаменяемы. Если мы знаем начальную и конечную точку (от скольки и до скольки), то удобнее использовать цикл `for`. Но бывает ситуация, когда мы не знаем конечной точки.\n\nВ теле цикла `while` можно использовать оператор `break`, который прерывает цикл и выйдет за его пределы.\n\n```php\n\u003c?php\n$i = 1;\n\n// Скрипт последовательно напечатает 1 2 3 4 5\n// из-за условия внутри тела цикла\nwhile($ \u003c 10) {\n  $i++;\n  print $i . \"\u003cbr\u003e\";\n  if ($i == 5)\n    break;\n} \n?\u003e\n```\n\nОператор `continue` в цикле `while` прерывает итерацию (переходит обратно к условию):\n\n```php\n\u003c?php\n$i = 0;\n\n// Печатает числа от 1 до 10 пропустив число 5\nwhile($i \u003c 10) {\n  $i++;\n  if ($i == 5)\n    continue;\n  print ($i . \"\u003cbr\u003e\");\n}\n?\u003e\n```\n\n**Операторы `break` и `continue` во вложенных циклах**\n\nПо умолчанию `break` и `continue` выходят на один уровень вложенности, если необходимо чтобы `break` или `continue` участвовал и во внешних циклах, надо указать через пробел число соответствующее уровню:\n\n```php\n\u003c?php\n$levelOne = 0;\n\n// Печатает таблицу умножения от 1 до 10\nwhile ($levelOne \u003c 10) {\n  $levelOne++;\n  $levelTwo = 0;\n  while ($levelTwo \u003c 10) {\n    $levelTwo++;\n    if ($levelOne == 2)\n      break 2; // или continue 2\n    echo \"| \", $levelOne * $levelTwo, \" \";\n  }\n}\n?\u003e\n```\n\nЕсли во втором вложенном цикле `while` используется `break`, то скрипт напечатает таблицу умножения только для числа 1 (`1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10`) и прервет внешний цикл выйдя из него насовсем.\n\nЕсли же будет использоваться `continue`, то скрипт прервёт лишь итерации для числа 2, но продолжит выполнение для остальных чисел (`1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30` ...и так далее)\n\n    ❗️ Значение оператора `break` или `continue` не должны\n    превышать уровень вложенности структуры.\n\n### do..while\n\nСинтаксис:\n\n```php\n\u003c?php\ndo {\n  инструкция 1;\n  инструкция 2;\n} while (условие);\n?\u003e\n```\n\nОтличие от цикла `while` в том, что если условие изначально ложно, тело цикла выполнится хотя бы один раз. Пример с таблицей умножения в цикле `while` можно переписать так:\n\n```php\n\u003c?php\n$levelOne = 0;\n\ndo {\n  ++$levelOne;\n  $levelTwo = 0;\n  do {\n    $levelTwo++;\n    if ($levelOne == 2)\n        continue 2;\n    echo '• ', $levelOne * $levelTwo, ' ';\n  } while($levelTwo \u003c 10);\n} while($levelOne \u003c 10);\n?\u003e\n```\n\n### foreach\n\nКонструкция `foreach` (для каждого) дает простой способ перебора массивов. `foreach` работает только с массивами и объектами, и будет генерировать ошибку при попытке использования с переменными других типов или неинициализированными переменными. Чтобы вывести только значения элементов массива, применим короткий синтаксис:\n\n```php\n\u003c?php\n$user = array(\n  \"name\" =\u003e \"Jane\",\n  \"last-name\" =\u003e \"Doe\",\n  \"age\" =\u003e 35,\n  \"height\" =\u003e 175,\n  \"weight\" =\u003e 55,\n  \"hair-color\" =\u003e 'brown'\n);\n\nforeach($user as $value) {\n  echo $value, \"\u003cbr\u003e\";\n}\n?\u003e\n```\n\nВторая форма делает то же самое, за исключением того, что ключ текущего элемента будет присвоен переменной `$k` соответствующей каждому значению:\n\n```php\n\u003c?php\nforeach($myArray as $k =\u003e $v) {\n  echo $k . \" — \" . $v . \"\u003cbr\u003e\";\n  if (is_string($v))\n    $v = '';\n}\n?\u003e\n```\n\nВ выражении `$v = ''` на оригинальный массив эти изменения не повлияют, т.к. в переменную `$v` передается копия значения.\n\nЕсли всё же необходимо, чтобы изменения затрагивали данные исходного массива который перебираем, то перед переменной используется `\u0026`, тогда обращение будет происходить по ссылке на оригинальный массив.\n\n```php\n\u003c?php\nforeach($array as \u0026$v)\n  if (is_string($v))\n    $v = '';\n?\u003e\n```\n\n## Функции\n\n_Функция_ – программный блок, который может многократно выполняться в любом месте сценария.\n\n### Объявление и вызов\n\n```php\n\u003c?php\nfunction hello() {\n  echo \"Hello, world!\";\n}\n?\u003e\n```\n\n**Вызов функции**\n\n```php\n\u003c?php sayHello(); ?\u003e\n```\n\n### Аргументы функции\n\nАргументы передаются списком разделённых запятыми выражениями.\n\n```php\n\u003c?php\nfunction hello($name) {\n  echo \"Hello, $name!\";\n}\n\nhello(\"John\"); // -\u003e Hello, John!\n\n$name = \"Jane\";\nhello($name); // -\u003e Hello, Jane!\n\n$funcName = \"hello\";\n$funcName($name); // -\u003e Hello, Jane!\n?\u003e\n```\n\nВ последнем случае, если вслед за переменной стоит открывающая круглая скобка, то PHP интерпретирует это как вызов функции.\n\n### Аргументы по умолчанию\n\nФункция может определять значения по умолчанию путём присваивания его переменной аргумента. Это значение будет применено если параметр не был передан при вызове функции.\n\n```php\n\u003c?php\nfunction sayHello($name = \"Guest\", $h = 3) {\n  echo \"\u003ch$h\u003eHello, $name!\u003c/h$h\u003e\";\n}\n\n// Все аргументы передаются\nsayHello(\"John\", 1); // -\u003e \u003ch1\u003eHello, John!\u003c/h1\u003e\n\n\n$name = \"Jane\";\n// Второй аргумент потерян, будет прменен по умолчанию 3\nsayHello($name); // -\u003e \u003ch3\u003eHello, Jane!\u003c/h3\u003e\n\n// Все аргументы применятся по умолчанию\nsayHello(); // -\u003e \u003ch3\u003eHello, Guest!\u003c/h3\u003e\n?\u003e\n```\n\nЕсли в функции есть параметры обязательные и по умолчанию, то сначала (слева направо) перечисляются обязательные параметры, а потом уже не обязательные. Пример ошибочной передачи параметров:\n\n```php\n\u003c?php sayHello(, 3); ?\u003e\n```\n\n### Области видимости переменных\n\nВ PHP существует два вида области видимости переменных — глобальная и локальная.\n\nГлобальные переменные это все переменные вне тела функции, локальные переменные это те что находятся в теле функции.\n\n```php\n\u003c?php\n// Глобальные переменные\n$a = 7; $b = 9;\n\n// Параметры функции — локальные переменные\nfunction summa($a, $b) {\n  global $a , $b; // Ссылка на глобальные переменные\n  return $a + $b;\n}\n\n// Возвращает 16 если переменные $a и $b\n// определены внутри функции global, иначе 36\necho summa(17, 19);\n?\u003e\n```\n\nПосле определения `$a` и `$b` внутри функции ключевым словом `global` все ссылки на любую из этих переменных будут указывать на их глобальную версию. Не существует никаких ограничений на количество глобальных переменных, которые могут обрабатываться функцией.\n\nВторой способ доступа к переменным глобальной области видимости — использование специального, определяемого PHP массива `$GLOBALS`. При создании переменной и присваивании ей значения PHP заносит данные в этот массив:\n\n```php\n\u003c?php\n// Объявление глобальной переменной\n$age = 20;\n\n// Альтернативный вариант создания глобальной переменной\n$GLOBALS['age'] = 20;\n?\u003e\n```\n\nПредыдущий пример может быть переписан так:\n\n```php\n\u003c?php\n$a = 7; $b = 9; $cnt;\n\nfunction summa($a, $b) {\n  // Объявление $cnt как глобальная переменная\n  $GLOBALS['cnt'];\n  \n  // ну или так\n  global $cnt;\n  \n  // Подсчет кол-ва вызовов функции\n  $cnt++;\n  return $GLOBALS[\"a\"] + $GLOBALS[\"b\"];\n}\n\necho summa(17, 19);\necho summa(21, 15);\necho summa(14, 37);\necho \"Функция summa была вызвана $cnt раз(а)\";\n?\u003e\n```\n\n### Статические переменные\n\nВ примере ниже мы хотим чтобы переменная `$a` сохраняла своё значение при каждом вызове функции и не теряла его, когда выполнение программы выходит из этой области видимости.\n\n```php\n\u003c?php\nfunction staticVar($a) {\n  $a = 0;\n  echo $a;\n  $a++\n}\n\nstaticVar(); // -\u003e 0\nstaticVar(); // -\u003e 0\nstaticVar(); // -\u003e 0\n?\u003e\n```\n\nТакая реализация будет абсолютно бесполезной поскольку при каждом вызове она устанавливает `$a` в `0` и печатает `0`. Инкремент переменной `$a++` здесь не играет роли, так как при выходе из функции переменная `$a` исчезает.\n\nСтатические переменные существуют только в локальной области видимости функции. Чтобы написать полезную считающую функцию, которая не будет терять текущего значения счетчика, переменная `$a` объявляется как `static`:\n\n```php\n\u003c?php\nfunction staticVar() {\n  static $a = 0;\n  echo $a;\n  $a++;\n}\nstaticVar(); // -\u003e 0\nstaticVar(); // -\u003e 1\nstaticVar(); // -\u003e 2\n?\u003e\n```\n\n### Рекурсия\n\nРекурсия – это способность функции вызывать саму себя изнутри. Ниже приведён классический пример реализации такого подхода в вычислении факториала для заданного числа.\n\n```php\n\u003c?php\nfunction factorial($n) {\n  if ($n == 0) return 1;\n  return $n = $n * factorial($n - 1); // Функция вызывает саму себя\n}\n\necho factorial(5); // -\u003e 120\n?\u003e\n```\n\n### Функции управления функциями\n\n**Проверка на существование**\n\nФункция `function_exists` возвратит `true` если функция с переданным названием уже есть.\n\n```php\n\u003c?php\nif(!function_exists(\"hello\")) {\n  // такой функции нет, можно создать её \n}\n?\u003e\n```\n\n**Список объявленных функций**\n\nЕсли нужно получить список всех определённых функций, как встроенных, так и пользовательских применяется функция `get_defined_functions`, которая возвратит список функций в виде многомерного массива.\n\n```php\n\u003c?php print_r(get_defined_functions()); ?\u003e\n```\n\n**Работа с функцией изнутри**\n\nСледующие функции применяются внутри тела функций.\n\n```php\n\u003c?php\nfunction foo() {\n  // Количество аргументов передаваемых функции\n  echo func_num_args();\n\n  // Возвращает массив аргументов функции  \n  print_r(func_get_args());\n\n  // Возвращает элемент из списка аргументов\n  echo func_get_arg(0); // -\u003e John\n}\n\nfoo(\"John\", 77, true);\n?\u003e\n```\n\n## Классы и объекты\n\nКласс определяется ключевым словом `class` за которым следует его имя и пара фигурных скобок. Внутри скобок могут содержаться свойства и методы этого класса.\n\n* Свойство класса – переменная внутри класса;\n* Методы – функции класса;\n* Имена класса чувствительны к регистру.\n\n### Описание класса\n\n```php\n\u003c?php\nclass MyClass {\n  // определение свойств\n  // определение методов\n}\n?\u003e\n```\n\nПример готового класса.\n\n```php\n\u003c?php\nclass Car {\n  public $year = 2023;\n  public $speed;\n  public $model;\n}\n\n// Иницилизация класса (создание объекта)\n$car1 = new Car(); // Объект, он же экземпляр класса\n$car2 = new Car();\n// Теперь $car1 и $car2 имеют все свойства класса Car\n?\u003e\n```\n\nОбращение к свойству происходит с помощью стрелки `-\u003e` затем следует имя свойства без указания знака `$`.\n\n```php\n\u003c?php\necho $car1-\u003eyear; // Обращение к свойству\n$car1-\u003espeed = 210; // Присваивание значения\n?\u003e\n```\n\n### Области видимости\n\nОбласти видимости свойств, методов или констант могут быть определены через следующие спецификаторы (модификаторы) доступа:\n\n* `public` (_публичный_, _общедоступный_) – позволяет иметь доступ к свойствам и методам класса из любого места;\n* `protected` (_защищённый_) – позволяет иметь доступ и родительскому (в котором определен сам член класса), и наследуемым классам;\n* `private` (_закрытый_) – ограничивает область видимости тем классом, в котором он объявлен.\n\n```php\n\u003c?php\nclass First {\n  public $name = 'Jane';\n  protected $age = 37;\n  private $sex = 'female';\n\n  public function getInfo(){\n    $this-\u003ename;\n    $this-\u003eage;\n    $this-\u003esex;\n  }\n}\n\nclass Second extends First {\n  // class body\n}\n\n$third = new Second();\n$third-\u003ename; // -\u003e Alex\n$thid-\u003eage; // -\u003e Fatal error\n$third-\u003esex; // -\u003e Notice: Undefined property\n?\u003e\n```\n\n**Псевдопеременная `$this`**\n\n`$this` – указатель на запрашиваемый объект, доступна в случае, если метод был вызван в контексте объекта. Используется чтобы явно указать какой объект имеется ввиду для доступа из метода к свойству объекта. Вызов метода из метода также происходит через ключевое слово `$this`.\n\n```php\n\u003c?php\nclass Car {\n  // по умолчанию public, т.е. можно не указывать\n  public function getSpeed() {\n    // $this — указатель на свойство класса\n    echo \"Скорость = \" . $this-\u003espeed;\n  }\n  \n  function avgSpeed() {\n    'Скорость = ' . $this-\u003egetSpeed(); // Обращение к методу\n  }\n}\n\n$myCar = new Car();\n$myCar-\u003egetSpeed(); // вызов метода\n?\u003e\n```\n\n### Конструкторы и деструкторы\n\n_Конструктор класса_ – специальный метод, который автоматически вызывается в момент создания объекта. Используется когда нужно что-нибудь сделать при создании объекта (посыл cookie, запись в файл, ...).\n\n_Деструктор класса_ – автоматически вызывается при удалении объекта. Деструктор не принимает параметров, скобки есть просто по синтаксису.\nПорядок удаления объектов в PHP не определен, поэтому в деструкторах не обращаются к другим объектам, т.к. на момент вызова деструктора он может быть уже удален.\n\nСначала PHP ищет метод `__construct`, если он его не находит, то ищет метод одноименный с именем класса и расценивает его как конструктор. Но если `__construct` будет, то одноименный метод станет обычным методом.\n\n```php\n\u003c?php\nclass User{\n  public $name = 'John';\n  public $login = 'johndoe';\n  public $password = '1234';\n\n  function __construct($name, $login, $password) {\n    $this-\u003ename = $name;\n    $this-\u003elogin = $login;\n    $this-\u003epassword = $password;\n  }\n\n  function __destruct(){ \n    echo '\u003cp\u003e\u003cОбъект удален!/p\u003e';\n  }\n}\n\n// При иницилизации автоматически сработает конструктор\n// В скобках передаются параметры конструктору\n$user1 = new User('Jane', 'janedoe', 'p@$$w0rd');\n\n// При удалении или окончании кода вызовется деструктор\nunset($user1);\n?\u003e\n```\n\n### Клонирование объектов\n\nИногда может понадобиться создать копию объекта, но создание копии с идентичными свойствами через обычное присваивание не всегда оказывается приемлемым вариантом. Для таких случаев копия объекта создаётся с помощью ключевого слова `clone`.\n\n```php\n\u003c?php\n$myObject = clone $myObject1; // копия (клонирование)\n$myObject2 = $myObject1; // ссылка\n$myObject2 = \u0026$myObject1; // ссылка\n?\u003e\n```\n\nХотя и при клонировании создается новый объект, конструктор не вызывается. Для этого существует специальный метод `__clone`, который будет вызван при клонировании.\n\n```php\n\u003c?php\nclass Car {\n  function __construct($mark, $model, $speed) {\n    $this-\u003emark = $mark;\n    $this-\u003emodel = $model;\n    $this-\u003espeed = $speed;\n  }\n  \n  // Выполнится при клонировании объекта\n  function __clone() {\n    $this-\u003emark = 'Unknown';\n    $this-\u003emodel = 'Unknown';\n    $this-\u003espeed = 0;\n  }\n}\n\n// Иницилизация объекта\n$car1 = new Car('Tesla', 'Model X', 210);\n$car1-\u003emodel; // Tesla\n$car2 = clone $car1; // Клонирование\n$car2-\u003emodel; // Unknown\n?\u003e\n```\n\n### Наследование\n\n_Наследование_ – дочерний класс наследует все публичные и защищенные свойства и методы родительского класса. При объявлении класса, нужно указать какой класс он наследует (`extends`).\n\n```php\n\u003c?php\n// Создание класса\nclass good {\n  public $title;\n}\n\n// Наследование класса good\nclass book extends good {\n  public $year;\n}\n\n$book1 = new book();\n// Нам доступны свойства и методы родительского класса\n$book1-\u003eyear;\n$book1-\u003etitle;\n?\u003e\n```\n\n### Перегрузка методов\n\n_Перегрузка методов_ – если имена методов в разных классах одинаковы, то применится метод описанный в классе к которому мы обращаемся, а не в родительском классе.\n\n```php\n\u003c?php\nclass Product {\n  public $title;\n\n  function __construct($title) {\n    $this-\u003etitle = $title;\n  }\n  \n  function getInfo() {\n    return 'Product class';\n  }\n}\n\nclass Book extends Product {\n  public $year;\n\n  // Перегрузка метода getInfo()\n  function getInfo() {\n    return __CLASS__;\n  }\n}\n\n$book1 = new Book('PHP \u0026 MySQL: Server-side Web Development');\n$book1-\u003egetInfo(); // -\u003e Book\n?\u003e\n```\n\n`parent` – обращение к родительским свойствам, методам, конструкторам, деструкторам, клонам, ...\n\n```php\n\u003c?php\nclass Book extends Good {\n  public $year;\n\n  function __construct($title, $year) {\n    // Отрабатывает родительский конструктор\n    parent::__construct($title);\n    // Дополняем конструктор новым свойством\n    $this-\u003eyear = $year;\n  }\n}\n\n$book2 = new Book(\n  'PHP 8 Programming Tips, Tricks and Best Practices',\n  2023\n);\n?\u003e\n```\n\n### Перебор свойств объекта\n\nПеребор свойств объекта PHP осуществляется с помощью цикла `foreach`. Для большего контроля над данными можно использовать его расширенную версию с извлечением ключей `$key`, где будут храниться имена свойств объекта.  \n\n```php\n\u003c?php\nclass Student {\n  public $name, $course, $faculty;\n\n  function __construct($name, $course, $faculty) {\n    $this-\u003ename = $name;\n    $this-\u003ecourse = $course;\n    $this-\u003efaculty = $faculty;\n  }\n}\n\n$student = new student('John Doe', 3, 'PHP Programming');\n\nforeach($student_1 as $key =\u003e $value) {\n  print \"\u003cp\u003e$key: $value\u003c/p\u003e\";\n}\n?\u003e\n```\n\n### Константы класса\n\nКонстанты класса определяются с помощью ключевого слова `const`. Доступ к константе внутри класса – `self::ИМЯ_КОНСТАНТЫ`, вне класса – `имя_класса::ИМЯ_КОНСТАНТЫ`.\n\nК имени класса можно обратиться с помощью переменной присвоив ей в качестве значения имя класса. Значение переменной не должно быть ключевым словом (например, `self`, `parent` или `static`).\n\n```php\n\u003c?php\nclass Animal {\n  const\n    eyes = 2, ears = 2, paws = 4, tail = 1; // Объявление констант\n\n  function pawsQuantity() {\n    // Доступ к константе внутри класса\n    return self::paws;\n  }\n}\n\n$tiger = new Animal();\n\n// Доступ к константе вне класса\necho Animal::ears;\necho $tiger-\u003epawsQuantity(); // -\u003e 4\n\n// Значение такое же как и имя класса\n$getTail = 'Animal';\necho $getTail::tail; // -\u003e 1\n?\u003e\n```\n\n### Абстрактные классы и методы\n\nОт абстрактного класса нельзя напрямую создавать объект. А создается объект от наследника абстрактного класса.\n\nВнутри абстрактного класса может быть и абстрактный метод. _Абстрактный метод_ – это метод без реализации (фигурных скобок). Он должен быть перегружен в классе наследника (иначе будет ошибка уровня _Fatal error_).\n\nЕсли в классе появился хоть один абстрактный метод, весь класс должен быть объявлен как абстрактный. Абстрактный класс может быть без абстрактного метода, но не наоборот.\n\n```php\n\u003c?php\nabstract class DB {\n  function db_connect() {\n    mysqli_connect('localhost', 'root', 'root', 'eshop');\n  }\n  \n  // Абстрактный метод без реализаций\n  abstract function db_query($sql);\n  abstract function db_close();\n}\n\nclass DB_inherit extends DB {\n  // Обязательно должен быть продекларирован\n  function db_query($sql){}\n  function db_close(){}\n}\n\n$Schema = new DB(); // Ошибка уровня Fatal error\n$Schema = new DB_inherit();\n?\u003e\n```\n\n### Интерфейсы\n\n_Интерфейс_ – это тот же самый абстрактный класс, но который содержит только абстрактные методы. Для интерфейса справедливы все правила абстрактного класса, но со следующими отличиями:\n\n* В интерфейсе все методы должны быть абстрактными;\n* Наследуемый класс определяется с помощью ключевого слова implements;\n* При описании интерфейса не используются слова class и abstract.\n\nЕсли необходимо обозначить не только абстрактные методы, но и реализованные методы и свойства, то применить нужно абстрактные классы.\n\n```php\n\u003c?php\ninterface DB {\n  function db_connect($host, $user, $password, $schema);\n  function db_query();\n  function db_close();\n}\n\nclass DB2 implements DB {\n  function db_connect($host, $user, $password, $schema){}\n  function db_query(){}\n  function db_close(){}\n}\n?\u003e\n```\n\nPHP не поддерживает множественное наследование. Однако, мы можем реализовывать класс от нескольких интерфейсов. Например, `class` A `extends` B `implements` C, D, E, F, ...\n\n```php\n\u003c?php\ninterface Head {\n  function ears();\n}\n\ninterface Hands {\n  function fingers();\n}\n\nclass Body implements Head, Hands {\n  function ears(){}\n  function fingers(){};\n}\n?\u003e\n```\n\n### Финальные классы и методы\n\nКлючевое слово `final` предотвращает переопределение метода в дочерних классах. Если же сам класс определяется с этим ключевым словом, то он не может быть унаследован.\n\n```php\n\u003c?php\nclass A {\n  final function foo(){}\n}\n\nclass B extends A {\n  function foo(){} // нельзя перегружать\n}\n?\u003e\n```\n\n### Статические свойства и методы\n\nК статическим свойствам и методам можно обращаться без создания экземпляра класса с помощью оператора `::`. По этой причине псевдопеременная `$this` не может быть использована внутри таких методов.\n\n```php\n\u003c?php\nclass staticClass {\n  static $address, $book_count;\n  public $name;\n\n  function __construct() {\n    // Обращение к статическому свойству и его инкремент\n    self::$address++;\n  }\n\n  static function staticFunction($book_name) {\n    // Преинкремент статического свойства\n    ++self::$book_count;\n    $name = $book_name;\n  }\n}\n\n$book1 = new staticClass();\n$book2 = new staticClass();\n$book3 = new staticClass();\n\n// Обращение к статическому свойству вне класса\nstaticClass::$address;\n//Обращение к статическому методу вне класса\nstaticClass::staticFunction('PHP \u0026 MySQL: Server-side Web Development');\nstaticClass::staticFunction('PHP 8 Objects, Patterns, and Practice');\necho staticClass::$book_count; // -\u003e 2\n?\u003e\n```\n\n`static` также используется для определения статических переменных, которые были рассмотрены в главе [Статические переменные](#Статические-переменные).\n\n### Ключевое слово instanceof\n\n`instanceof` – если требуется узнать, является ли класс унаследованным от другого класса или интерфейса.\n\nТакже можно использовать функцию `is_a()`, которая проверяет, принадлежит ли объект к данному классу или содержит данный класс в числе своих предков.\n\n```php\n\u003c?php\nclass User {}\n\nclass SuperUser extends User {}\n\nfunction checkObject($object) {\n  // Принадлежит ли переданный объект классу\n  if ($object instanceOf User) {\n    if ($object instanceof SuperUser)\n      return 'Данный пользователь обычный пользователь';\n    else\n      return 'Данный пользователь обладает правами администратора';\n  }\n  else\n    return 'Неизвестный пользователь';\n}\n?\u003e\n```\n\n### Автоматическая загрузка классов\n\nЕсли PHP не может найти класс, то он прежде чем выдать ошибку сначала ищет функцию `__autoload()` передавая имя искомого класса. Если функция описана, то она будет вызвана перед ошибкой.\n\n```php\n\u003c?php\nfunction __autoload($class) {\n  print(\"Класс $class не описан\");\n}\n\n$car1 = new car();\n?\u003e\n```\n\nОсновное назначение функции `__autoload` подгружать файл где описан не найденный в текущем файле класс. Для этого необходимо создать файл с таким же названием, как и имя искомого класса.\n\n```php\n\u003c?php\nfunction __autoload($class) {\n  // Файл где описан класс\n  include \"$class.class.php\";\n}\n$car1 = new car();\n?\u003e\n```\n\n### Магические методы\n\n_Магические методы_ – это специальные методы, которые переопределяют действие PHP по умолчанию, в момент когда над объектом выполняются определённые действия. В PHP есть следующие магические методы: `__construct()`, `__destruct()`, `__call()`, `__callStatic()`, `__get()`, `__set()`, `__isset()`, `__unset()`, `__sleep()`, `__wakeup()`, `__serialize()`, `__unserialize()`, `__toString()`, `__invoke()`, `__set_state()`, `__clone()` и `__debugInfo()`.\n\n#### Методы доступа к свойствам объекта\n\nКогда происходит **присваивание** значения к свойству, который не описан в классе – PHP, прежде чем создать это свойство, сначала ищет магический метод `__set()` куда передает имя и значение.\n\nКогда происходит **обращение** к неизвестному свойству, который не описан в классе – PHP ищет магический метод `__get()`, куда передает имя свойства, и если такой метод есть, он вызывается.\n\n```php\n\u003c?php\nclass A {\n  public $params = array();\n\n  function __set($name, $value){\n    // Присваивание ячейке массива\n    $this-\u003eparams[$name] = $value;\n  }\n\n  function __get($name){\n    // Есть ли ключ с таким именем в массиве $params?\n    if (array_key_exists($name, $this-\u003eparams))\n      return $this-\u003eparams[$name];\n  }\n  \n  // Возвращает имя: значение неописанных свойств\n  function getArg(){\n    foreach($this-\u003eparams as $k=\u003e$v){\n      echo \"\u003cp\u003e$k: $v\u003c/p\u003e\";\n    }\n  }\n}\n\n$obj = new A;\n\n//Присваивание неописанному свойству\n$obj-\u003ename = 'John';\n$obj-\u003elast_name = 'Doe';\n$obj-\u003eage = 30;\n$obj-\u003egetArg();\n\n// Обращение к неописанному свойству\necho $obj-\u003ename; // -\u003e John\n?\u003e\n```\n\n#### Перегрузка вызова несуществующих методов\n\nЕсли идет обращение к методу который не описан в классе, PHP ищет магический метод `__call()`, куда передает имя несуществующего метода и массив параметров.\n\n```php\n\u003c?php\nclass A {\n  function __call($name, $argument){\n    echo \"function $name with the next arguments: \",\n    implode(', ', $argument), ' does not exist';\n  }\n}\n\n$obj = new A;\n$obj-\u003efoo(123, 'milk', 'bread', 'solt'); // Такого метода нет в классе\n?\u003e\n```\n\n#### Преобразование объекта в строку\n\nПри попытке конвертации объекта в строку, следует вызов магического метода `__toString()`.\n\n```php\n\u003c?php\nclass A {\n  function __toString(){\n    return 'Это класс \"A\"';\n  }\n}\n\n$obj = new A;\n// Конвертация объекта, вызов метода __toString()\necho $obj; // -\u003e Это класс \"A\"\n?\u003e\n```\n\n### Разыменование объектов\n\nМы можем создавать объект динамически (на лету) обращаться к его методам, не создавая самого объекта.\n\n```php\n\u003c?php\nclass A {\n  public function myFunction(){\n    echo 'This class is \"A\"';\n  }\n}\n\nclass B {\n  public function myFunction(){\n    echo 'This class is \"B\"';\n  }\n}\n\nfunction dereference($object){\n  switch($object){\n    // Возвращает созданный объект\n    case 'A' : return new A;\n    case 'B' : return new B;\n  }\n}\n\n// Вызывается метод динамически созданного объекта\ndereference('A')-\u003emyFunction(); // -\u003e This class is \"A\"\n?\u003e\n```\n\n### Уточнение типа класса\n\nPHP предоставляет возможность уточнить тип класса. Сделать это можно при передаче параметров метода, указав перед переменной название класса объекта.\n\n```php\n\u003c?php\ninterface Foo {\n  function func1(Foo $foo);\n}\n\ninterface Bar {\n  function func2(Bar $bar);\n}\n\nclass MyClass implements Foo, Bar {\n  public function func1(Foo $foo) {\n    // код метода\n  }\n\n  public function func2(Bar $bar) {\n    // код метода\n  }\n}\n\n$obj1 = new MyClass;\n$obj2 = new MyClass;\n$obj1-\u003efunc1($obj2);\n$obj1-\u003efunc2($obj2);\n?\u003e\n```\n\n## Cookies\n\n_Cookie_ позволяют сохранять пользовательские данные в браузере для последующей идентификации или отслеживания. _Cookie_ посылается серверу, чтоб тот \"сказал\" браузеру, чтобы он установил _cookie_ для текущего пользователя. Передаются _Cookie_ вместе с HTTP-заголовками в ответе сервера и если _Cookie_ у пользователя уже существует, то оно отправится при запросе вместе с HTTP-заголовками.\n\nHTTP-заголовок `Set_Cookie: UserName=John` – при ответе на запрос.\nЗаголовок `Cookie: UserName: John` – если у нас уже есть _Cookie_, то она отправляется при запросе.\n\n_Cookie_ может быть сессионная или условно постоянная. _Сессия_ – время до закрытия браузера. Постоянные _Cookie_ могут быть до тех пор, пока пользователь намеренно не очистит свой браузер от них.\n\n### Создание Cookie\n\n```php\nsetcookie(\n  \"название-cookie\",\n  \"значение-cookie\",\n  период действия (временая метка Unix),\n  \"путь (директория в которой доступна cookie)\",\n  \"домен (которому будет доступна cookie)\",\n  true (если отправляется по безопасному протоколу HTTPS)\n);\n```\n\nВ имени куки должны быть только латинские буквы, цифры, символ подчеркивания и дефис. Все другие символы будут преобразованы в символ подчеркивания.\n\n### Чтение Cookie\n\n```php\n\u003c?php\n// Отправка куки \"навсегда\" (до 2038 года)\nsetcookie('cookieName', 'PHP', time() + 0x7FFFFFFF);\n\necho $_COOKIE['cookieName']; // -\u003e PHP\n\nwhile(list($name, $value) = each($_COOKIE) {\n  $myArray[] = $value; // для индексированного массива\n  $myArray[$name] = $value; // для ассоциативного массива\n}\n?\u003e\n```\n\nМассивы хранятся в _Cookie_ в сериализованном виде.\n\n```php\n\u003c?php\n$userInfo = array(\n  'name' =\u003e 'Jane',\n  'age' =\u003e 37,\n  'e-mail' =\u003e 'me@janedoe.com',\n  'uri' =\u003e 'https://janedoe.com'\n);\n\n// Сериализация массива в строку\nserialize($userInfo);\n// Выставление cookie на две недели\nsetcookie('userInfo', serialize($userInfo), time() + 1209600);\n// Десериализация и перевод в массив\n$userInfo = unserialize($_COOKIE['userInfo']);\n?\u003e\n```\n\n### Удаление Cookie\n\nЧтобы удалить _Cookie_, официально принято послать имя _Cookie_ без значения.\n\n```php\n\u003c?php setcookie('CookieName'); ?\u003e\n```\n\nили послать _Cookie_ с пустым значением:\n\n```php\n\u003c?php setcookie('CookieName', ''); ?\u003e\n```\n\nили указав заднее время:\n\n```php\n\u003c?php setcookie('CookieName', '', time() - 3600); ?\u003e\n```\n\n## Сессии\n\n_Сессия_ – глобальная переменная (ассоциативный массив), хранящаяся на сервере и содержащий переменные сессии, которые доступны из всех файлов сразу. Грубо говоря сессии – это аналог _Cookie_, данные которых, временно хранятся у нас на сервере.\n\nБраузер создает сессионную _Cookie_, по умолчанию с заг","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsa2kasov%2Fphp-reference-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsa2kasov%2Fphp-reference-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsa2kasov%2Fphp-reference-guide/lists"}