Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/sa2kasov/php-reference-guide

Reference Guide of PHP with MySQL, OOP, and other
https://github.com/sa2kasov/php-reference-guide

mysql php php-oop php-reference sqlite3

Last synced: 2 days ago
JSON representation

Reference Guide of PHP with MySQL, OOP, and other

Awesome Lists containing this project

README

        


PHP Logo

# Справочное руководство по PHP

### Содержание

1. [Предыстория](#Предыстория)
2. [Интерпретатор PHP](#Интерпретатор-PHP)
1. [Связка с веб-сервером Apache](#Связка-с-веб-сервером-Apache)
3. [Синтаксис языка](#Синтаксис-языка)
1. [PHP–теги](#PHP–теги)
2. [Комментарии](#Комментарии)
4. [Hello, World!](#Hello,-World!)
5. [Переменные](#Переменные)
1. [Экранирование переменных](#Экранирование-переменных)
2. [Присвоение по ссылке](#Присвоение-по-ссылке)
6. [Ошибки](#Ошибки)
7. [Типы данных](#Типы-данных)
1. [Boolean](#boolean)
2. [Integer и Float](#Integer-и-Float)
3. [String](#String)
1. [Синтаксис heredoc и nowdoc](#Синтаксис-heredoc-и-nowdoc)
2. [Доступ к символу в строке](#Доступ-к-символу-в-строке)
4. [NULL](#NULL)
8. [Операторы](#Операторы)
1. [Арифметические](#Арифметические)
2. [Строковые](#Строковые)
3. [Операторы сравнения](#Операторы-сравнения)
4. [Логические операторы](#Логические-операторы)
9. [Полезные функции](#Полезные-функции)
10. [Управляющие конструкции](#Управляющие-конструкции)
1. [if](#if)
2. [if..else..](#ifelse)
3. [if..elseif..else..](#ifelseifelse)
4. [Альтернативный синтаксис](#Альтернативный-синтаксис)
5. [Тернарный оператор](#Тернарный-оператор)
6. [switch](#switch)
7. [try..catch](#trycatch)
11. [Массивы](#Массивы)
1. [Нумерованный массив](#Нумерованный-массив)
2. [Ассоциативный массив](#Ассоциативный-массив)
3. [Многомерный массив](#Многомерный-массив)
4. [Работа с массивами](#Работа-с-массивами)
1. [Печать массива](#Печать-массива)
2. [Подсчёт элементов массива](#Подсчёт-элементов-массива)
3. [Встраивание массива в строки](#Встраивание-массива-в-строки)
4. [Перемещение указателя массива](#Перемещение-указателя-массива)
12. [Константы](#Константы)
1. [Магические константы](#Магические-константы)
13. [Циклы](#Циклы)
1. [for](#for)
2. [while](#while)
3. [do..while](#dowhile)
4. [foreach](#foreach)
14. [Функции](#Функции)
1. [Объявление и вызов](#Объявление-и-вызов)
2. [Аргументы функции](#Аргументы-функции)
3. [Аргументы по умолчанию](#Аргументы-по-умолчанию)
4. [Области видимости переменных](#Области-видимости-переменных)
5. [Статические переменные](#Статические-переменные)
6. [Рекурсия](#Рекурсия)
7. [Функции управления функциями](#Функции-управления-функциями)
15. [Классы и объекты](#Классы-и-объекты)
1. [Описание класса](#Описание-класса)
2. [Области видимости](#Области-видимости)
3. [Конструкторы и деструкторы](#Конструкторы-и-деструкторы)
4. [Клонирование объектов](#Клонирование-объектов)
5. [Наследование](#Наследование)
6. [Перегрузка методов](#Перегрузка-методов)
7. [Перебор свойств объекта](#Перебор-свойств-объекта)
8. [Константы класса](#Константы-класса)
9. [Абстрактные классы и методы](#Абстрактные-классы-и-методы)
10. [Интерфейсы](#Интерфейсы)
11. [Финальные классы и методы](#Финальные-классы-и-методы)
12. [Статические свойства и методы](#Статические-свойства-и-методы)
13. [Ключевое слово instanceof](#Ключевое-слово-instanceof)
14. [Автоматическая загрузка классов](#Автоматическая-загрузка-классов)
15. [Магические методы](#Магические-методы)
16. [Разыменование объектов](#Разыменование-объектов)
17. [Уточнение типа класса](#Уточнение-типа-класса)
16. [Cookies](#Cookies)
1. [Создание Cookie](#Создание-Cookie)
2. [Чтение Cookie](#Чтение-Cookie)
3. [Удаление Cookie](#Удаление-Cookie)
17. [Сессии](#Сессии)
18. [HTTP-заголовки](#HTTP-заголовки)
19. [Файлы](#Файлы)
1. [Получение сведений о файлах](#Получение-сведений-о-файлах)
2. [Открытие и закрытие](#Открытие-и-закрытие)
3. [Режимы работы с файлами](#Режимы-работы-с-файлами)
4. [Чтение файла](#Чтение-файла)
5. [Запись в файл](#Запись-в-файл)
6. [Манипуляции с курсором](#Манипуляции-с-курсором)
7. [Прямая работа с данными](#Прямая-работа-с-данными)
8. [Управление файлами](#Управление-файлами)
9. [Директории (каталоги)](#Директории-каталоги)
10. [Загрузка файлов на сервер](#Загрузка-файлов-на-сервер)
11. [Разбор файлов на сервере](#Разбор-файлов-на-сервере)
20. [Работа с почтой](#Работа-с-почтой)
21. [Базы данных и SQL](#Базы-данных-и-SQL)
1. [Введение в SQL](#Введение-в-SQL)
2. [Примеры SQL-запросов](#Примеры-SQL-запросов)
22. [MySQL](#MySQL)
1. [Работа с MySQL в консоли](#Работа-с-MySQL-в-консоли)
2. [Создание базы данных и таблиц](#Создание-базы-данных-и-таблиц)
3. [Модуль MySQLi](#Модуль-MySQLi)
23. [SQLite](#SQLite)
1. [Поддержка SQLite в PHP](#Поддержка-SQLite-в-PHP)
2. [Создание базы, таблиц и выборка данных](#Создание-базы-таблиц-и-выборка-данных)

## Предыстория

**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 году.

Язык подвергся значительной переработке когда в 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. Сегодня язык разрабатывается группой энтузиастов и распространяется под собственной лицензией в рамках проекта с открытым исходным кодом.

## Интерпретатор PHP

Местоположение интерпретатора можно узнать по информации выдаваемой функцией `phpinfo()`. В системе Windows путь к директории, где установлен PHP можно узнать в `Переменные среды` системы, путь к интерпретатору будет в списке переменной среды `Path`.

Стандартный при поставке PHP содержит больше >9000 функций. При разработке нет необходимости в таком количестве функций, поэтому часть стандартных функций вшиты в ядро, а часть функций (расширений) находятся в папке `ext`. В зависимости от необходимости мы можем подключать то или иное расширение.

`php.ini` – главный конфигурационный файл настроек PHP. При установке нужно при необходимости переименовать файл `php.ini-production` или `php.ini-development` в `php.ini`.

Настройки PHP делятся на три группы где их можно изменять:
1. Это непосредственно файл `php.ini`. На shared-хостинге, как правило, не дают прямой доступ к файлу `php.ini`, лишь выносят часть их настроек в панель управления хостингом;
2. `.htaccess` – настройки распространяются ко всем подпапкам, кроме тех, у которых есть свой файл `.htaccess`;
3. Прямо в коде. Например:

```php

```

### Связка с веб-сервером Apache

Чтобы подключить PHP к веб-серверу Apache, нужно указать Apache, где находится файл `php.ini` одним из следующим способом:

1. Прописать путь к файлу php.ini в значение:
* С помощью директивы `PHPIniDir` указать путь к файлу `php.ini` в главном конфигурационном файле Apache `httpd.conf` (в версиях Apache 2 и выше);
* Системной переменной `PHPRC`;
* Ключа реестра `IniFilePath` в ветвях:
* HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x.y.z\ (5.4.8)
* HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x.y\ (5.4.8)
* HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x\ (5.4.8)
* HKEY_LOCAL_MACHINE\SOFTWARE\PHP\

2. Скопировать файл `php.ini` в директорию:
* PHP;
* Сервера;
* ОС Windows (например, C:\Windows).

Узнать какой именно файл `php.ini` зачитывается можно с помощью той же функцией `phpinfo()` в строке `Loaded Configuration File`.

## Синтаксис языка

### PHP–теги

Все, что находится между открывающими и закрывающими php-тегами – есть код на PHP. Каждая инструкция заканчивается точкой с запятой.

**Рекомендуется к использованию:**

```php

```

**Короткая запись**

Для этого тега параметр `short_open_tag` в `php.ini` должен быть установлен как `on`. Такая конструкция может быть нежелательной из-за того, что декларация XML также начинается с `` и заканчивается `?>`:

```php
код PHP ?>
```

**Вместо вопросов проценты**

В свое время, чтобы переманить на свою сторону программистов на ASP.NET были введены такие открывающиеся/закрывающие теги PHP. Для этого параметр `asp_tags` должен быть включен:

```php
<% код PHP %>
```

### Комментарии

В классическом программировании принято чтобы комментарии составляли 30% от кода. Однострочные комментарии начинаются с двумя слэшами `//`. Блочные комментарии заключаются между `/*` и `*/`.

```php

```

## Hello, World!

За вывод строковых данных на экран в PHP используется функция `echo`, которая выводит одну и более строк. Языковая конструкция `print` также печатает данные на экран. В отличие от `echo` она умеет принимать только один параметр и всегда возвращает 1.

```php
', 'Hello, ', 'world!', '';

// Короткая запись (сокращенное echo)
// Для этого должен быть включён флаг short_open_tag
='Hello, world!'?>
?>
```

## Переменные

Переменная — именованная ячейка памяти.

* Все имена переменных должны начинаться со знака доллара `$`;
* Первым символом после `$` должна быть буква или символ подчеркивания. Далее, в имени переменной могут присутствовать буквы, цифры и символ подчеркивания;
* Имена переменных чувствительны к регистру.

Есть несколько подходов к написанию переменных. В C (Си) подобных языках переменные пишут с маленькой буквы, в Basic с заглавной. Нужно определить свой стиль написания переменной. Если переменная состоит из двух слов, то можно записать так: `user_name` или методом "верблюжьей нотацией" `userName` (`UserName`). Последняя чаще может встречаться в крупных проектах в таких, как WordPress.

**Присвоение значения переменной и её удаление**

```php

```

После завершения конструкции PHP значения переменных стираются из памяти, но бывают ситуации, когда переменные нужно удалить до того, как закончится код.

```php

```

### Экранирование переменных

Имена переменных можно помещать в строки (тип данных String рассматривается в разделе [Типы данных](#String)). В строках заключенные одинарными кавычками переменные отображаются как простой текст. Однако в двойных кавычках переменная подставит своё значение.

```php
";

// Переменной $beers не существует
echo "He drank some $beers
";
?>
```

Если имя переменной сливается в строке с другими символами, и интерпретатор может допустить лишние символы как часть имени переменной, то такую переменную следует экранировать заключив её имя в конструкции `${name}` или `{$name}`.

```php
// Экранирование переменных одним из двух способов
echo "He drank some ${beer}s
"; // первый способ
echo "He drank some {$beer}s
"; // второй способ
```

### Присвоение по ссылке

В переменную может быть присвоено значение по ссылке. Это значит, что создаваемая переменная не будет иметь своё собственное значение, а будет ссылаться на оригинальную переменную. Другими словами, являться собой ярлыком, псевдонимом другой переменной.

```php
10
?>
```

Широкое применение это находит, например, в [циклах](#foreach), когда мы хотим изменить значения массива на месте прямо в теле цикла.

```php
$inputs = [ ... ]; // Условная переменная-массив

foreach($inputs as &$input) {
$input['checked'] = true; // Изменяется исходный массив
}
```

## Ошибки

* Если мы не видим ошибки на строке который указывает нам браузер, то ошибку следует искать строчкой выше;
* Когда у нас выпадает много ошибок, нужно искать и исправлять ошибки сверху вниз, а не снизу вверх.

У PHP есть четыре уровня ошибок (предупреждений):
1. **PARSE** – ошибка при парсинге. PHP не сразу выполняет полученный код, а сперва проверяет на предмет синтаксических ошибок;
Если синтаксических ошибок не обнаружено, то код начинает выполняться...
2. **FATAL ERROR** – в этом случае нам выведется ошибка и выполнение кода прекратится;
3. **WARNING** – предупреждение. Выведет ошибку, но выполнение кода продолжится;
4. **NOTICE** – уведомление.

Мы можем запретить выводить показ об ошибке в браузере выполнив `error_reporting(0);`. По умолчанию все константы уровней ошибок (кроме NOTICE) будут выводиться в браузере. На практике сначала проверяют код на предмет серьезных ошибок, и только потом если таких ошибок не обнаружено, включают `error_reporting(E_ALL)`.

## Типы данных

PHP поддерживает 10 простых типов:

* Четыре скалярных типа:
* boolean (логический)
* integer (целые числа)
* float (вещественные (плавающие) числа)
* string (строковый тип)

* Два смешанных типа:
* array (массив)
* object (объект)
* callable
* iterable

* Два специальных типа:
* resource
* NULL

В этом разделе рассмотрим только скалярные типы и специальный тип `NULL`.

### Boolean

Простейший тип, выражающий истинность значения. Это может быть либо `true` или `false`.
При преобразовании в логический тип, следующие значения рассматриваются как `false`:
* само значение `false`;
* Целое 0 (ноль);
* Вещественное число (с плавающей точкой) 0.0 (ноль);
* Пустая строка и строка `"0"`;
* Пустой массив;
* Специальный тип `NULL` (включая неустановленные переменные).

Все остальные значения рассматриваются как `true`.

### Integer и Float

```php

```

### String

Строки заключаются в двойные и одинарные кавычки, а также доступен синтаксис `heredoc` рассматриваемый дальше.

```php

```

В строках с двойными кавычками допустимо использовать специальные символы, некоторые из них:

- \n - перевод на новую строку;
- \r - возврат каретки;
- \t - горизонтальная табуляция;
- \\ - обратный слеш;
- \$ - знак доллара;
- \" - двойная кавычка;

```php
Переменная $str - Текстовая строка
?>
```

Разница между двойными и одинарными кавычками в том, что в двойных переменные и спец. символы обрабатываются, а в одинарных нет.

### Синтаксис heredoc и nowdoc

Конструкция **heredoc** и **nowdoc** начинаются с тремя знаками `<<<` после которого следует идентификатор, а затем перевод строки. После этого идёт сама строка, а потом этот же идентификатор, закрывающий вставку.

Закрывающий идентификатор может иметь отступ в виде пробела или табуляции. В этом случае отступ будет удалён из всех строк в строке документа.

```php
,
т.е. сохраняются пробелы, отступы, переходы на новую строку,
табуляции, также сюда можно подставлять переменные, использовать
специальные символы.
LABEL;
?>
```

**Определение строк с помощью синтаксиса nowdoc**

**nowdoc** — это то же самое для строк в одинарных кавычках, что и heredoc для строк в двойных кавычках. **nowdoc** похож на **heredoc**, но внутри него не осуществляется никаких подстановок. Эта конструкция идеальна для внедрения PHP-кода или других больших блоков текста без необходимости его экранирования.

**nowdoc** указывается той же последовательностью `<<<`, что используется в **heredoc**, но последующий за ней идентификатор заключается в одинарные кавычки, например, `<<<'EOT'`.

```php

```

Некоторые правила касающиеся типа string **heredoc** и **nowdoc**:

* Строка с открывающим идентификатором не содержит после него никаких других символов, включая пробел;
* Закрывающий идентификатор до версии PHP 7.3.0 должен начинаться с первой позиции строки;
* Строка с закрывающим идентификатором не содержит других символов (включая пробел), за исключением точки с запятой.

### Доступ к символу в строке

Мы можем получить доступ к любому символу в строке объявленной в переменной `$str` передав номер позиции символа в квадратных `[]` или фигурных `{}` скобках. Отсчёт позиции символов начинается с нуля.

```php

```

### NULL

Переменная считается NULL если:

* Ей была присвоена константа `NULL`;
* Ей ещё не было присвоено какое-либо значение;
* Она была удалена с помощью `unset()`.

## Операторы

Операторы принимают одно или несколько значений и вычисляют на их основе новое значение. Под вычислением может происходить сравнение двух значений, их арифметическое вычисление, присваивание и т.д.

Операторы бывают _унарные_ – принимают только одно значение, например `!` (логическое отрицание), `++` (инкремент) и др. и _бинарные_ – принимают два значения (большинство операторов именно такие). Также существует один [_тернарный оператор_](#Тернарный-оператор), принимающий три значения.

### Арифметические

```php

```

### Строковые

```php

```

### Операторы сравнения

```php
true если $a равно $b
$a === $b // -> true если тип операндов совпадает и $a равно $b
$a != $b // -> true если $a не равно $b
$a !== $b // -> true если типы не совпадают и $a не равно $b
$a > $b // -> true если $a строго больше $b
$a < $b // -> true если $a строго меньше $b
$a >= $b // -> true если $a больше или равно $b
$a <= $b // -> true если $a меньше или равно $b
?>
```

### Логические операторы

```php
true если $a и $b true
$a or $b // -> true если $a или $b true
!$a // -> true если $a не true

// Сначала вычислится сравнение $a и $b,
// и только потом их результат сравнится с $c
$a and $b and $c

// Сначала вычислится сравнение $b и $c,
// и только потом их результат сравнится с $a
$a and ($b and $c) эквивалентно $a and $b && $c

// Сначала вычислится сравнение $b или $c,
// и только потом их результат сравнится с $a
$a and ($b or $c) эквивалентно $a and $b || $c
?>
```

Операторы `&&` (логическое умножение), `||` (логическое сложение) приоритетнее операторов `and` и `or`.

## Полезные функции

- `isset(имя_переменной)` – возвращает `true`, если существует переменная или `false`, если переменная не определена или ей присвоено `NULL` (что в принципе одно и то же);

- `empty(имя_переменной)` – возвращает `true`, если значение переменной пустая строка `""`, `NULL`, переменная не определена ($x), пустой массив ($x = array()), значение `false` ($x = false), значение `0` ($x = 0;) или ($x = "0"). Возвращает `false`, если значение переменной `true` ($x = true), значение `>` или `<` 0;

- `gettype(имя_переменной)` – возвращает тип переменной (boolean, string, integer, double(float), NULL). Например:

```php

```

- `settype(имя_переменной, "тип")` – конвертирует переменную в другой тип. Например:

```php

```

- Временное приведение к типу

Если мы хотим вывести только 100, но также хотим чтобы значение `"100darov"` в переменной `$variable` осталось — нужно написать в скобках нужный тип данных перед именем переменной без пробелов:

```php
100
?>
```

## Управляющие конструкции

Основные конструкции PHP это _условные операторы_ (if, else), _оператор выбора_ (switch) и _циклы_ (for, foreach, while, do..while). Внутри конструкции `switch` и некоторых циклов могут быть использованы ключевые слова (return, break, continue).

### if

Если условие в скобках истинно, но выполнится инструкция.

```php

```

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

```php
if (условие) {
инструкция 1;
инструкция 2;
}
?>
```

### if..else..

Если условие в `if` окажется истинным, то выполнятся только инструкции 1 и 2, иначе выполняются инструкции 3 и 4.

```php

```

### if..elseif..else..

Если `условие 1` истинно, то выполнится только `инструкция 1`, все остальные `elseif` и `else` интерпретатор проверять не станет. Аналогично и с `условием 2`, во всех остальных случаях выполнится `инструкция 3` в блоке `else`.

`Инструкция 4` выполнится в любом случае, сразу после разрешения конструкции выше.

```php

```

### Альтернативный синтаксис

Закрытие блока `?>`, это еще не есть закрытие кода. Очень легко запутаться в фигурных скобках, поэтому для удобства PHP предлагает альтернативный синтаксис для некоторых его управляющих структур, а именно: `if`, `while`, `for`, `foreach` и `switch`.

```php

код условия 1

код условия 2

код блока else

?>
```

### Тернарный оператор

Тернарный оператор это то же условие `if..else`, но с более коротким синтаксисом. Сначала проверяется условие в скобках, если оно истинно, то выполняется инструкция после знака `?`, иначе после знака `:`.

Скобки вокруг условия факультативны, но предпочтительней их ставить для лучшей читаемости кода.

```php
1) ? "a больше единицы" : "a меньше единицы";
$b = ($a > 1) ? "One" : "Zero"; // Значение присвоится переменной $b
?>
```

### switch

Оператор `switch` можно представить как ещё одну разновидность оператора `if..elseif..else`. В случаях, когда необходимо сравнивать одну и ту же переменную (или выражение) со множеством значений.

Конструкция `switch/case` использует нестрогое сравнение `==`.

Оператор `continue` прерывает все последующие итерации. Следующая за `continue` инструкция и далее уже не будут выполнены. Может также быть использована в циклических структурах и выполнять там ту же функцию.

`break` прерывает выполнение текущей структуры `switch` и выходит за операторные скобки. Может также применяться в таких циклических конструкциях как `for`, `foreach`, `while`, `do..while`.

`continue` и `break` принимают числовой параметр, сообщающей интерпретатору какое кол-во вложенных структур надо прервать. Поведение работы этих операторов в циклических структурах описано далее на примере работы цикла [**while**](#while).

В случае если ни один из вариантов не подошел, то будет исполнено то, что в блоке `default`.

```php

```

**Пример использования `switch`**

К примеру необходимо вычислить значение директивы `post_max_size` в байтах. Значение любой директивы в PHP можно получить/установить с помощью функций:

* `ini_get('имя_директивы')` — данная функция всегда возвращает значение в строковом типе;
* `ini_set('имя_директивы', "on | of | значение")` — включение/выключение/изменение директивы Runtime (прямо в коде).

Допустим мы имеем код со следующей реализацией:

```php
8M
$letter = $result{strlen($result) - 1}; // -> M
$size = (integer)$result; // -> 8

switch ($letter) {
case "G": $size = $size * 1024 * 1024 * 1024; break;
case "M": $size = $size * 1024 * 1024; break;
case "K": $size = $size * 1024; break;
default: $size;
}

echo "POST_MAX_SIZE = " . $size . " bytes";
?>
```

Вот как выглядит код после оптимизации. Пример демонстрирует случай, когда такое использование `switch` особенно оправдано.

```php
8M
$letter = $result{strlen($result) - 1}; // -> M
$size = (int)$result; // -> 8

// Альтернативный фигурным скобкам синтаксис
switch ($letter):
case "G": $size *= 1024; // -> 8 589 934 592
case "M": $size *= 1024; // -> 8 388 608
case "K": $size *= 1024; // -> 8 192
endswitch;
?>
```

### try..catch..

Конструкция `try..catch..` используется для обработки исключений и отслеживания ошибок. Ошибку в случае возникновения перехватывает `catch`, информацию об ошибке можно извлечь из класса `Exception`.

```php
name = $name;
$this->last_name = $last_name;
$this->age = $age;
$this->sex = $sex;
}
catch(Exception $error) {
// Сообщение об ошибке
echo $error->getMessage(); // -> "Введены не все данные!"
// Строка на которой произошла ошибка
echo $error->getLine();
// Файл, в котором произошла ошибка
echo $error->getFile();
}
}
}

$user = new User(); // $error object
?>
```

## Массивы

_Массив_ — упорядоченный набор данных, где каждый элемент массива имеет свой ключ и значение. Массив может быть создан языковой конструкцией `array()` или с помощью короткого синтаксиса `[]`. Ключи массива могут быть либо целочисленным типом [Integer](#Integer-и-Float), либо [String](#String). Значение же может быть любым типом.

### Нумерованный массив

_Нумерованные массивы_ — это массивы, у которых ключи являются числа.

```php
'1st', 1 => '2nd', 3 => '3rd'];

// Значение "4th" теперь будет имет порядковый номер 10
$arr[10] = '4th';
?>
```

### Ассоциативный массив

_Ассоциативный массив_ — это когда вместо индексов (номеров) назначают строковые осмысленные имена.

```php
"guest",
true
);
?>
```

У ниже приведённых двух элементов массива будет одинаковая структура, хоть они и были созданы разными способами.

```php
"Model S Plaid",
'speed' => 321,
'doors' => 4,
'year' => "2022"
);

$cars['mercedes-benz']['model'] = 'Mercedes-Benz EQC';
$cars['mercedes-benz']['speed'] = 180;
$cars['mercedes-benz']['doors'] = 4;
$cars['mercedes-benz']['year'] = "2022";
?>
```

### Многомерный массив

_Многомерный массив_ — массив, где элементы в свою очередь могут сами являться массивами и содержать в себе сколько угодно вложенных массивов. Пример многомерного массива:

```php
array(
"Глава I" => array(
"Глава 1.1",
"Глава 1.2",
"Глава 1.3",
),
"Глава II",
"Глава III",
),
"Часть II",
"Часть III" => array(
"Глава I" => array(
"Глава 1.1",
"Глава 1.2",
"Глава 1.3",
),
"Глава II",
"Глава III" => array(
"Глава 1.1",
"Глава 1.2",
"Глава 1.3",
),
"Глава IV",
),
"Часть IV",
"Заключение",
);
?>
```

### Работа с массивами

Объявлять массив предпочтительней с помощью языковой конструкцией `array()`, но добавлять новые ячейки в уже имеющийся массив удобней с помощью квадратных скобок `$myArray[] = 'добавление'`.

#### Печать массива

Можно просмотреть индексы массива и соответствующие им значения с помощью функции `print_r()`. Для сохранения форматирования вывод был обрамлён тегами `

`.

```php
echo '

', print_r($user), '
';
```

Функция `var_dump()` также печатает массив, в отличие от предыдущей данные массива печатаются с дополнительной информацией — с указанием длины массива, индекса, тип значения и само значение, а также длину строки, если значение строковое. `var_dump()` также можно применить и к обычной переменной и в случаях, когда необходимо более подробно посмотреть массив.

```php
echo "

", var_dump($cars), "
";

// Результат выполнения
array(1) {
["tesla"]=>
array(4) {
["model"]=>
string(13) "Model S Plaid"
["speed"]=>
int(321)
["doors"]=>
int(4)
["year"]=>
string(4) "2022"
}
```

#### Подсчёт элементов массива

Подсчет количества элементов массива или количества свойств объекта
выполняет функция `count($myArray)`.

Если в качестве второго параметра передать `true`, т.е сделать так `count(myArray, 1)`, то функция подсчитает все вложенные элементы, если это многомерный массив.

#### Встраивание массива в строки

Вывести ячейки массива внутри двойных кавычек можно двумя способами:

* Экранировать переменные:

```php

```

* Обращаться к ячейкам массива без кавычек:

```php

```

#### Перемещение указателя массива

Можно передвигать указатель массива (вверх-вниз) с помощью специальных функций:

```php
Борщ

// Переход на следующую позицию
next($menu['Блюдо']); // -> Щи

// Переход на предыдущую позицию
prev($menu['Блюдо']); // -> Борщ

// Переход к последнему элементу
end($menu['Блюдо']); // -> Под шубой

// Возвращает ключ из ассоциативного массива
key($menu['Блюдо']); // -> Салат3
?>
```

## Константы

_Константы_ — те же самые переменные, но только значения в них неизменны.

* У констант нет приставки в виде знака доллара;
* Константы можно определить только с помощью функции `define()`, а не присваиванием значения;
* Константы доступны в любом месте, без учета области видимости;
* Константы не могут быть переопределены или аннулированы после первоначального объявления;
* Константы не встраивают в строки с двойными кавычками, их нужно конкатенировать.

Константы задаются следующей функцией:

```php

```

Константу можно проверить следующей функцией:

```php
true, если такая константа уже есть

// нечувствительная к регистру константа
define("имя_константы", значение, true);
?>
```

Передав `true` третьим параметром мы разрешаем константе быть регистро-независимой (не рекомендуется).

Имена констант принято писать большими буквами (но допускается и строчными). Единожды созданная константа существует до конца кода. Константе нельзя заново присвоить какое-нибудь значение, её нельзя удалить (с помощью функции `unset()`).

Константы обычно заводятся по двум причинам:

1. Удобней помнить имя константы. Например, константы `E_ALL`, `E_ERROR` и др. за такими константами на самом деле стоит определенное значение (число). И гораздо удобней запомнить имя константы, чем то число, которое стоит за ней;
2. В процессе работы мы заводим переменную значение которой впоследствии можно ненамеренно переназначить. С использованием констант эта проблема отпадает, т.к. её значение всегда остаётся неизменным.

### Магические константы

В PHP есть 9 псевдоконстант, которые меняют своё значение в зависимости от контекста, где они используются.

| Имя | Описание |
|:---------------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **\_\_LINE\_\_** | Текущий номер строки в файле. |
| **\_\_FILE\_\_** | Полный путь и имя текущего файла с развёрнутыми симлинками. Если используется внутри подключаемого файла, то возвращается имя данного файла. |
| **\_\_DIR\_\_** | Директория файла. Если используется внутри подключаемого файла, то возвращается директория этого файла. Это эквивалентно вызову dirname(**\_\_FILE\_\_**). Возвращаемое имя директории не оканчивается на слеш, за исключением корневой директории. |
| **\_\_FUNCTION\_\_** | Имя функции или `{closure}` в случае анонимной функции. |
| **\_\_CLASS\_\_** | Имя класса. Это имя содержит название пространства имён, в котором класс был объявлен (например, `Foo\Bar`). При использовании в методах трейтов \_\_CLASS\_\_ является именем класса, в котором эти методы используется. |
| **\_\_TRAIT\_\_** | Имя трейта. Это имя содержит название пространства имён, в котором трейт был объявлен (например, Foo\Bar). |
| **\_\_METHOD\_\_** | Имя метода класса. |
| **\_\_NAMESPACE\_\_** | Имя текущего пространства имён. |
| **ClassName::class** | Полное имя класса. |

**Пример использования в классах**

```php
getMethod; // myClass::getMethod
$myObject->getClass; // myClass
?>
```

## Циклы

PHP поддерживает несколько различных циклических структур управления.

### for

Синтаксис цикла `for`:

```php

```

Параметры цикла `for` (в круглых скобках) можно разделить на три части, которые в свою очередь разделяются `;`, т.е. в данном случае точка с запятой выступают как разделитель, а не как окончание выражения или инструкции.

* Выражения, находящиеся в `части A`, PHP просто выполняет, и как правило, там инициализируется счетчик (т.е. мы назначаем какую-то переменную и говорим что она будет счетчик);
* `Часть B` (или так называемый встроенный `if`), здесь проверяется истинность, и в случае, если там `true`, то PHP заходит в тело цикла;
* Содержимое `части C` PHP, как и в случае с `частью A` просто выполняет и как правило, там мы изменяем наш счетчик.

В каждом из этих трех частей мы можем использовать не одно выражение, а сколько угодно, но в этом случае поскольку точка с запятой служит разделителем частей в конструкции for, разделять выражения следует запятой.

Когда интерпретатор PHP встречает цикл `for`, первое что он делает — заходит в `часть A` и делает все что там написано. Сюда он попадает только один раз. Потом он перемещается в `часть B` и если там `true`, то PHP выполняет тело цикла. Затем выполняется `часть C`. Таким образом, далее цикл работает как по треугольнику: `часть B` => тело цикла => `часть C`, до тех пор, пока условие в `части B` не окажется ложным.

Например: вывести нечетные числа от 0 до 50.

```php
";
}
?>
```

В цикле `for` любую из частей можно опустить. Пример классического бесконечного цикла:

```php
";
}
?>
```

### while

Синтаксис:

```php

```

Если условие истинно, то выполняется тело цикла. Цикл `for` и `while` взаимозаменяемы. Если мы знаем начальную и конечную точку (от скольки и до скольки), то удобнее использовать цикл `for`. Но бывает ситуация, когда мы не знаем конечной точки.

В теле цикла `while` можно использовать оператор `break`, который прерывает цикл и выйдет за его пределы.

```php
";
if ($i == 5)
break;
}
?>
```

Оператор `continue` в цикле `while` прерывает итерацию (переходит обратно к условию):

```php
");
}
?>
```

**Операторы `break` и `continue` во вложенных циклах**

По умолчанию `break` и `continue` выходят на один уровень вложенности, если необходимо чтобы `break` или `continue` участвовал и во внешних циклах, надо указать через пробел число соответствующее уровню:

```php

```

Если во втором вложенном цикле `while` используется `break`, то скрипт напечатает таблицу умножения только для числа 1 (`1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10`) и прервет внешний цикл выйдя из него насовсем.

Если же будет использоваться `continue`, то скрипт прервёт лишь итерации для числа 2, но продолжит выполнение для остальных чисел (`1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30` ...и так далее)

❗️ Значение оператора `break` или `continue` не должны
превышать уровень вложенности структуры.

### do..while

Синтаксис:

```php

```

Отличие от цикла `while` в том, что если условие изначально ложно, тело цикла выполнится хотя бы один раз. Пример с таблицей умножения в цикле `while` можно переписать так:

```php

```

### foreach

Конструкция `foreach` (для каждого) дает простой способ перебора массивов. `foreach` работает только с массивами и объектами, и будет генерировать ошибку при попытке использования с переменными других типов или неинициализированными переменными. Чтобы вывести только значения элементов массива, применим короткий синтаксис:

```php
"Jane",
"last-name" => "Doe",
"age" => 35,
"height" => 175,
"weight" => 55,
"hair-color" => 'brown'
);

foreach($user as $value) {
echo $value, "
";
}
?>
```

Вторая форма делает то же самое, за исключением того, что ключ текущего элемента будет присвоен переменной `$k` соответствующей каждому значению:

```php
$v) {
echo $k . " — " . $v . "
";
if (is_string($v))
$v = '';
}
?>
```

В выражении `$v = ''` на оригинальный массив эти изменения не повлияют, т.к. в переменную `$v` передается копия значения.

Если всё же необходимо, чтобы изменения затрагивали данные исходного массива который перебираем, то перед переменной используется `&`, тогда обращение будет происходить по ссылке на оригинальный массив.

```php

```

## Функции

_Функция_ – программный блок, который может многократно выполняться в любом месте сценария.

### Объявление и вызов

```php

```

**Вызов функции**

```php

```

### Аргументы функции

Аргументы передаются списком разделённых запятыми выражениями.

```php
Hello, John!

$name = "Jane";
hello($name); // -> Hello, Jane!

$funcName = "hello";
$funcName($name); // -> Hello, Jane!
?>
```

В последнем случае, если вслед за переменной стоит открывающая круглая скобка, то PHP интерпретирует это как вызов функции.

### Аргументы по умолчанию

Функция может определять значения по умолчанию путём присваивания его переменной аргумента. Это значение будет применено если параметр не был передан при вызове функции.

```php
Hello, $name!";
}

// Все аргументы передаются
sayHello("John", 1); // ->

Hello, John!

$name = "Jane";
// Второй аргумент потерян, будет прменен по умолчанию 3
sayHello($name); // ->

Hello, Jane!

// Все аргументы применятся по умолчанию
sayHello(); // ->

Hello, Guest!


?>
```

Если в функции есть параметры обязательные и по умолчанию, то сначала (слева направо) перечисляются обязательные параметры, а потом уже не обязательные. Пример ошибочной передачи параметров:

```php

```

### Области видимости переменных

В PHP существует два вида области видимости переменных — глобальная и локальная.

Глобальные переменные это все переменные вне тела функции, локальные переменные это те что находятся в теле функции.

```php

```

После определения `$a` и `$b` внутри функции ключевым словом `global` все ссылки на любую из этих переменных будут указывать на их глобальную версию. Не существует никаких ограничений на количество глобальных переменных, которые могут обрабатываться функцией.

Второй способ доступа к переменным глобальной области видимости — использование специального, определяемого PHP массива `$GLOBALS`. При создании переменной и присваивании ей значения PHP заносит данные в этот массив:

```php

```

Предыдущий пример может быть переписан так:

```php

```

### Статические переменные

В примере ниже мы хотим чтобы переменная `$a` сохраняла своё значение при каждом вызове функции и не теряла его, когда выполнение программы выходит из этой области видимости.

```php
0
staticVar(); // -> 0
staticVar(); // -> 0
?>
```

Такая реализация будет абсолютно бесполезной поскольку при каждом вызове она устанавливает `$a` в `0` и печатает `0`. Инкремент переменной `$a++` здесь не играет роли, так как при выходе из функции переменная `$a` исчезает.

Статические переменные существуют только в локальной области видимости функции. Чтобы написать полезную считающую функцию, которая не будет терять текущего значения счетчика, переменная `$a` объявляется как `static`:

```php
0
staticVar(); // -> 1
staticVar(); // -> 2
?>
```

### Рекурсия

Рекурсия – это способность функции вызывать саму себя изнутри. Ниже приведён классический пример реализации такого подхода в вычислении факториала для заданного числа.

```php
120
?>
```

### Функции управления функциями

**Проверка на существование**

Функция `function_exists` возвратит `true` если функция с переданным названием уже есть.

```php

```

**Список объявленных функций**

Если нужно получить список всех определённых функций, как встроенных, так и пользовательских применяется функция `get_defined_functions`, которая возвратит список функций в виде многомерного массива.

```php

```

**Работа с функцией изнутри**

Следующие функции применяются внутри тела функций.

```php
John
}

foo("John", 77, true);
?>
```

## Классы и объекты

Класс определяется ключевым словом `class` за которым следует его имя и пара фигурных скобок. Внутри скобок могут содержаться свойства и методы этого класса.

* Свойство класса – переменная внутри класса;
* Методы – функции класса;
* Имена класса чувствительны к регистру.

### Описание класса

```php

```

Пример готового класса.

```php

```

Обращение к свойству происходит с помощью стрелки `->` затем следует имя свойства без указания знака `$`.

```php
year; // Обращение к свойству
$car1->speed = 210; // Присваивание значения
?>
```

### Области видимости

Области видимости свойств, методов или констант могут быть определены через следующие спецификаторы (модификаторы) доступа:

* `public` (_публичный_, _общедоступный_) – позволяет иметь доступ к свойствам и методам класса из любого места;
* `protected` (_защищённый_) – позволяет иметь доступ и родительскому (в котором определен сам член класса), и наследуемым классам;
* `private` (_закрытый_) – ограничивает область видимости тем классом, в котором он объявлен.

```php
name;
$this->age;
$this->sex;
}
}

class Second extends First {
// class body
}

$third = new Second();
$third->name; // -> Alex
$thid->age; // -> Fatal error
$third->sex; // -> Notice: Undefined property
?>
```

**Псевдопеременная `$this`**

`$this` – указатель на запрашиваемый объект, доступна в случае, если метод был вызван в контексте объекта. Используется чтобы явно указать какой объект имеется ввиду для доступа из метода к свойству объекта. Вызов метода из метода также происходит через ключевое слово `$this`.

```php
speed;
}

function avgSpeed() {
'Скорость = ' . $this->getSpeed(); // Обращение к методу
}
}

$myCar = new Car();
$myCar->getSpeed(); // вызов метода
?>
```

### Конструкторы и деструкторы

_Конструктор класса_ – специальный метод, который автоматически вызывается в момент создания объекта. Используется когда нужно что-нибудь сделать при создании объекта (посыл cookie, запись в файл, ...).

_Деструктор класса_ – автоматически вызывается при удалении объекта. Деструктор не принимает параметров, скобки есть просто по синтаксису.
Порядок удаления объектов в PHP не определен, поэтому в деструкторах не обращаются к другим объектам, т.к. на момент вызова деструктора он может быть уже удален.

Сначала PHP ищет метод `__construct`, если он его не находит, то ищет метод одноименный с именем класса и расценивает его как конструктор. Но если `__construct` будет, то одноименный метод станет обычным методом.

```php
name = $name;
$this->login = $login;
$this->password = $password;
}

function __destruct(){
echo '

<Объект удален!/p>';
}
}

// При иницилизации автоматически сработает конструктор
// В скобках передаются параметры конструктору
$user1 = new User('Jane', 'janedoe', 'p@$$w0rd');

// При удалении или окончании кода вызовется деструктор
unset($user1);
?>
```

### Клонирование объектов

Иногда может понадобиться создать копию объекта, но создание копии с идентичными свойствами через обычное присваивание не всегда оказывается приемлемым вариантом. Для таких случаев копия объекта создаётся с помощью ключевого слова `clone`.

```php

```

Хотя и при клонировании создается новый объект, конструктор не вызывается. Для этого существует специальный метод `__clone`, который будет вызван при клонировании.

```php
mark = $mark;
$this->model = $model;
$this->speed = $speed;
}

// Выполнится при клонировании объекта
function __clone() {
$this->mark = 'Unknown';
$this->model = 'Unknown';
$this->speed = 0;
}
}

// Иницилизация объекта
$car1 = new Car('Tesla', 'Model X', 210);
$car1->model; // Tesla
$car2 = clone $car1; // Клонирование
$car2->model; // Unknown
?>
```

### Наследование

_Наследование_ – дочерний класс наследует все публичные и защищенные свойства и методы родительского класса. При объявлении класса, нужно указать какой класс он наследует (`extends`).

```php
year;
$book1->title;
?>
```

### Перегрузка методов

_Перегрузка методов_ – если имена методов в разных классах одинаковы, то применится метод описанный в классе к которому мы обращаемся, а не в родительском классе.

```php
title = $title;
}

function getInfo() {
return 'Product class';
}
}

class Book extends Product {
public $year;

// Перегрузка метода getInfo()
function getInfo() {
return __CLASS__;
}
}

$book1 = new Book('PHP & MySQL: Server-side Web Development');
$book1->getInfo(); // -> Book
?>
```

`parent` – обращение к родительским свойствам, методам, конструкторам, деструкторам, клонам, ...

```php
year = $year;
}
}

$book2 = new Book(
'PHP 8 Programming Tips, Tricks and Best Practices',
2023
);
?>
```

### Перебор свойств объекта

Перебор свойств объекта PHP осуществляется с помощью цикла `foreach`. Для большего контроля над данными можно использовать его расширенную версию с извлечением ключей `$key`, где будут храниться имена свойств объекта.

```php
name = $name;
$this->course = $course;
$this->faculty = $faculty;
}
}

$student = new student('John Doe', 3, 'PHP Programming');

foreach($student_1 as $key => $value) {
print "

$key: $value

";
}
?>
```

### Константы класса

Константы класса определяются с помощью ключевого слова `const`. Доступ к константе внутри класса – `self::ИМЯ_КОНСТАНТЫ`, вне класса – `имя_класса::ИМЯ_КОНСТАНТЫ`.

К имени класса можно обратиться с помощью переменной присвоив ей в качестве значения имя класса. Значение переменной не должно быть ключевым словом (например, `self`, `parent` или `static`).

```php
pawsQuantity(); // -> 4

// Значение такое же как и имя класса
$getTail = 'Animal';
echo $getTail::tail; // -> 1
?>
```

### Абстрактные классы и методы

От абстрактного класса нельзя напрямую создавать объект. А создается объект от наследника абстрактного класса.

Внутри абстрактного класса может быть и абстрактный метод. _Абстрактный метод_ – это метод без реализации (фигурных скобок). Он должен быть перегружен в классе наследника (иначе будет ошибка уровня _Fatal error_).

Если в классе появился хоть один абстрактный метод, весь класс должен быть объявлен как абстрактный. Абстрактный класс может быть без абстрактного метода, но не наоборот.

```php

```

### Интерфейсы

_Интерфейс_ – это тот же самый абстрактный класс, но который содержит только абстрактные методы. Для интерфейса справедливы все правила абстрактного класса, но со следующими отличиями:

* В интерфейсе все методы должны быть абстрактными;
* Наследуемый класс определяется с помощью ключевого слова implements;
* При описании интерфейса не используются слова class и abstract.

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

```php

```

PHP не поддерживает множественное наследование. Однако, мы можем реализовывать класс от нескольких интерфейсов. Например, `class` A `extends` B `implements` C, D, E, F, ...

```php

```

### Финальные классы и методы

Ключевое слово `final` предотвращает переопределение метода в дочерних классах. Если же сам класс определяется с этим ключевым словом, то он не может быть унаследован.

```php

```

### Статические свойства и методы

К статическим свойствам и методам можно обращаться без создания экземпляра класса с помощью оператора `::`. По этой причине псевдопеременная `$this` не может быть использована внутри таких методов.

```php
2
?>
```

`static` также используется для определения статических переменных, которые были рассмотрены в главе [Статические переменные](#Статические-переменные).

### Ключевое слово instanceof

`instanceof` – если требуется узнать, является ли класс унаследованным от другого класса или интерфейса.

Также можно использовать функцию `is_a()`, которая проверяет, принадлежит ли объект к данному классу или содержит данный класс в числе своих предков.

```php

```

### Автоматическая загрузка классов

Если PHP не может найти класс, то он прежде чем выдать ошибку сначала ищет функцию `__autoload()` передавая имя искомого класса. Если функция описана, то она будет вызвана перед ошибкой.

```php

```

Основное назначение функции `__autoload` подгружать файл где описан не найденный в текущем файле класс. Для этого необходимо создать файл с таким же названием, как и имя искомого класса.

```php

```

### Магические методы

_Магические методы_ – это специальные методы, которые переопределяют действие PHP по умолчанию, в момент когда над объектом выполняются определённые действия. В PHP есть следующие магические методы: `__construct()`, `__destruct()`, `__call()`, `__callStatic()`, `__get()`, `__set()`, `__isset()`, `__unset()`, `__sleep()`, `__wakeup()`, `__serialize()`, `__unserialize()`, `__toString()`, `__invoke()`, `__set_state()`, `__clone()` и `__debugInfo()`.

#### Методы доступа к свойствам объекта

Когда происходит **присваивание** значения к свойству, который не описан в классе – PHP, прежде чем создать это свойство, сначала ищет магический метод `__set()` куда передает имя и значение.

Когда происходит **обращение** к неизвестному свойству, который не описан в классе – PHP ищет магический метод `__get()`, куда передает имя свойства, и если такой метод есть, он вызывается.

```php
params[$name] = $value;
}

function __get($name){
// Есть ли ключ с таким именем в массиве $params?
if (array_key_exists($name, $this->params))
return $this->params[$name];
}

// Возвращает имя: значение неописанных свойств
function getArg(){
foreach($this->params as $k=>$v){
echo "

$k: $v

";
}
}
}

$obj = new A;

//Присваивание неописанному свойству
$obj->name = 'John';
$obj->last_name = 'Doe';
$obj->age = 30;
$obj->getArg();

// Обращение к неописанному свойству
echo $obj->name; // -> John
?>
```

#### Перегрузка вызова несуществующих методов

Если идет обращение к методу который не описан в классе, PHP ищет магический метод `__call()`, куда передает имя несуществующего метода и массив параметров.

```php
foo(123, 'milk', 'bread', 'solt'); // Такого метода нет в классе
?>
```

#### Преобразование объекта в строку

При попытке конвертации объекта в строку, следует вызов магического метода `__toString()`.

```php
Это класс "A"
?>
```

### Разыменование объектов

Мы можем создавать объект динамически (на лету) обращаться к его методам, не создавая самого объекта.

```php
myFunction(); // -> This class is "A"
?>
```

### Уточнение типа класса

PHP предоставляет возможность уточнить тип класса. Сделать это можно при передаче параметров метода, указав перед переменной название класса объекта.

```php
func1($obj2);
$obj1->func2($obj2);
?>
```

## Cookies

_Cookie_ позволяют сохранять пользовательские данные в браузере для последующей идентификации или отслеживания. _Cookie_ посылается серверу, чтоб тот "сказал" браузеру, чтобы он установил _cookie_ для текущего пользователя. Передаются _Cookie_ вместе с HTTP-заголовками в ответе сервера и если _Cookie_ у пользователя уже существует, то оно отправится при запросе вместе с HTTP-заголовками.

HTTP-заголовок `Set_Cookie: UserName=John` – при ответе на запрос.
Заголовок `Cookie: UserName: John` – если у нас уже есть _Cookie_, то она отправляется при запросе.

_Cookie_ может быть сессионная или условно постоянная. _Сессия_ – время до закрытия браузера. Постоянные _Cookie_ могут быть до тех пор, пока пользователь намеренно не очистит свой браузер от них.

### Создание Cookie

```php
setcookie(
"название-cookie",
"значение-cookie",
период действия (временая метка Unix),
"путь (директория в которой доступна cookie)",
"домен (которому будет доступна cookie)",
true (если отправляется по безопасному протоколу HTTPS)
);
```

В имени куки должны быть только латинские буквы, цифры, символ подчеркивания и дефис. Все другие символы будут преобразованы в символ подчеркивания.

### Чтение Cookie

```php
PHP

while(list($name, $value) = each($_COOKIE) {
$myArray[] = $value; // для индексированного массива
$myArray[$name] = $value; // для ассоциативного массива
}
?>
```

Массивы хранятся в _Cookie_ в сериализованном виде.

```php
'Jane',
'age' => 37,
'e-mail' => '[email protected]',
'uri' => 'https://janedoe.com'
);

// Сериализация массива в строку
serialize($userInfo);
// Выставление cookie на две недели
setcookie('userInfo', serialize($userInfo), time() + 1209600);
// Десериализация и перевод в массив
$userInfo = unserialize($_COOKIE['userInfo']);
?>
```

### Удаление Cookie

Чтобы удалить _Cookie_, официально принято послать имя _Cookie_ без значения.

```php

```

или послать _Cookie_ с пустым значением:

```php

```

или указав заднее время:

```php

```

## Сессии

_Сессия_ – глобальная переменная (ассоциативный массив), хранящаяся на сервере и содержащий переменные сессии, которые доступны из всех файлов сразу. Грубо говоря сессии – это аналог _Cookie_, данные которых, временно хранятся у нас на сервере.

Браузер создает сессионную _Cookie_, по умолчанию с заголовком `PHPSESSID` (можем изменить `session_name('cookie_name')`) с уникальным значением (`session_id()`), именно по нему происходит распознание пользователя. При запросе PHP распознает заголовок по умолчанию `sessid` с уникальным идентификатором.

Механизм сессий можно было б воссоздать вручную, в целом проделывается следующее:

* Создается файл, со случайно сгенерированным именем;
* Посылается сессионная _Cookie_;
* Когда мы заносим данные в массив `$_SESSION` в файле сессии данные хранятся в сериализованной строке (функция `serialize()`);
* Считывание данных, в массиве `$_SESSION` результат десериализации (функция `unserialize()`).

Когда пользователь запрашивает страницу, мы проверяем есть ли для него сессия, если нет то создаем её. А когда необходимо подсчитать результаты, мы берем данные из глобального массива `$_SESSION` и выдаем результат.

Физически на компьютере пользователя (`C:\WINDOWS\Temp`) создается файл с уникальным идентификатором, однозначно идентифицирующий пользователя, а когда сессия закончится – этот файл удалится сам.

**Создание и использование**

Начало и/или продолжение сессии осуществляется вызовом функции `session_start()`. Функция вызывается вначале исполнения файла, сессия при этом либо создаётся, либо продолжается.

Когда создается сессия в браузер посылается Cookie следующего содержания:

```php
PHPSESSID=btcii6g2ak26rsvogoov47jr25
?>
```

Физически данные сессии хранятся в файле, но для работы с переменными сессии есть глобальный массив `$_SESSION`. Если мы что-то хотим сохранить в сессии, то создаем ячейку и присваиваем значение.

```php
// Создание и доступ к элементу сессии
$_SESSION['User'] = 'John';
echo $_SESSION['User']; // -> John

// Удаление ячейки массива
unset($_SESSION['User']);

// Закрытие сессии (физическое удаление файла)
session_destroy();
?>
```

При закрытии сессии `session_destroy()` файл сессии удаляется физически, но _Cookie_ остается все равно и при очередном открытии сессии, браузер создаст файл с точно таким же идентификатором, поэтому рекомендуется сразу после закрытии сессии удалять и _Cookie_. Например:

```php

```

## HTTP-заголовки

Все HTTP-заголовки посылаются с помощью функции `header("имя_заголовка: значение")`. Структура HTTP-запроса на примере запроса `HEAD` выглядит следующим образом:

_Запрос_

```http request
HEAD /folder/index.html HTTP/1.1
Host: www.example.com
Accept: */*
Accept-Language: ru
Referrer: https://google.com/search?text=SearchingText
User-Agent: Mozilla/5.0 (Windows NT 11.0; Win64; x64)...
```

_Ответ_

```http request
HTTP/1.1 200 OK
Server: Microsoft IIS 10
Content-Type: text/html
Content-Length: 12345
Last-Modified: Tue, 19 Oct 2023 00:45:00 GMT+6
```

Как только браузер встречает заголовок `Location`, то сразу перезапрашивает адрес указанный в заголовке `Location`, т.е. фактически происходит редирект на уровне HTTP-заголовков.

```php

```

Однажды отправленный запрос, со всеми передаваемыми заголовками при обновлении страницы браузера(`F5`) повторяет тот же самый запрос. С помощью `Location` можно от этого избавиться перезапросив эту же страницу методом GET.

```php

```

Перезапрос страницы через определенное количество секунд:

```php

```

Обработка файла по указанному MIME-типу:

```php

```

**Управление кэшированием и актуальностью веб-страницы**

Браузер может закэшировать страницу, но перед очередным запросом должен проверить - не обновлялась ли страница, если нет, то кэш используется.

```php

```

_Cookie_ можно послать с помощью функции `header()`, как HTTP-заголовок.

```php

```

## Файлы

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

- Открыть файл;
- Выполнить операцию чтения, изменения или записи в файл;
- Закрыть файл.

### Получение сведений о файлах

```php

```

### Открытие и закрытие

```php

```

### Режимы работы с файлами

mode | Описание
:---:|---
'r' | Открывает файл только для чтения; помещает указатель в начало файла.
'r+' | Открывает файл для чтения и записи; помещает указатель в начало файла.
'w' | Открывает файл только для записи; в противном случае ведёт себя так же, как и `w+`.
'w+' | Открывает файл для чтения и записи; помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует - пытается его создать.
'a' | Открывает файл только для записи; помещает указатель в конец файла. Если файл не существует - пытается его создать. В данном режиме функция `fseek()` не применима, записи всегда добавляются в конец.
'a+' | Открывает файл для чтения и записи; помещает указатель в конец файла. Если файл не существует - пытается его создать. В данном режиме функция `fseek()` влияет только на позицию чтения, записи всегда добавляются в конец.
'x' | Создаёт и открывает только для записи; помещает указатель в начало файла. Если файл уже существует, вызов `fopen()` закончится неудачей, вернёт `false` и выдаст ошибку уровня `E_WARNING`. Если файл не существует, попытается его создать.
'x+' | Создаёт и открывает для чтения и записи; в остальном имеет то же поведение, что и `x`.
'c' | Открывает файл только для записи. Если файл не существует, то он создаётся. Если же файл существует, то он не обрезается (в отличие от `w`), и вызов к этой функции не вызывает ошибку (также как и в случае с `x`). Указатель на файл будет установлен на начало файла. Это может быть полезно при желании заблокировать файл (смотрите `flock()`) перед изменением, так как использование `w` может обрезать файл ещё до того как была получена блокировка (если вы желаете обрезать файл, можно использовать функцию `ftruncate()` после запроса на блокировку).
'c+' | Открывает файл для чтения и записи; в остальном имеет то же поведение, что и `c`.
'e' | Установить флаг `close-on-exec` (закрыть при запуске) на открытый файловый дескриптор.

### Чтение файла

```php
строка
echo fgets($f); // -> следующая строка

// Функция fgetss() аналогична функции fgets() с той разницей,
// что эта функция зачитывает файл без html и php тегов
echo fgetss($f, filesize('text.html'), '
');
// -> строка с сохранением тегов
и

// Посимвольное считывание
echo fgetc($f); // -> cимвол
echo fgetc($f); // -> cледующий символ

fclose($f); // Закрытие файла
?>
```

### Запись в файл

```php

```

### Манипуляции с курсором

```php

```

### Прямая работа с данными

```php

```

### Управление файлами

```php

```

### Директории (каталоги)

**Манипуляция с папками**

```php

```

**Открытие и чтение**

```php
имя папки или false, если ошибка

// Закрытие директории
closedir($dir); // Освобождает дескриптор каталога
?>
```

**Сканирование директории**

`scandir()` получает массив элементов текущей директории. Если передать второй параметр `true`, то функция вернет массив в обратном порядке.

```php

```

**Организация вывода всех файлов и папок в директории**

```php
Это папка ' . $myDir . '';
else
echo '

Это файл ', $myDir, '

';
}
?>
```

Разработчики PHP не гарантируют порядок выборки файлов и директории. Обычно элементы директории возвращаются в том порядке, в котором они хранятся в файловой системе, но это не значит, что это будет так везде (зависит от ряда факторов: операционная система, версии PHP и т.д.). Для контроля вывода, рекомендуется элементы сначала добавить в массив (функция `scandir()`) и отсортировать их.

### Загрузка файлов на сервер

Файлы загружаются на сервер только методом _POST_. При этом атрибут `enctype` тега `` должен быть `multipart/form-data`.

Для отправки файлов на сервер может понадобиться настройка конфигурационного файла `php.ini`, а именно следующие параметры:

* `file_uploads (on | off)` – разрешает или нет закачивание файлов;
* `upload_tmp_dir` – временная директория, используемая для временного хранения закачанных файлов. Должна быть доступна для записи пользователю, от имени которого запущен PHP. Если не указана, используется директория по умолчанию для вашей системы. Если для указанной директории нет прав на запись, PHP откатится обратно к системной временной директории, используемой по умолчанию. Если включена директива `open_basedir`, то для успешной загрузки файлов системная директория по умолчанию должна быть разрешена;
* `upload_max_filesize` – по умолчанию равна 2 Мб, максимальный размер закачиваемого файла. Здесь нужно чтобы значение директивы `post_max_size` было больше значения `upload_max_filesize`;
* `post_max_size` – устанавливает максимально допустимый размер данных, отправляемых методом POST. Это значение также влияет на загрузку файлов на сервер.

Чтобы ограничить размер посылаемых данных (например: аватарок на форуме) можно создать скрытый `input` и задать параметру `MAX_FILE_SIZE` определенное значение:

```html


Послать файл

```

### Разбор файлов на сервере

После отправки файла на сервер все файлы сначала попадают во временную директорию, которая указана в директиве `upload_tmp_dir`. Когда файлы попадают в эту директорию, они временно переименовываются. И вся информация, которая к нам приходит, попадает в суперглобальную переменную `$_FILES`.

Массив `$_FILES` двумерный, ячейка первая — это имя поля, которое указано в атрибуте name тега `input`, а в ней в свою очередь 5 ячеек:

```php

```

Если файл пришел без ошибок, то мы его "забираем" себе перемещая в нужное место.

```php

```

## Работа с почтой

**Настройка конфигурации**

Директивы настроек по работе с почтой находятся в секции `[mail functions]` файла `php.ini`. Настройки эти только для ОС Windows.

* `SMTP = localhost` – адрес SMTP-сервера;
* `sendmail_from =
[email protected]` – e-mail по умолчанию от кого будет приходить почта.

Функция `mail()` позволяет отправлять электронную почту. PHP сам письма не отправляет, а только передает почтовому серверу. Поэтому функция `mail()` говорит только о том, что PHP передал письмо почтовому серверу.

**Пример отправки**

```php

```

**Пример расширенной отправки**

```php
\r\n";
?>
```

## Базы данных и SQL

_База данных (сокр. БД)_ – набор данных, хранящийся в электронном виде, которая управляется программой (СУБД) по взаимодействию с этой базой данных. База данных по отношению к управляющей ею программе является её элементом, единичной сущностью этой программы.

_СУБД_ – система управления базой данных, программное обеспечение, необходимое для создания, изменения и обслуживания файлов БД.

_Проектирование БД_ – создание эффективной структуры данных, обеспечивающее хранение требуемой информации.

Существуют следующие разновидности баз данных:

* иерархические – подобно файловой системе компьютера основана на древовидной структуре хранения информации;
* реляционные – табличное представление данных;
* объектно-ориентированные – данные хранятся в виде объектов;
* гибридные – совмещают возможности реляционных и объектно-ориентированных баз данных.

В реляционных базах данных:

- Данные хранятся в таблицах, состоящих из столбцов и строк;
- На пересечении каждого столбца и строки находится в точности одно значение;
- У каждого столбца есть свое имя, которое служит его названием, и все значения в одном столбце имеют один тип;
- Запросы к БД возвращают результат в виде таблиц, которые тоже могут выступать как объект запросов.

### Введение в SQL

_SQL (Structured Query Language — Язык структурированных запросов)_ – универсальный язык, применяемый для создания, модификации и управления данными в реляционных базах данных.

Язык SQL делится на три части:

- _DDL (Data Definition Language - язык определения данных)_ – состоит из команд, которые создают объекты, изменяют или удаляют их. Под объектами понимается таблицы, индексы, просмотры и т. д. в базе данных:
- CREATE (создать);
- ALTER (изменить);
- DROP (уничтожить).

- _DML (Data Manipulation Language - Язык манипуляции данными)_ – набор команд, которые определяют, какие значения представлены в таблицах в любой момент времени. Для работы с информацией, находящихся внутри объектов базы данных:
- INSERT (вставить);
- UPDATE (обновить);
- DELETE (удалить).

- _DCL (Data Control Language - Операторы управления данными)_ – состоит из средств, которые определяют, разрешить ли пользователю выполнять определенные действия или нет. Одним словом, для управления доступом к данной базе:
- GRANT (предоставить доступ);
- DENY (запретить доступ);
- REVOKE (временно отменить доступ).


- _DQL (Data Query Lanquage – Язык запросов)_:
- SELECT (выбрать).

### Примеры SQL-запросов

**Запросы SELECT**

_выборка с сортировкой_

```sql
SELECT name, addr, city -- Перечисление полей
FROM teachers -- Из какой таблицы
ORDER BY name -- Сортировать по полю name
```

_с определенным условием_

```sql
SELECT title
FROM courser
WHERE length > 30
```

_совпадение в строковых значениях_

```sql
SELECT *
FROM courses
WHERE length > 30 -- длина больше 30
AND title LIKE 'Web%' -- значение поля title должно начинаться с Web
```

_объединение 2-ух таблиц_

```sql
SELECT t.lname, t.fname, l.course -- Выборка полей из конкретных таблиц
FROM teachers t, lessons l -- Назначение таблице teachers алиас t
INNER JOIN lessons l ON t.id = l.teacher_id -- Внутреннее объединение
```

_левое внешнее соединение_

Если записям в левой таблице не найдутся соответствия, то они выводятся в конце со значением NULL.

```sql
SELECT t.lname, t.fname, l.course
FROM teachers t, lessons l
LEFT OUTER JOIN lessons l ON t.id = l.teacher_id
```

_объединение 3-ёх таблиц_

```sql
SELECT DISTINCT teachers.name
FROM teachers INNER JOIN
(lessons INNER JOIN courses ON lessons.course = courses.id)
ON teachers.id = lessons.teachers
WHERE courses.title LIKE 'Web%'
ORDER BY teachers.name
```

**Запросы INSERT**

В таблицу `courses` добавить значения в каждое поле.

```sql
INSERT INTO courses
VALUES (Null, 'Java2', '...', 40) -- Добавляемые значения
```

Добавление только в конкретные поля.

```sql
INSERT INTO courses (title, length)
VALUES ('Java', 40) -- Добавляемые значения
```

**Запрос DELETE**

```sql
DELETE FROM lessons -- Из какой таблицы
WHERE lessons.date = '2013-05-17' -- Условие удаления
```

Важно! Если не передать условие, то удалятся все записи.

**Запросы UPDATE**

```sql
UPDATE teachers -- В какой таблице
SET -- Установить обновление
zarplata = zarplata * 2,
premia = premia * 10
WHERE name LIKE 'Иванов%'
OR name LIKE 'Петров%'
OR name LIKE 'Сидоров%'
```

```sql
UPDATE teachers
SET
zarplata = zarplata * 2,
premia = premia * 10
WHERE name IN ('Иванов', 'Петров', 'Сидоров')
```

## MySQL

_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 в свою линейку СУБД.

### Работа с MySQL в консоли

Для работы с базами в консоли у MySQL есть утилита командной строки _mysql.exe_.

```bat
:: Открытие MySQL monitor (соединение с сервером баз данных MySQL)
mysql -ulogin -ppassword
:: Использование базы данных
USE имя_базы_данных
:: Установка кодировки
SET NAMES 'utf8mb4'
:: Показать существующие таблицы в БД
SHOW TABLES
:: Показать поля, типы, ключи, ... таблицы
DESCRIBE имя_таблицы
:: Выход
quit (или exit)
```

Конец запроса разделяется `;` (или `\g`). Если результат выборки не помещается в окно, то можно в конце добавить `\G`.

**Использование утилиты mysqldump (создание дампа БД)**

```bat
:: Создать дамп БД
mysqldump -uroot -ppass имя_БД > dump.sql

:: Создать БД с именем database_name
:: на основе запросов из дампа dump.sql
mysql -uroot -ppass database_name < dump.sql
```

### Создание базы данных и таблиц

Общий алгоритм работы с сервером баз данных:
1. Устанавливаем соединение с сервером баз данных;
2. Выбираем базу данных для работы;
3. Посылаем запрос:
√ При необходимости (SELECT), работаем с выбранными данными;
4. Закрываем соединение.

Для работы с MySQL необходимо подключить расширения:
- _php_pdo.dll_
- _php_pdo_mysql.dll_
- _php_mysql.dll_

**Соединение с сервером баз данных**

```php

```

**Соединение с самой базой данных**

```php

```

**Отправка запроса**

```php

```

**Некоторые функции обработки выборки**

```php
';
}

// Точечная выборка из конкретной ячейки
// -> 1-ая ячейка поля address
mysql_result($query_result, 0, 'address');
// Идентификатор сгенерированный при последнем INSERT-запросе
mysql_insert_id($connect);
?>
```

### Модуль MySQLi

_Расширение MySQLi (MySQL Improved)_ – позволяет получить доступ к функциональности, которую предоставляет MySQL-сервер.

К ядру PHP подключаются ряд необязательных модулей, расширяющие круг задач, который может выполнить код на PHP. Относящиеся к MySQL модули, такие как `mysqli` и драйвер PDO MySQL, взаимодействуют с ядром с помощью таких PHP модулей.

**Настройка модуля `mysqli`**

В конфигурационном файле `php.ini` убедитесь что модули `php_mysqli.dll` и `php_pdo.dll` подключены.

`mysqli` предоставляет следующие преимущества:
- Помимо процедурного интерфейса предоставляет и объектно-ориентированный интерфейс;
- Имеет поддержку дополнительных функций мониторинга, отлова ошибок, управления загрузкой и репликации;
- Подготавливаемые запросы и поддержка транзакций и мультизапросов.

**Особенность подключения с MySQLi**

```php

```

Подробнее в [документации MySQL](https://dev.mysql.com/doc/) на официальной странице сервера и в [документации модуля MySQLi](https://www.php.net/manual/ru/book.mysqli.php) на странице php.net.

## SQLite

* _SQLite_ – библиотека, написанная на языке C, реализующая встраиваемый движок SQL базы данных;
* Программы, использующие библиотеку _SQLite_, могут использовать SQL базы данных без использования внешнего процесса реляционной системы управления базами данных (RDBMS);
* _SQLite_ не является клиентской библиотекой, подключающейся к большому серверу базы данных, _SQLite_ сама является сервером и напрямую оперирует файлами базы данных на диске;
* Реализованы как серверные, так и клиентские функции.

**Преимущества использования SQLite**

- Полностью бесплатна;
- Нет необходимости в средствах администрирования;
- Высокая производительность и легкая переносимость;
- Поддержка процедурного и объектно-ориентированного интерфейсов;
- Хранение данных объемом до 2 терабайт;
- Хранение строк и бинарных данных неограниченной длины.

**Ограничения использования SQLite**

* _SQLite_ предназначен для небольших и средних приложений;
* Основной выигрыш в производительности, если преобладают операции вставки и выборки данных;
* При чрезвычайно активном обращении к данным, или в случае частых сортировок, _SQLite_ работает медленнее своих конкурентов.

### Поддержка SQLite в PHP

В PHP 5.0 поддержка SQLite была доступна по умолчанию на уровне ядра. Начиная с PHP 5.1 поддержка _SQLite_ вынесена за пределы ядра. Начиная с версии PHP 5.4, расширение _SQLite_ доступно только через PECL.
Расширение _SQLite3_ доступно по умолчанию начиная с версии PHP 5.3.0.

Пользователи Windows должны включить поддержку `php_sqlite3.dll` для того, чтобы использовать это расширение. Эта DLL входит в состав Windows-дистрибутивов РНР начиная с версии PHP 5.3.0.

```ini
extension=php_pdo.dll
extension=php_sqlite.dll
```

### Создание базы, таблиц и выборка данных

В примере если файла с именем `test.db` нет — он создастся, есть — установится соединение.

```php

```

**Особенности в SQLite3**

Первичный ключ автоматически становится _autoincrement_.

```php

```

**Получение результата выборки в виде массива**

```php
_db->query($sql);
$i = 0;

while($record[$i] = $result->fetchArray(SQLITE3_ASSOC)) {
while(list($name, $value) = each($record))
$records[$name] = $value;
$i++;
}

return $records; // -> Двумерный массив со всеми записями
}
?>
```

**Исключения в SQLite3**

```php
_db->query($sql); // -> Результат запроса
if(!$res) throw new Exception($this->_db->lastErrorMsg());
return true; // -> true, если запрос успешен
} catch(Exception $error) {
// Запись в лог ошибок
file_put_contents('errors.log', $error, FILE_APPEND);
// Отправить письмо с ошибкой
mail('[email protected]', 'Тема письма', $error);
return false; // -> false, если запрос завершился неудачей
}
?>
```