Skip to content

sa2kasov/php-reference-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

58 Commits
 
 

Repository files navigation

PHP Logo

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

Содержание

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

Предыстория

PHP – расшифровывается как PHP: Hypertext Preprocessor (рекурсивный акроним), язык общего назначение активно применяемый в веб-разработке. Берёт начало в 1994 году когда датский программист Расмус Лердорф разработал на языке C набор CGI-скриптов обрабатывающие HTML-документы для учёта посетителей его онлайн-резюме. Первый релиз состоялся 8 июня 1995 году.

Язык подвергся значительной переработке когда в 1997 году два израильских программиста, Энди Гутманс и Зеев Сураски, полностью переписали код интерпретатора. Новая версия языка 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 php_flag short_open_tag off ?>

Связка с веб-сервером 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\
  1. Скопировать файл php.ini в директорию:
  • PHP;
  • Сервера;
  • ОС Windows (например, C:\Windows).

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

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

PHP–теги

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

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

<?php инструкция; ?>

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

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

<? код PHP ?>

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

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

<% код PHP %>

Комментарии

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

<?php 
# однострочный комментарий
// однострочный комментарий
?>

<?php
/*
это блочный комментарий
*/
?>

Hello, World!

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

<?php
echo "Привет, это просто текст";
print "Привет, это просто текст";
print("так тоже можно");

// Здесь четыре раза вызывается echo
echo '<h1>', 'Hello, ', 'world!', '</h1>';

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

Переменные

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

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

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

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

<?php
// Переменной $var присваивается значение John
$var = 'John';

// Переменной $num присваивается значение 99
$num = 99;

// Переменной $num присваивается результат выражения, т.е. 10
$num = 5 + 5;
?>

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

<?php
$user = "John";
echo $user;

// Удаление из памяти переменную $user
unset($user);

// Уведомление (PHP Notice) о том, что переменная неопределена
echo $user;
?>

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

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

<?php
$beer = 'Heineken';

// Выведет переменную beer,
// т.к. апостроф не допустимый символ в именах переменных
echo "$beer's taste is great<br>";

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

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

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

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

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

<?php
$a = 10;
$b = &$a; // Ссылка на переменную $a
echo $b; // -> 10
?>

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

$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
// Целые числа
$int = 123; // Целое десятичное число
$int = -23; // Целое отрицательное число
$int = 0123; // Восьмиричное число (начинается с 0)
$int = 0x1A; // Шестнадцатиричное число

// Вещественные числа
$flt = 1.23; // Дробное число
$flt = 1.2e3; // экспоненциальная запись
$flt = 7E-10;
?>

String

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

<?php
$str = "Текстовая строка"; // в двойных кавычках
echo $str;
?>

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

  • \n - перевод на новую строку;
  • \r - возврат каретки;
  • \t - горизонтальная табуляция;
  • \ - обратный слеш;
  • $ - знак доллара;
  • " - двойная кавычка;
<?php
$str = 'Текстовая строка'; // в одинарных кавычках
echo 'Переменная $str - ' . $str; // -> Переменная $str - Текстовая строка
?>

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

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

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

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

<?php
echo <<<LABEL
Пример строки, охватывающей несколько строк, с использованием
heredoc-синтаксиса.

Это очень похоже на использование HTML-тега <PRE>,
т.е. сохраняются пробелы, отступы, переходы на новую строку,
табуляции, также сюда можно подставлять переменные, использовать
специальные символы.
LABEL;
?>

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

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

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

<?php
echo <<<'LABEL'
строка nowdoc
LABEL;
?>

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

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

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

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

<?php
$str = "Hello, world!";

// Получение первого символа строки
$first = $str{0}; // Возвращает позицию первого символа, т.е. H

// То же самое можно сделать используя квадратные скобки
$first = $str[0]; // Возвращает позицию первого символа, т.е. H

// Получение третьего символа строки
$third = $str{2}; // Возвращает l

// Получение последнего символа строки
$last = strlen($str); // Возвращает количество символов (отсчет с 1)
$sym = $str{$last - 1}; // Возвращает ! знак
print "$sym"; // Печатает ! знак
?>

NULL

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

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

Операторы

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

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

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

<?php
$a + $b; // Сумма $a и $b
$a - $b; // Разность $a и $b
$a * $b; // Произведение $a и $b
$a / $b; // Частное от деления $a на $b
$a % $b; // Целочисленный остаток от деления $a на $b
$a += $b; // Тоже, что и $a = $a + $b.

// Остальные операторы работают аналогично
$a = '5Word';
$b = $a * 10; // От переменной $a возмется 5 и результат будет 50

$a = 'Строка';
$b = $a * 10; // Переменная $a приведется к нулю и результат будет 0
?>

Строковые

<?php
$word1 = "Привет!";
$word2 = $word1 . " Мир"; // Конкатенация (возвращает "Привет! Мир")

$word1 .= " Мир"; // Конкатенация сокращенная (возвращает "Привет! Мир")

$word3 = "Я";
$word4 = "люблю";
print $word3 . " " . word4 . " " . "кофе!";
echo $word3, ' ', $word4, ' ', 'чай!';
?>

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

<?php
$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
$a <= $b // -> true если $a меньше или равно $b
?>

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

<?php
$a and $b // -> 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
$variable = "100darov";
echo gettype($variable); // Возвращает string
?>
  • settype(имя_переменной, "тип") – конвертирует переменную в другой тип. Например:
<?php
$variable = "100darov";
settype($variable, "integer"); // Возвращает integer
?>
  • Временное приведение к типу

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

<?php
$variable = "100darov";
echo (integer)$variable; // -> 100
?>

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

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

if

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

<?php
$var = true;
if ($var) echo "Инструкция выполнится, в $var истинное значение";
?>

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

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

if..else..

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

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

if..elseif..else..

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

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

<?php
if (условие 1) {
  инструкция 1;
}
elseif (условие 2) {
  инструкция 2;
} else {
  инструкция 3;
}

инструкция 4;
?>

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

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

<?php if (условие 1): ?>
  код условия 1
<?php elseif (условие 2): ?>
  код условия 2
<?php else: ?>
  код блока else
<?php endif; ?>
?>

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

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

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

<?php
echo ($a > 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.

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

<?php
switch (выражение) {
  case 0: инструкция 1;
  case 1: инструкция 2;
  case 2:
    инструкция 3;
    continue;
  case 3: инструкция 4;
  case 4:
    инструкция 5;
    break;
  case 5: инструкция 6;
  case 6: инструкция 7;
  default:
    инструкция 8;
}
?>

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

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

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

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

<?php
$result = ini_get("post_max_size"); // -> 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
$result = ini_get("post_max_size"); // -> 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
class User {
  public $name, $last_name, $age, $sex;

  function __construct($name = '', $lastName = '', $age = 0, $sex = '') {
    try {
      if($name == '' or $lastName == '' or $age == 0 or $sex == '')
        throw new Exception('Введены не все данные!');
      $this->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, либо String. Значение же может быть любым типом.

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

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

<?php
$arr = [0 => '1st', 1 => '2nd', 3 => '3rd'];

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

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

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

<?php
$user = Array(
  "Jane",
  "Doe",
  20,
  // Значение "guest" теперь будет имет порядковый номер (индекс) 55
  55 => "guest",
  true
);
?>

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

<?php
$cars['tesla'] = Array(
  'model' => "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
$contents = array(
"Введение",
"Часть I" => 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(). Для сохранения форматирования вывод был обрамлён тегами <pre>.

echo '<pre>', print_r($user), '</pre>';

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

echo "<pre>", var_dump($cars), "</pre>";

// Результат выполнения
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
echo "Меня зовут {$user['name']}! Мне {$user['age']} лет";
?>
  • Обращаться к ячейкам массива без кавычек:
<?php
echo "Меня зовут $user[name]! Мне $user[age] лет";
?>

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

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

<?php
// Исходный маассив
$menu['Блюдо']['Суп1'] = "Борщ";
$menu['Блюдо']['Суп2'] = "Щи";
$menu['Блюдо']['Суп3'] = "Рассольник";
$menu['Блюдо']['Салат1'] = "Венегрет";
$menu['Блюдо']['Салат2'] = "Оливье";
$menu['Блюдо']['Салат3'] = "Под шубой";

// Возвратить текущий элемент массива
current($menu['Блюдо']); // -> Борщ

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

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

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

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

Константы

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

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

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

<?php define('имя_константы', значение); ?>

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

<?php
defined("имя_константы"); // -> 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
class myClass{
  function getMethod(){
    echo __METHOD__:
  }

  function getClass(){
    echo __CLASS__;
  }
}

$myObject = new myClass();
$myObject->getMethod; // myClass::getMethod
$myObject->getClass; // myClass
?>

Циклы

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

for

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

<?php
for (часть A; часть B; часть C) {
  инструкция 1;
  инструкция 2;
  ...
}
?>

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

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

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

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

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

<?php
$str = "Привет! Мир";
for($j=0, $cnt = strlen($str); $j < $cnt; $j++) {
  echo $str{$j}, "<br>";
}
?>

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

<?php
for(;;) {
  print $a . "<br>";
}
?>

while

Синтаксис:

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

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

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

<?php
$i = 1;

// Скрипт последовательно напечатает 1 2 3 4 5
// из-за условия внутри тела цикла
while($ < 10) {
  $i++;
  print $i . "<br>";
  if ($i == 5)
    break;
} 
?>

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

<?php
$i = 0;

// Печатает числа от 1 до 10 пропустив число 5
while($i < 10) {
  $i++;
  if ($i == 5)
    continue;
  print ($i . "<br>");
}
?>

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

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

<?php
$levelOne = 0;

// Печатает таблицу умножения от 1 до 10
while ($levelOne < 10) {
  $levelOne++;
  $levelTwo = 0;
  while ($levelTwo < 10) {
    $levelTwo++;
    if ($levelOne == 2)
      break 2; // или continue 2
    echo "| ", $levelOne * $levelTwo, " ";
  }
}
?>

Если во втором вложенном цикле 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
do {
  инструкция 1;
  инструкция 2;
} while (условие);
?>

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

<?php
$levelOne = 0;

do {
  ++$levelOne;
  $levelTwo = 0;
  do {
    $levelTwo++;
    if ($levelOne == 2)
        continue 2;
    echo '', $levelOne * $levelTwo, ' ';
  } while($levelTwo < 10);
} while($levelOne < 10);
?>

foreach

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

<?php
$user = array(
  "name" => "Jane",
  "last-name" => "Doe",
  "age" => 35,
  "height" => 175,
  "weight" => 55,
  "hair-color" => 'brown'
);

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

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

<?php
foreach($myArray as $k => $v) {
  echo $k . "" . $v . "<br>";
  if (is_string($v))
    $v = '';
}
?>

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

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

<?php
foreach($array as &$v)
  if (is_string($v))
    $v = '';
?>

Функции

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

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

<?php
function hello() {
  echo "Hello, world!";
}
?>

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

<?php sayHello(); ?>

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

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

<?php
function hello($name) {
  echo "Hello, $name!";
}

hello("John"); // -> Hello, John!

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

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

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

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

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

<?php
function sayHello($name = "Guest", $h = 3) {
  echo "<h$h>Hello, $name!</h$h>";
}

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


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

// Все аргументы применятся по умолчанию
sayHello(); // -> <h3>Hello, Guest!</h3>
?>

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

<?php sayHello(, 3); ?>

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

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

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

<?php
// Глобальные переменные
$a = 7; $b = 9;

// Параметры функции — локальные переменные
function summa($a, $b) {
  global $a , $b; // Ссылка на глобальные переменные
  return $a + $b;
}

// Возвращает 16 если переменные $a и $b
// определены внутри функции global, иначе 36
echo summa(17, 19);
?>

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

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

<?php
// Объявление глобальной переменной
$age = 20;

// Альтернативный вариант создания глобальной переменной
$GLOBALS['age'] = 20;
?>

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

<?php
$a = 7; $b = 9; $cnt;

function summa($a, $b) {
  // Объявление $cnt как глобальная переменная
  $GLOBALS['cnt'];
  
  // ну или так
  global $cnt;
  
  // Подсчет кол-ва вызовов функции
  $cnt++;
  return $GLOBALS["a"] + $GLOBALS["b"];
}

echo summa(17, 19);
echo summa(21, 15);
echo summa(14, 37);
echo "Функция summa была вызвана $cnt раз(а)";
?>

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

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

<?php
function staticVar($a) {
  $a = 0;
  echo $a;
  $a++
}

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

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

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

<?php
function staticVar() {
  static $a = 0;
  echo $a;
  $a++;
}
staticVar(); // -> 0
staticVar(); // -> 1
staticVar(); // -> 2
?>

Рекурсия

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

<?php
function factorial($n) {
  if ($n == 0) return 1;
  return $n = $n * factorial($n - 1); // Функция вызывает саму себя
}

echo factorial(5); // -> 120
?>

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

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

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

<?php
if(!function_exists("hello")) {
  // такой функции нет, можно создать её 
}
?>

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

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

<?php print_r(get_defined_functions()); ?>

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

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

<?php
function foo() {
  // Количество аргументов передаваемых функции
  echo func_num_args();

  // Возвращает массив аргументов функции  
  print_r(func_get_args());

  // Возвращает элемент из списка аргументов
  echo func_get_arg(0); // -> John
}

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

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

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

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

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

<?php
class MyClass {
  // определение свойств
  // определение методов
}
?>

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

<?php
class Car {
  public $year = 2023;
  public $speed;
  public $model;
}

// Иницилизация класса (создание объекта)
$car1 = new Car(); // Объект, он же экземпляр класса
$car2 = new Car();
// Теперь $car1 и $car2 имеют все свойства класса Car
?>

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

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

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

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

  • public (публичный, общедоступный) – позволяет иметь доступ к свойствам и методам класса из любого места;
  • protected (защищённый) – позволяет иметь доступ и родительскому (в котором определен сам член класса), и наследуемым классам;
  • private (закрытый) – ограничивает область видимости тем классом, в котором он объявлен.
<?php
class First {
  public $name = 'Jane';
  protected $age = 37;
  private $sex = 'female';

  public function getInfo(){
    $this->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
class Car {
  // по умолчанию public, т.е. можно не указывать
  public function getSpeed() {
    // $this — указатель на свойство класса
    echo "Скорость = " . $this->speed;
  }
  
  function avgSpeed() {
    'Скорость = ' . $this->getSpeed(); // Обращение к методу
  }
}

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

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

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

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

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

<?php
class User{
  public $name = 'John';
  public $login = 'johndoe';
  public $password = '1234';

  function __construct($name, $login, $password) {
    $this->name = $name;
    $this->login = $login;
    $this->password = $password;
  }

  function __destruct(){ 
    echo '<p><Объект удален!/p>';
  }
}

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

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

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

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

<?php
$myObject = clone $myObject1; // копия (клонирование)
$myObject2 = $myObject1; // ссылка
$myObject2 = &$myObject1; // ссылка
?>

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

<?php
class Car {
  function __construct($mark, $model, $speed) {
    $this->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
// Создание класса
class good {
  public $title;
}

// Наследование класса good
class book extends good {
  public $year;
}

$book1 = new book();
// Нам доступны свойства и методы родительского класса
$book1->year;
$book1->title;
?>

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

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

<?php
class Product {
  public $title;

  function __construct($title) {
    $this->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
class Book extends Good {
  public $year;

  function __construct($title, $year) {
    // Отрабатывает родительский конструктор
    parent::__construct($title);
    // Дополняем конструктор новым свойством
    $this->year = $year;
  }
}

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

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

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

<?php
class Student {
  public $name, $course, $faculty;

  function __construct($name, $course, $faculty) {
    $this->name = $name;
    $this->course = $course;
    $this->faculty = $faculty;
  }
}

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

foreach($student_1 as $key => $value) {
  print "<p>$key: $value</p>";
}
?>

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

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

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

<?php
class Animal {
  const
    eyes = 2, ears = 2, paws = 4, tail = 1; // Объявление констант

  function pawsQuantity() {
    // Доступ к константе внутри класса
    return self::paws;
  }
}

$tiger = new Animal();

// Доступ к константе вне класса
echo Animal::ears;
echo $tiger->pawsQuantity(); // -> 4

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

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

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

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

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

<?php
abstract class DB {
  function db_connect() {
    mysqli_connect('localhost', 'root', 'root', 'eshop');
  }
  
  // Абстрактный метод без реализаций
  abstract function db_query($sql);
  abstract function db_close();
}

class DB_inherit extends DB {
  // Обязательно должен быть продекларирован
  function db_query($sql){}
  function db_close(){}
}

$Schema = new DB(); // Ошибка уровня Fatal error
$Schema = new DB_inherit();
?>

Интерфейсы

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

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

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

<?php
interface DB {
  function db_connect($host, $user, $password, $schema);
  function db_query();
  function db_close();
}

class DB2 implements DB {
  function db_connect($host, $user, $password, $schema){}
  function db_query(){}
  function db_close(){}
}
?>

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

<?php
interface Head {
  function ears();
}

interface Hands {
  function fingers();
}

class Body implements Head, Hands {
  function ears(){}
  function fingers(){};
}
?>

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

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

<?php
class A {
  final function foo(){}
}

class B extends A {
  function foo(){} // нельзя перегружать
}
?>

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

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

<?php
class staticClass {
  static $address, $book_count;
  public $name;

  function __construct() {
    // Обращение к статическому свойству и его инкремент
    self::$address++;
  }

  static function staticFunction($book_name) {
    // Преинкремент статического свойства
    ++self::$book_count;
    $name = $book_name;
  }
}

$book1 = new staticClass();
$book2 = new staticClass();
$book3 = new staticClass();

// Обращение к статическому свойству вне класса
staticClass::$address;
//Обращение к статическому методу вне класса
staticClass::staticFunction('PHP & MySQL: Server-side Web Development');
staticClass::staticFunction('PHP 8 Objects, Patterns, and Practice');
echo staticClass::$book_count; // -> 2
?>

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

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

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

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

<?php
class User {}

class SuperUser extends User {}

function checkObject($object) {
  // Принадлежит ли переданный объект классу
  if ($object instanceOf User) {
    if ($object instanceof SuperUser)
      return 'Данный пользователь обычный пользователь';
    else
      return 'Данный пользователь обладает правами администратора';
  }
  else
    return 'Неизвестный пользователь';
}
?>

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

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

<?php
function __autoload($class) {
  print("Класс $class не описан");
}

$car1 = new car();
?>

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

<?php
function __autoload($class) {
  // Файл где описан класс
  include "$class.class.php";
}
$car1 = new car();
?>

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

Магические методы – это специальные методы, которые переопределяют действие 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
class A {
  public $params = array();

  function __set($name, $value){
    // Присваивание ячейке массива
    $this->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 "<p>$k: $v</p>";
    }
  }
}

$obj = new A;

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

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

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

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

<?php
class A {
  function __call($name, $argument){
    echo "function $name with the next arguments: ",
    implode(', ', $argument), ' does not exist';
  }
}

$obj = new A;
$obj->foo(123, 'milk', 'bread', 'solt'); // Такого метода нет в классе
?>

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

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

<?php
class A {
  function __toString(){
    return 'Это класс "A"';
  }
}

$obj = new A;
// Конвертация объекта, вызов метода __toString()
echo $obj; // -> Это класс "A"
?>

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

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

<?php
class A {
  public function myFunction(){
    echo 'This class is "A"';
  }
}

class B {
  public function myFunction(){
    echo 'This class is "B"';
  }
}

function dereference($object){
  switch($object){
    // Возвращает созданный объект
    case 'A' : return new A;
    case 'B' : return new B;
  }
}

// Вызывается метод динамически созданного объекта
dereference('A')->myFunction(); // -> This class is "A"
?>

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

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

<?php
interface Foo {
  function func1(Foo $foo);
}

interface Bar {
  function func2(Bar $bar);
}

class MyClass implements Foo, Bar {
  public function func1(Foo $foo) {
    // код метода
  }

  public function func2(Bar $bar) {
    // код метода
  }
}

$obj1 = new MyClass;
$obj2 = new MyClass;
$obj1->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

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

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

Чтение Cookie

<?php
// Отправка куки "навсегда" (до 2038 года)
setcookie('cookieName', 'PHP', time() + 0x7FFFFFFF);

echo $_COOKIE['cookieName']; // -> PHP

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

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

<?php
$userInfo = array(
  'name' => 'Jane',
  'age' => 37,
  'e-mail' => 'me@janedoe.com',
  'uri' => 'https://janedoe.com'
);

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

Удаление Cookie

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

<?php setcookie('CookieName'); ?>

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

<?php setcookie('CookieName', ''); ?>

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

<?php setcookie('CookieName', '', time() - 3600); ?>

Сессии

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

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

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

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

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

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

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

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

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

<?php
echo session_name(), '=', session_id;
// -> PHPSESSID=btcii6g2ak26rsvogoov47jr25
?>

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

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

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

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

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

<?php
session_destroy(); // Закрытие сессии
setcookie(session_name(), ''); // Удаление куки сессии
?>

HTTP-заголовки

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

Запрос

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/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 header("Location: https://site.com"); ?>

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

<?php
header("Location: " . $_SERVER['PHP_SELF']);
exit; // Прекращает выполнение текущего скрипта
?>

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

<?php
// Через 3 секунды Вы будете перемещены на главную страницу
header("Refresh: 3; url=https://x.com");
?>

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

<?php
// Передаваемый файл обрабатывать как text/xml с кодировкой utf-8
header("Content-type: text/xml; charset=utf-8");
?>

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

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

<?php
// Повторить запрос с сервера-источника
header('Cache-Control: no-cache');

// Явный запрет на кэширование
header('Cache-Control: no-store');

// Заголовок Expires говорит об актуальности этой страницы 
header('Expires: ' . date('r'));

// Последнее изменение страницы
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');

// Разрешение
header('Cache-Control: public');

// Страница будет актуальна один час
header('Expires: ' . date('r', time() + 3600));
?>

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

<?php
header('Set-Cookie: name=Hello; expires=Wed, 18 Oct 23 15:00:00 GMT');
?>

Файлы

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

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

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

<?php
// Проверяет наличие указанного файла или каталога
file_exists('text.txt');

// Возвращает размер файла
filesize('text.txt');

// Дата последнего обращения к файлу (date("d M Y", $atime))
fileatime('text.txt');

// Возвращает время последнего изменения файла (date("d M Y", $mtime))
filemtime('text.txt');

// Дата создания файла Windows (временная метка Unix)
filectime('text.txt');
?>

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

<?php
$f = fopen('text.txt', 'w+') or die('Файл не найден или еще что-то');

// Открывает файл только для чтения и помещает указатель в начало файла
$f = fopen('http://www.example.com/text.html', 'r');
$f = fopen('http://ftp.example.com/text.html', 'r+');

// Закрывает открытый дескриптор файла
fclose($f);
?>

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

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
$f = fopen('text.txt', 'r+') or exit('Нет файла или другая ошибка');

// Чтение файла на указанную длину
echo fread($f, 9);

// Функция fgets() читает файл построчно
echo fgets($f); // -> строка
echo fgets($f); // -> следующая строка

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

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

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

Запись в файл

<?php
// Получение дескриптора файла
$connect = fopen('write.txt', 'r+');

// Если нужно записать в конец файла,
// то режим функции fopen() 'a' или 'a+'

// Перезапишет слово "Hello" в начале строки
fwrite($connect, 'Hello');

fclose($connect);
?>

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

<?php
$connect = fopen('text.txt', 'r+') or exit;

// Перемещает курсор в конец файла и на 10 символов назад
fseek($connect, -10, SEEK_END);

// Зачитываем эти 10 символов
echo fread($connect, 10);

// Возвращает текущую позицию файлового указателя
ftell($connect);

// Сбрасывает курсор файлового указателя на начало файлового потока
rewind($connect);

// Аналогична rewind($connect);
fseek($connect, 0);

// Проверяет, достигнут ли конец файла
feof($connect);

fclose($connect);
?>

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

<?php
// Возвращает массив где в каждой ячейке своя строка
$myArray = file('text.txt');

// аналогично работе следующего кода
$f = fopen('text.txt', 'r') or die;
while($line = $fgets($f))
  $lines[] = $line;
fclose($f);

// Читает содержимое файла все в одну строку
file_get_contents('text.html');

// Пишет строку в конец файла
file_put_contents('text.txt', "\nНовая строка", FILE_APPEND);
?>

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

<?php
// Перемещение файла text.txt из папки folder1 в папку folder2
rename('folder1/text.txt', 'folder2/text.txt');

// Переименование файла из "text1.txt" в "text2.txt"
rename('text1.txt', 'text2.txt');

// Копирование и переименование
copy('folder1/text.txt', 'folder2/text2.txt');

// Удаление
unlink('folder/text.txt');
?>

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

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

<?php
// Создание вложенной папки в текущей директории
// с самыми широкими правами (0777)
mkdir('./firstCatalog/secondCatalog', 0777, true);

// Переименование
rename("myfolder","newfolder");

// Перемещение
rename("myfolder","newfolder/myfolder");

// Удаление каталога (если он пустой)
rmdir('./newCatalog');
?>

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

<?php
// Открытие текущей директории
$dir = opendir('.');

// Чтение директории
$catalog_or_file = readdir($dir); // -> имя папки или false, если ошибка

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

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

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

<?php
print_r(scandir('.')); // Массив содержимого папки
is_dir('./catalog/folder'); // Это папка?
is_file('./catalog/file.txt'); // Это файл?
?>

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

<?php
$d = opendir('.');
// Пока переменная получает элемент каталога...
while($myDir = readdir($d)) {
  if(is_dir($myDir)) // Если это папка
    echo '<p>Это папка ' . $myDir . '</p>';
  else
    echo '<p>Это файл ', $myDir, '</p>';
}
?>

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

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

Файлы загружаются на сервер только методом POST. При этом атрибут enctype тега <form> должен быть 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 определенное значение:

<form action="upload.php" method="post" enctype="multipart/form-data">
  <input type="file" name="userFile">
  <button type="submit">Послать файл</button>
</form>

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

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

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

<?php
// Реальное имя файла (пример: logo.gif)
$_FILES['значение атрибута name тега input']['name'];

// MIME-тип файла (пример: image/gif или image/jpeg и т.д.)
$_FILES['значение атрибута name тега input']['type'];

// Физический путь к временно переименнованному файлу
$_FILES['значение атрибута name тега input']['tmp_name'];

// Если в ячейке error значение 0, то ошибки нет,
// иначе поле будет содержать номер ошибки
$_FILES['значение атрибута name тега input']['error'];

// Размер файла (как правило в байтах)
$_FILES['значение атрибута name тега input']['size'];
?>

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

<?php
if($_FILES['UserFile']['error'] == 0) {
  // Путь к временному переименнованному файлу
  $temporary_name = $_FILES['UserFile']['tmp_name'];
  
  // Реальное имя файла
  $real_name = $_FILES['UserFile']['name'];
  
  // Перемещение загруженного файла из временной директории
  move_uploaded_file($temporary_name, './folder/' . $real_name);
}
?>

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

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

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

  • SMTP = localhost – адрес SMTP-сервера;
  • sendmail_from = me@localhost.kz – e-mail по умолчанию от кого будет приходить почта.

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

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

<?php
if(mail('me@example.com', 'Тема письма', 'Тело письма')) {
  echo 'Письмо успешно передано почтовому серверу';
  /* При этом заголовок From у получателя будет тот,
  что указан по умолчанию в директиве php.ini
  sendmail_from = me@example.local */
}
?>

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

<?php
mail(
  'me@example.com',
  'Тема письма',
  $message,
  "From: me@$SERVER_NAME\r\n".
  "Reply-To: me@$SERVER_NAME\r\n".
  "X-Mailer: PHP/" . phpversion()
);

// Или можно установить заголовки в одну переменную
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=utf-8\r\n";
$headers .= "From: John Doe <me@example.com>\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

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

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

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

SELECT title
FROM courser
WHERE length > 30

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

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

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

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.

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

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

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 добавить значения в каждое поле.

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

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

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

Запрос DELETE

DELETE FROM lessons -- Из какой таблицы
WHERE lessons.date = '2013-05-17' -- Условие удаления
Важно! Если не передать условие, то удалятся все записи.

Запросы UPDATE

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

MySQL

MySQL – свободная реляционная СУБД распространяемая под лицензией GNU GPL и под собственной коммерческой лицензией. Изначально разрабатывалась в шведской компании MySQL AB. 26 февраля 2008 года компания Sun Microsystems приобрела MySQL AB, а позднее 27 января 2010 года компания Oracle приобрела Sun Microsystems включив MySQL в свою линейку СУБД.

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

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

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

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

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

:: Создать дамп БД
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
// Открывает соединение с сервером MySQL
mysql_connect('адрес сервера', 'login', 'password');

// Выбирает базу данных MySQL
mysql_select_db('db_name', 'идентификатор соединения с MySQL');

// Закрывает соединение с MYSQL
mysql_close([необязательный дескриптор соединения с MySQL]);
?>

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

<?php
mysql_select_db('имя_БД', [дескриптор ресурса]);

// Функции для работы с ошибками MySQL
mysql_errno([указатель ресурса]); // Номер ошибки MySQL
mysql_error([указатель ресурса]); // Описание ошибки

// Пример соединения с БД
mysql_select_db('db') or die(mysql_error());
?>

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

<?php
mysql_query("SET names 'utf8mb4'");

// Рекомендуентся запрос сначала присвоить переменной
$myQuery = 'SELECT * FROM teachers';
// а затем уже её подставлять
$result = mysql_query($myQuery);

mysql_close();
?>

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

<?php
$query_result = mysql_query("SELECT title FROM lessons");

// Индекс-ый и ассоц-ый массив одного ряда таблицы
mysql_fetch_array($query_result, MYSQL_BOTH);
// Индексированный массив одного ряда таблицы
mysql_fetch_row($query_result);
// Ассоциативный массив одного ряда таблицы
mysql_fetch_assoc($query_result);
// Пример вывода имен сотрудников
while($employer = mysql_fetch_assoc($query_result)){
  echo $employer['name'], '<br>';
}

// Точечная выборка из конкретной ячейки
// -> 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
$connect = mysqli_connect(
  'localhost',
  'user_login',
  'password',
  'db_name' // 4-ым параметром передается имя базы данных
); // (нет функции mysql_select_db())
?>

Подробнее в документации MySQL на официальной странице сервера и в документации модуля MySQLi на странице 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.

extension=php_pdo.dll
extension=php_sqlite.dll

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

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

<?php
// Процедурный подход
$connect = sqlite_open('test.db');
sqlite_close($connect); // Закрытие соединения

// Объектно-ориентированный подход
$connect = new SQLiteDatabase('test.db');
unset($connect); // Закрытие соединения

// SQLite3
$connect = new SQLite3('test.db');
unset($connect);
?>

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

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

<?php
// PRIMARY KEY и AUTOINCREMENT
CREATE TABLE users (id INTEGER PRIMARY KEY, name, age)

// Экранировать запросы нужно через функцию
$clear = sqlite_escape_string($sql_query);
?>

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

<?php
function fetchAll(){
  $sql = 'SELECT id, name, email, msg, datetime, ip
          FROM msgs ORDER BY 1 DESC';

  $result = $this->_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
try {
  $res = $this->_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('me@mail.com', 'Тема письма', $error);
  return false; // -> false, если запрос завершился неудачей
}
?>

About

Reference Guide of PHP with MySQL, OOP, and other

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published