{"id":19925148,"url":"https://github.com/sa2kasov/php-reference-guide","last_synced_at":"2025-03-01T10:28:38.347Z","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-01-12T00:27:42.907Z","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,"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","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241352388,"owners_count":19948832,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":"2025-03-01T10:28:38.328Z","avatar_url":"https://github.com/sa2kasov.png","language":null,"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_, по умолчанию с заголовком `PHPSESSID` (можем изменить `session_name('cookie_name')`) с уникальным значением (`session_id()`), именно по нему происходит распознание пользователя. При запросе PHP распознает заголовок по умолчанию `sessid` с уникальным идентификатором.\n\nМеханизм сессий можно было б воссоздать вручную, в целом проделывается следующее:\n\n* Создается файл, со случайно сгенерированным именем;\n* Посылается сессионная _Cookie_;\n* Когда мы заносим данные в массив `$_SESSION` в файле сессии данные хранятся в сериализованной строке (функция `serialize()`);\n* Считывание данных, в массиве `$_SESSION` результат десериализации (функция `unserialize()`).\n\nКогда пользователь запрашивает страницу, мы проверяем есть ли для него сессия, если нет то создаем её. А когда необходимо подсчитать результаты, мы берем данные из глобального массива `$_SESSION` и выдаем результат.\n\nФизически на компьютере пользователя (`C:\\WINDOWS\\Temp`) создается файл с уникальным идентификатором, однозначно идентифицирующий пользователя, а когда сессия закончится – этот файл удалится сам.\n\n**Создание и использование**\n\nНачало и/или продолжение сессии осуществляется вызовом функции `session_start()`. Функция вызывается вначале исполнения файла, сессия при этом либо создаётся, либо продолжается.\n\nКогда создается сессия в браузер посылается Cookie следующего содержания:\n\n```php\n\u003c?php\necho session_name(), '=', session_id;\n// -\u003e PHPSESSID=btcii6g2ak26rsvogoov47jr25\n?\u003e\n```\n\nФизически данные сессии хранятся в файле, но для работы с переменными сессии есть глобальный массив `$_SESSION`. Если мы что-то хотим сохранить в сессии, то создаем ячейку и присваиваем значение.\n\n```php\n// Создание и доступ к элементу сессии\n$_SESSION['User'] = 'John';\necho $_SESSION['User']; // -\u003e John\n\n// Удаление ячейки массива\nunset($_SESSION['User']);\n\n// Закрытие сессии (физическое удаление файла)\nsession_destroy();\n?\u003e\n```\n\nПри закрытии сессии `session_destroy()` файл сессии удаляется физически, но _Cookie_ остается все равно и при очередном открытии сессии, браузер создаст файл с точно таким же идентификатором, поэтому рекомендуется сразу после закрытии сессии удалять и _Cookie_. Например:\n\n```php\n\u003c?php\nsession_destroy(); // Закрытие сессии\nsetcookie(session_name(), ''); // Удаление куки сессии\n?\u003e\n```\n\n## HTTP-заголовки\n\nВсе HTTP-заголовки посылаются с помощью функции `header(\"имя_заголовка: значение\")`. Структура HTTP-запроса на примере запроса `HEAD` выглядит следующим образом:\n\n_Запрос_\n\n```http request\nHEAD /folder/index.html HTTP/1.1\nHost: www.example.com\nAccept: */*\nAccept-Language: ru\nReferrer: https://google.com/search?text=SearchingText\nUser-Agent: Mozilla/5.0 (Windows NT 11.0; Win64; x64)...\n```\n\n_Ответ_\n\n```http request\nHTTP/1.1 200 OK\nServer: Microsoft IIS 10\nContent-Type: text/html\nContent-Length: 12345\nLast-Modified: Tue, 19 Oct 2023 00:45:00 GMT+6\n```\n\nКак только браузер встречает заголовок `Location`, то сразу перезапрашивает адрес указанный в заголовке `Location`, т.е. фактически происходит редирект на уровне HTTP-заголовков.\n\n```php\n\u003c?php header(\"Location: https://site.com\"); ?\u003e\n```\n\nОднажды отправленный запрос, со всеми передаваемыми заголовками при обновлении страницы браузера(`F5`) повторяет тот же самый запрос. С помощью `Location` можно от этого избавиться перезапросив эту же страницу методом GET.\n\n```php\n\u003c?php\nheader(\"Location: \" . $_SERVER['PHP_SELF']);\nexit; // Прекращает выполнение текущего скрипта\n?\u003e\n```\n\nПерезапрос страницы через определенное количество секунд:\n\n```php\n\u003c?php\n// Через 3 секунды Вы будете перемещены на главную страницу\nheader(\"Refresh: 3; url=https://x.com\");\n?\u003e\n```\n\nОбработка файла по указанному MIME-типу:\n\n```php\n\u003c?php\n// Передаваемый файл обрабатывать как text/xml с кодировкой utf-8\nheader(\"Content-type: text/xml; charset=utf-8\");\n?\u003e\n```\n\n**Управление кэшированием и актуальностью веб-страницы**\n\nБраузер может закэшировать страницу, но перед очередным запросом должен проверить - не обновлялась ли страница, если нет, то кэш используется.\n\n\n```php\n\u003c?php\n// Повторить запрос с сервера-источника\nheader('Cache-Control: no-cache');\n\n// Явный запрет на кэширование\nheader('Cache-Control: no-store');\n\n// Заголовок Expires говорит об актуальности этой страницы \nheader('Expires: ' . date('r'));\n\n// Последнее изменение страницы\nheader('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');\n\n// Разрешение\nheader('Cache-Control: public');\n\n// Страница будет актуальна один час\nheader('Expires: ' . date('r', time() + 3600));\n?\u003e\n```\n\n_Cookie_ можно послать с помощью функции `header()`, как HTTP-заголовок.\n\n```php\n\u003c?php\nheader('Set-Cookie: name=Hello; expires=Wed, 18 Oct 23 15:00:00 GMT');\n?\u003e\n```\n\n## Файлы\n\nPHP предоставляет набор функций для работы с файловой системой. Процесс манипуляции над файлом часто сводится к следующим шагам:\n\n- Открыть файл;\n- Выполнить операцию чтения, изменения или записи в файл;\n- Закрыть файл.\n\n### Получение сведений о файлах\n\n```php\n\u003c?php\n// Проверяет наличие указанного файла или каталога\nfile_exists('text.txt');\n\n// Возвращает размер файла\nfilesize('text.txt');\n\n// Дата последнего обращения к файлу (date(\"d M Y\", $atime))\nfileatime('text.txt');\n\n// Возвращает время последнего изменения файла (date(\"d M Y\", $mtime))\nfilemtime('text.txt');\n\n// Дата создания файла Windows (временная метка Unix)\nfilectime('text.txt');\n?\u003e\n```\n\n### Открытие и закрытие\n\n```php\n\u003c?php\n$f = fopen('text.txt', 'w+') or die('Файл не найден или еще что-то');\n\n// Открывает файл только для чтения и помещает указатель в начало файла\n$f = fopen('http://www.example.com/text.html', 'r');\n$f = fopen('http://ftp.example.com/text.html', 'r+');\n\n// Закрывает открытый дескриптор файла\nfclose($f);\n?\u003e\n```\n\n### Режимы работы с файлами\n\nmode | Описание\n:---:|---\n'r'\t | Открывает файл только для чтения; помещает указатель в начало файла.\n'r+' | Открывает файл для чтения и записи; помещает указатель в начало файла.\n'w'  | Открывает файл только для записи; в противном случае ведёт себя так же, как и `w+`.\n'w+' | Открывает файл для чтения и записи; помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует - пытается его создать.\n'a'  | Открывает файл только для записи; помещает указатель в конец файла. Если файл не существует - пытается его создать. В данном режиме функция `fseek()` не применима, записи всегда добавляются в конец.\n'a+' | Открывает файл для чтения и записи; помещает указатель в конец файла. Если файл не существует - пытается его создать. В данном режиме функция `fseek()` влияет только на позицию чтения, записи всегда добавляются в конец.\n'x'  | Создаёт и открывает только для записи; помещает указатель в начало файла. Если файл уже существует, вызов `fopen()` закончится неудачей, вернёт `false` и выдаст ошибку уровня `E_WARNING`. Если файл не существует, попытается его создать.\n'x+' | Создаёт и открывает для чтения и записи; в остальном имеет то же поведение, что и `x`.\n'c'  | Открывает файл только для записи. Если файл не существует, то он создаётся. Если же файл существует, то он не обрезается (в отличие от `w`), и вызов к этой функции не вызывает ошибку (также как и в случае с `x`). Указатель на файл будет установлен на начало файла. Это может быть полезно при желании заблокировать файл (смотрите `flock()`) перед изменением, так как использование `w` может обрезать файл ещё до того как была получена блокировка (если вы желаете обрезать файл, можно использовать функцию `ftruncate()` после запроса на блокировку).\n'c+' | Открывает файл для чтения и записи; в остальном имеет то же поведение, что и `c`.\n'e'  | Установить флаг `close-on-exec` (закрыть при запуске) на открытый файловый дескриптор.\n\n### Чтение файла\n\n```php\n\u003c?php\n$f = fopen('text.txt', 'r+') or exit('Нет файла или другая ошибка');\n\n// Чтение файла на указанную длину\necho fread($f, 9);\n\n// Функция fgets() читает файл построчно\necho fgets($f); // -\u003e строка\necho fgets($f); // -\u003e следующая строка\n\n// Функция fgetss() аналогична функции fgets() с той разницей,\n// что эта функция зачитывает файл без html и php тегов\necho fgetss($f, filesize('text.html'), '\u003ca\u003e\u003cbr\u003e');\n// -\u003e строка с сохранением тегов \u003ca\u003e и \u003cbr\u003e\n\n// Посимвольное считывание\necho fgetc($f); // -\u003e cимвол\necho fgetc($f); // -\u003e cледующий символ\n\nfclose($f); // Закрытие файла\n?\u003e\n```\n\n### Запись в файл\n\n```php\n\u003c?php\n// Получение дескриптора файла\n$connect = fopen('write.txt', 'r+');\n\n// Если нужно записать в конец файла,\n// то режим функции fopen() 'a' или 'a+'\n\n// Перезапишет слово \"Hello\" в начале строки\nfwrite($connect, 'Hello');\n\nfclose($connect);\n?\u003e\n```\n\n### Манипуляции с курсором\n\n```php\n\u003c?php\n$connect = fopen('text.txt', 'r+') or exit;\n\n// Перемещает курсор в конец файла и на 10 символов назад\nfseek($connect, -10, SEEK_END);\n\n// Зачитываем эти 10 символов\necho fread($connect, 10);\n\n// Возвращает текущую позицию файлового указателя\nftell($connect);\n\n// Сбрасывает курсор файлового указателя на начало файлового потока\nrewind($connect);\n\n// Аналогична rewind($connect);\nfseek($connect, 0);\n\n// Проверяет, достигнут ли конец файла\nfeof($connect);\n\nfclose($connect);\n?\u003e\n```\n\n### Прямая работа с данными\n\n```php\n\u003c?php\n// Возвращает массив где в каждой ячейке своя строка\n$myArray = file('text.txt');\n\n// аналогично работе следующего кода\n$f = fopen('text.txt', 'r') or die;\nwhile($line = $fgets($f))\n  $lines[] = $line;\nfclose($f);\n\n// Читает содержимое файла все в одну строку\nfile_get_contents('text.html');\n\n// Пишет строку в конец файла\nfile_put_contents('text.txt', \"\\nНовая строка\", FILE_APPEND);\n?\u003e\n```\n\n### Управление файлами\n\n```php\n\u003c?php\n// Перемещение файла text.txt из папки folder1 в папку folder2\nrename('folder1/text.txt', 'folder2/text.txt');\n\n// Переименование файла из \"text1.txt\" в \"text2.txt\"\nrename('text1.txt', 'text2.txt');\n\n// Копирование и переименование\ncopy('folder1/text.txt', 'folder2/text2.txt');\n\n// Удаление\nunlink('folder/text.txt');\n?\u003e\n```\n\n\n### Директории (каталоги)\n\n**Манипуляция с папками**\n\n```php\n\u003c?php\n// Создание вложенной папки в текущей директории\n// с самыми широкими правами (0777)\nmkdir('./firstCatalog/secondCatalog', 0777, true);\n\n// Переименование\nrename(\"myfolder\",\"newfolder\");\n\n// Перемещение\nrename(\"myfolder\",\"newfolder/myfolder\");\n\n// Удаление каталога (если он пустой)\nrmdir('./newCatalog');\n?\u003e\n```\n\n**Открытие и чтение**\n\n```php\n\u003c?php\n// Открытие текущей директории\n$dir = opendir('.');\n\n// Чтение директории\n$catalog_or_file = readdir($dir); // -\u003e имя папки или false, если ошибка\n\n// Закрытие директории\nclosedir($dir); // Освобождает дескриптор каталога\n?\u003e\n```\n\n**Сканирование директории**\n\n`scandir()` получает массив элементов текущей директории. Если передать второй параметр `true`, то функция вернет массив в обратном порядке.\n\n```php\n\u003c?php\nprint_r(scandir('.')); // Массив содержимого папки\nis_dir('./catalog/folder'); // Это папка?\nis_file('./catalog/file.txt'); // Это файл?\n?\u003e\n```\n\n**Организация вывода всех файлов и папок в директории**\n\n```php\n\u003c?php\n$d = opendir('.');\n// Пока переменная получает элемент каталога...\nwhile($myDir = readdir($d)) {\n  if(is_dir($myDir)) // Если это папка\n    echo '\u003cp\u003eЭто папка ' . $myDir . '\u003c/p\u003e';\n  else\n    echo '\u003cp\u003eЭто файл ', $myDir, '\u003c/p\u003e';\n}\n?\u003e\n```\n\nРазработчики PHP не гарантируют порядок выборки файлов и директории. Обычно элементы директории возвращаются в том порядке, в котором они хранятся в файловой системе, но это не значит, что это будет так везде (зависит от ряда факторов: операционная система, версии PHP и т.д.). Для контроля вывода, рекомендуется элементы сначала добавить в массив (функция `scandir()`) и отсортировать их.\n\n### Загрузка файлов на сервер\n\nФайлы загружаются на сервер только методом _POST_. При этом атрибут `enctype` тега `\u003cform\u003e` должен быть `multipart/form-data`.\n\nДля отправки файлов на сервер может понадобиться настройка конфигурационного файла `php.ini`, а именно следующие параметры:\n\n* `file_uploads (on | off)` – разрешает или нет закачивание файлов;\n* `upload_tmp_dir` – временная директория, используемая для временного хранения закачанных файлов. Должна быть доступна для записи пользователю, от имени которого запущен PHP. Если не указана, используется директория по умолчанию для вашей системы. Если для указанной директории нет прав на запись, PHP откатится обратно к системной временной директории, используемой по умолчанию. Если включена директива `open_basedir`, то для успешной загрузки файлов системная директория по умолчанию должна быть разрешена;\n* `upload_max_filesize` – по умолчанию равна 2 Мб, максимальный размер закачиваемого файла. Здесь нужно чтобы значение директивы `post_max_size` было больше значения `upload_max_filesize`;\n* `post_max_size` – устанавливает максимально допустимый размер данных, отправляемых методом POST. Это значение также влияет на загрузку файлов на сервер.\n\nЧтобы ограничить размер посылаемых данных (например: аватарок на форуме) можно создать скрытый `input` и задать параметру `MAX_FILE_SIZE` определенное значение:\n\n```html\n\u003cform action=\"upload.php\" method=\"post\" enctype=\"multipart/form-data\"\u003e\n  \u003cinput type=\"file\" name=\"userFile\"\u003e\n  \u003cbutton type=\"submit\"\u003eПослать файл\u003c/button\u003e\n\u003c/form\u003e\n```\n\n### Разбор файлов на сервере\n\nПосле отправки файла на сервер все файлы сначала попадают во временную директорию, которая указана в директиве `upload_tmp_dir`. Когда файлы попадают в эту директорию, они временно переименовываются. И вся информация, которая к нам приходит, попадает в суперглобальную переменную `$_FILES`.\n\nМассив `$_FILES` двумерный, ячейка первая — это имя поля, которое указано в атрибуте name тега `input`, а в ней в свою очередь 5 ячеек:\n\n```php\n\u003c?php\n// Реальное имя файла (пример: logo.gif)\n$_FILES['значение атрибута name тега input']['name'];\n\n// MIME-тип файла (пример: image/gif или image/jpeg и т.д.)\n$_FILES['значение атрибута name тега input']['type'];\n\n// Физический путь к временно переименнованному файлу\n$_FILES['значение атрибута name тега input']['tmp_name'];\n\n// Если в ячейке error значение 0, то ошибки нет,\n// иначе поле будет содержать номер ошибки\n$_FILES['значение атрибута name тега input']['error'];\n\n// Размер файла (как правило в байтах)\n$_FILES['значение атрибута name тега input']['size'];\n?\u003e\n```\n\nЕсли файл пришел без ошибок, то мы его \"забираем\" себе перемещая в нужное место.\n\n```php\n\u003c?php\nif($_FILES['UserFile']['error'] == 0) {\n  // Путь к временному переименнованному файлу\n  $temporary_name = $_FILES['UserFile']['tmp_name'];\n  \n  // Реальное имя файла\n  $real_name = $_FILES['UserFile']['name'];\n  \n  // Перемещение загруженного файла из временной директории\n  move_uploaded_file($temporary_name, './folder/' . $real_name);\n}\n?\u003e\n```\n\n## Работа с почтой\n\n**Настройка конфигурации**\n\nДирективы настроек по работе с почтой находятся в секции `[mail functions]` файла `php.ini`. Настройки эти только для ОС Windows.\n\n* `SMTP = localhost` – адрес SMTP-сервера;\n* `sendmail_from = me@localhost.kz` – e-mail по умолчанию от кого будет приходить почта.\n\nФункция `mail()` позволяет отправлять электронную почту. PHP сам письма не отправляет, а только передает почтовому серверу. Поэтому функция `mail()` говорит только о том, что PHP передал письмо почтовому серверу.\n\n**Пример отправки**\n\n```php\n\u003c?php\nif(mail('me@example.com', 'Тема письма', 'Тело письма')) {\n  echo 'Письмо успешно передано почтовому серверу';\n  /* При этом заголовок From у получателя будет тот,\n  что указан по умолчанию в директиве php.ini\n  sendmail_from = me@example.local */\n}\n?\u003e\n```\n\n**Пример расширенной отправки**\n\n```php\n\u003c?php\nmail(\n  'me@example.com',\n  'Тема письма',\n  $message,\n  \"From: me@$SERVER_NAME\\r\\n\".\n  \"Reply-To: me@$SERVER_NAME\\r\\n\".\n  \"X-Mailer: PHP/\" . phpversion()\n);\n\n// Или можно установить заголовки в одну переменную\n$headers = \"MIME-Version: 1.0\\r\\n\";\n$headers .= \"Content-Type: text/html; charset=utf-8\\r\\n\";\n$headers .= \"From: John Doe \u003cme@example.com\u003e\\r\\n\";\n?\u003e\n```\n\n## Базы данных и SQL\n\n_База данных (сокр. БД)_ – набор данных, хранящийся в электронном виде, которая управляется программой (СУБД) по взаимодействию с этой базой данных. База данных по отношению к управляющей ею программе является её элементом, единичной сущностью этой программы.\n\n_СУБД_ – система управления базой данных, программное обеспечение, необходимое для создания, изменения и обслуживания файлов БД.\n\n_Проектирование БД_ – создание эффективной структуры данных, обеспечивающее хранение требуемой информации.\n\nСуществуют следующие разновидности баз данных:\n\n* иерархические – подобно файловой системе компьютера основана на древовидной структуре хранения информации;\n* реляционные – табличное представление данных;\n* объектно-ориентированные – данные хранятся в виде объектов;\n* гибридные – совмещают возможности реляционных и объектно-ориентированных баз данных.\n\nВ реляционных базах данных:\n\n- Данные хранятся в таблицах, состоящих из столбцов и строк;\n- На пересечении каждого столбца и строки находится в точности одно значение;\n- У каждого столбца есть свое имя, которое служит его названием, и все значения в одном столбце имеют один тип;\n- Запросы к БД возвращают результат в виде таблиц, которые тоже могут выступать как объект запросов.\n\n### Введение в SQL\n\n_SQL (Structured Query Language — Язык структурированных запросов)_ – универсальный язык, применяемый для создания, модификации и управления данными в реляционных базах данных.\n\nЯзык SQL делится на три части:\n\n- _DDL (Data Definition Language - язык определения данных)_ – состоит из команд, которые создают объекты, изменяют или удаляют их. Под объектами понимается таблицы, индексы, просмотры и т. д. в базе данных:\n  - CREATE (создать);\n  - ALTER (изменить);\n  - DROP (уничтожить).\n\n\n- _DML (Data Manipulation Language - Язык манипуляции данными)_ – набор команд, которые определяют, какие значения представлены в таблицах в любой момент времени. Для работы с информацией, находящихся внутри объектов базы данных:\n  - INSERT (вставить);\n  - UPDATE (обновить);\n  - DELETE (удалить).\n\n\n- _DCL (Data Control Language - Операторы управления данными)_ – состоит из средств, которые определяют, разрешить ли пользователю выполнять определенные действия или нет. Одним словом, для управления доступом к данной базе:\n  - GRANT (предоставить доступ);\n  - DENY (запретить доступ);\n  - REVOKE (временно отменить доступ).\n\n \n- _DQL (Data Query Lanquage – Язык запросов)_:\n  - SELECT (выбрать).\n\n### Примеры SQL-запросов\n\n**Запросы SELECT**\n\n_выборка с сортировкой_\n\n```sql\nSELECT name, addr, city -- Перечисление полей\nFROM teachers -- Из какой таблицы\nORDER BY name -- Сортировать по полю name\n```\n\n_с определенным условием_\n\n```sql\nSELECT title\nFROM courser\nWHERE length \u003e 30\n```\n\n_совпадение в строковых значениях_\n\n```sql\nSELECT *\nFROM courses\nWHERE length \u003e 30 -- длина больше 30\nAND title LIKE 'Web%' -- значение поля title должно начинаться с Web\n```\n\n_объединение 2-ух таблиц_\n\n```sql\nSELECT t.lname, t.fname, l.course -- Выборка полей из конкретных таблиц\nFROM teachers t, lessons l -- Назначение таблице teachers алиас t\nINNER JOIN lessons l ON t.id = l.teacher_id -- Внутреннее объединение\n```\n\n_левое внешнее соединение_\n\nЕсли записям в левой таблице не найдутся соответствия, то они выводятся в конце со значением NULL.\n\n```sql\nSELECT t.lname, t.fname, l.course\nFROM teachers t, lessons l\nLEFT OUTER JOIN lessons l ON t.id = l.teacher_id\n```\n\n_объединение 3-ёх таблиц_\n\n```sql\nSELECT DISTINCT teachers.name\nFROM teachers INNER JOIN \n(lessons INNER JOIN courses ON lessons.course = courses.id)\nON teachers.id = lessons.teachers\nWHERE courses.title LIKE 'Web%'\nORDER BY teachers.name\n```\n\n**Запросы INSERT**\n\nВ таблицу `courses` добавить значения в каждое поле.\n\n```sql\nINSERT INTO courses\n  VALUES (Null, 'Java2', '...', 40) -- Добавляемые значения\n```\n\nДобавление только в конкретные поля.\n\n```sql\nINSERT INTO courses (title, length)\n  VALUES ('Java', 40) -- Добавляемые значения\n```\n\n**Запрос DELETE**\n\n```sql\nDELETE FROM lessons -- Из какой таблицы\nWHERE lessons.date = '2013-05-17' -- Условие удаления\n```\n\n    Важно! Если не передать условие, то удалятся все записи.\n\n**Запросы UPDATE**\n\n```sql\nUPDATE teachers -- В какой таблице\nSET -- Установить обновление\nzarplata = zarplata * 2,\npremia = premia * 10\nWHERE name LIKE 'Иванов%'\n  OR name LIKE 'Петров%'\n  OR name LIKE 'Сидоров%'\n```\n\n```sql\nUPDATE teachers\nSET\nzarplata = zarplata * 2,\npremia = premia * 10\nWHERE name IN ('Иванов', 'Петров', 'Сидоров')\n```\n\n## MySQL\n\n_MySQL_ – свободная реляционная СУБД распространяемая под лицензией [GNU GPL](https://ru.wikipedia.org/wiki/GNU_General_Public_License) и под собственной коммерческой лицензией. Изначально разрабатывалась в шведской компании MySQL AB. 26 февраля 2008 года компания Sun Microsystems приобрела MySQL AB, а позднее 27 января 2010 года компания Oracle приобрела Sun Microsystems включив MySQL в свою линейку СУБД.\n\n### Работа с MySQL в консоли\n\nДля работы с базами в консоли у MySQL есть утилита командной строки _mysql.exe_.\n\n```bat\n:: Открытие MySQL monitor (соединение с сервером баз данных MySQL)\nmysql -ulogin -ppassword\n:: Использование базы данных\nUSE имя_базы_данных\n:: Установка кодировки\nSET NAMES 'utf8mb4'\n:: Показать существующие таблицы в БД\nSHOW TABLES\n:: Показать поля, типы, ключи, ... таблицы\nDESCRIBE имя_таблицы\n:: Выход\nquit (или exit)\n```\n\nКонец запроса разделяется `;` (или `\\g`). Если результат выборки не помещается в окно, то можно в конце добавить `\\G`.\n\n**Использование утилиты mysqldump (создание дампа БД)**\n\n```bat\n:: Создать дамп БД\nmysqldump -uroot -ppass имя_БД \u003e dump.sql\n\n:: Создать БД с именем database_name\n:: на основе запросов из дампа dump.sql\nmysql -uroot -ppass database_name \u003c dump.sql\n```\n\n### Создание базы данных и таблиц\n\nОбщий алгоритм работы с сервером баз данных:\n1. Устанавливаем соединение с сервером баз данных;\n2. Выбираем базу данных для работы;\n3. Посылаем запрос:\n   √ При необходимости (SELECT), работаем с выбранными данными;\n4. Закрываем соединение.\n\nДля работы с MySQL необходимо подключить расширения:\n- _php_pdo.dll_\n- _php_pdo_mysql.dll_\n- _php_mysql.dll_\n\n**Соединение с сервером баз данных**\n\n```php\n\u003c?php\n// Открывает соединение с сервером MySQL\nmysql_connect('адрес сервера', 'login', 'password');\n\n// Выбирает базу данных MySQL\nmysql_select_db('db_name', 'идентификатор соединения с MySQL');\n\n// Закрывает соединение с MYSQL\nmysql_close([необязательный дескриптор соединения с MySQL]);\n?\u003e\n```\n\n**Соединение с самой базой данных**\n\n```php\n\u003c?php\nmysql_select_db('имя_БД', [дескриптор ресурса]);\n\n// Функции для работы с ошибками MySQL\nmysql_errno([указатель ресурса]); // Номер ошибки MySQL\nmysql_error([указатель ресурса]); // Описание ошибки\n\n// Пример соединения с БД\nmysql_select_db('db') or die(mysql_error());\n?\u003e\n```\n\n**Отправка запроса**\n\n```php\n\u003c?php\nmysql_query(\"SET names 'utf8mb4'\");\n\n// Рекомендуентся запрос сначала присвоить переменной\n$myQuery = 'SELECT * FROM teachers';\n// а затем уже её подставлять\n$result = mysql_query($myQuery);\n\nmysql_close();\n?\u003e\n```\n\n**Некоторые функции обработки выборки**\n\n```php\n\u003c?php\n$query_result = mysql_query(\"SELECT title FROM lessons\");\n\n// Индекс-ый и ассоц-ый массив одного ряда таблицы\nmysql_fetch_array($query_result, MYSQL_BOTH);\n// Индексированный массив одного ряда таблицы\nmysql_fetch_row($query_result);\n// Ассоциативный массив одного ряда таблицы\nmysql_fetch_assoc($query_result);\n// Пример вывода имен сотрудников\nwhile($employer = mysql_fetch_assoc($query_result)){\n  echo $employer['name'], '\u003cbr\u003e';\n}\n\n// Точечная выборка из конкретной ячейки\n// -\u003e 1-ая ячейка поля address\nmysql_result($query_result, 0, 'address');\n// Идентификатор сгенерированный при последнем INSERT-запросе\nmysql_insert_id($connect);\n?\u003e\n```\n\n### Модуль MySQLi\n\n_Расширение MySQLi (MySQL Improved)_ – позволяет получить доступ к функциональности, которую предоставляет MySQL-сервер.\n\nК ядру PHP подключаются ряд необязательных модулей, расширяющие круг задач, который может выполнить код на PHP. Относящиеся к MySQL модули, такие как `mysqli` и драйвер PDO MySQL, взаимодействуют с ядром с помощью таких PHP модулей.\n\n**Настройка модуля `mysqli`**\n\nВ конфигурационном файле `php.ini` убедитесь что модули `php_mysqli.dll` и `php_pdo.dll` подключены.\n\n`mysqli` предоставляет следующие преимущества:\n- Помимо процедурного интерфейса предоставляет и объектно-ориентированный интерфейс;\n- Имеет поддержку дополнительных функций мониторинга, отлова ошибок, управления загрузкой и репликации;\n- Подготавливаемые запросы и поддержка транзакций и мультизапросов.\n\n**Особенность подключения с MySQLi**\n\n```php\n\u003c?php\n$connect = mysqli_connect(\n  'localhost',\n  'user_login',\n  'password',\n  'db_name' // 4-ым параметром передается имя базы данных\n); // (нет функции mysql_select_db())\n?\u003e\n```\n\nПодробнее в [документации MySQL](https://dev.mysql.com/doc/) на официальной странице сервера и в [документации модуля MySQLi](https://www.php.net/manual/ru/book.mysqli.php) на странице php.net.\n\n## SQLite\n\n* _SQLite_ – библиотека, написанная на языке C, реализующая встраиваемый движок SQL базы данных;\n* Программы, использующие библиотеку _SQLite_, могут использовать SQL базы данных без использования внешнего процесса реляционной системы управления базами данных (RDBMS);\n* _SQLite_ не является клиентской библиотекой, подключающейся к большому серверу базы данных, _SQLite_ сама является сервером и напрямую оперирует файлами базы данных на диске;\n* Реализованы как серверные, так и клиентские функции.\n\n**Преимущества использования SQLite**\n\n- Полностью бесплатна;\n- Нет необходимости в средствах администрирования;\n- Высокая производительность и легкая переносимость;\n- Поддержка процедурного и объектно-ориентированного интерфейсов;\n- Хранение данных объемом до 2 терабайт;\n- Хранение строк и бинарных данных неограниченной длины.\n\n**Ограничения использования SQLite**\n\n* _SQLite_ предназначен для небольших и средних приложений;\n* Основной выигрыш в производительности, если преобладают операции вставки и выборки данных;\n* При чрезвычайно активном обращении к данным, или в случае частых сортировок, _SQLite_ работает медленнее своих конкурентов.\n\n### Поддержка SQLite в PHP\n\nВ PHP 5.0 поддержка SQLite была доступна по умолчанию на уровне ядра. Начиная с PHP 5.1 поддержка _SQLite_ вынесена за пределы ядра. Начиная с версии PHP 5.4, расширение _SQLite_ доступно только через PECL.\nРасширение _SQLite3_ доступно по умолчанию начиная с версии PHP 5.3.0.\n\nПользователи Windows должны включить поддержку `php_sqlite3.dll` для того, чтобы использовать это расширение. Эта DLL входит в состав Windows-дистрибутивов РНР начиная с версии PHP 5.3.0.\n\n```ini\nextension=php_pdo.dll\nextension=php_sqlite.dll\n```\n\n### Создание базы, таблиц и выборка данных\n\nВ примере если файла с именем `test.db` нет — он создастся, есть — установится соединение.\n\n```php\n\u003c?php\n// Процедурный подход\n$connect = sqlite_open('test.db');\nsqlite_close($connect); // Закрытие соединения\n\n// Объектно-ориентированный подход\n$connect = new SQLiteDatabase('test.db');\nunset($connect); // Закрытие соединения\n\n// SQLite3\n$connect = new SQLite3('test.db');\nunset($connect);\n?\u003e\n```\n\n**Особенности в SQLite3**\n\nПервичный ключ автоматически становится _autoincrement_.\n\n```php\n\u003c?php\n// PRIMARY KEY и AUTOINCREMENT\nCREATE TABLE users (id INTEGER PRIMARY KEY, name, age)\n\n// Экранировать запросы нужно через функцию\n$clear = sqlite_escape_string($sql_query);\n?\u003e\n```\n\n**Получение результата выборки в виде массива**\n\n```php\n\u003c?php\nfunction fetchAll(){\n  $sql = 'SELECT id, name, email, msg, datetime, ip\n          FROM msgs ORDER BY 1 DESC';\n\n  $result = $this-\u003e_db-\u003equery($sql);\n  $i = 0;\n\n  while($record[$i] = $result-\u003efetchArray(SQLITE3_ASSOC)) {\n    while(list($name, $value) = each($record))\n      $records[$name] = $value;\n    $i++;\n  }\n\n  return $records; // -\u003e Двумерный массив со всеми записями\n}\n?\u003e\n```\n\n**Исключения в SQLite3**\n\n```php\n\u003c?php\ntry {\n  $res = $this-\u003e_db-\u003equery($sql); // -\u003e Результат запроса\n  if(!$res) throw new Exception($this-\u003e_db-\u003elastErrorMsg());\n  return true; // -\u003e true, если запрос успешен\n} catch(Exception $error) {\n  // Запись в лог ошибок\n  file_put_contents('errors.log', $error, FILE_APPEND);\n  // Отправить письмо с ошибкой\n  mail('me@mail.com', 'Тема письма', $error);\n  return false; // -\u003e false, если запрос завершился неудачей\n}\n?\u003e\n```\n","funding_links":[],"categories":[],"sub_categories":[],"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"}