🐘 PHP
Полный справочник: типы и строгая типизация, строки, массивы, функции, ООП, enum, исключения, PDO и безопасность, формы и сессии, Composer, тесты и экосистема.
Шпаргалки · Программирование · #php #web #backend #laravel
Запуск и окружение
php file.php php -S localhost:8000 -t public php -v php -m # модули
composer init / require guzzlehttp/guzzle / install / update / dump-autoload
php artisan serve # Laravel; bin/console # Symfony
IDE: PhpStorm, VS Code (Intelephense). Версии: 8.2–8.4 актуальны. Стандарты: PSR-1/12 (стиль), PSR-4 (автозагрузка), PSR-7/15 (HTTP). Анализ и стиль: PHPStan, Psalm, PHP-CS-Fixer, Pint.
Основы
<?php
declare(strict_types=1); // строгая типизация скалярных типов
$name = 'Аня'; // переменные начинаются с $
echo "Привет, $name! {$user['id']}\n"; // двойные кавычки подставляют переменные
define('MAX', 10); const MIN = 1;
var_dump($x); print_r($arr); dd($x); // отладка (dd в Laravel)
Комментарии: //, #, /* */, документация /** */. Теги <?php ... ?>, в чистых PHP-файлах закрывающий тег не нужен.
Типы данных
| Тип | Пример |
|---|---|
int, float |
42, 3.14, 0x1A, 1_000_000 |
string |
'a', "b $x", heredoc <<<EOT |
bool, null |
true, null |
array |
[1, 2], ['a' => 1] |
object, callable, iterable, mixed, never, void |
gettype($x); is_int($x); is_numeric('12.5'); (int)'12abc'; (string)5; intval('42'); floatval('1.5');
$x ?? 'по умолчанию'; $x ??= 5; $obj?->prop?->method();
empty('0'); isset($a['k']); array_key_exists('k', $a);
Ложные значения: false, 0, 0.0, '', '0', [], null. Сравнивайте ===, а не == ('abc' == 0 в старых версиях истинно; 0 == 'a' изменилось в PHP 8).
Операторы
+ - * / % **, . (склейка), == === != !== <=> < >, && || ! and or xor, ??, ?:, ?->, instanceof, ... (spread), => (в массивах и стрелочных функциях).
Строки
strlen($s); mb_strlen($s); // для UTF-8 используйте mb_*
str_contains($s, 'x'); str_starts_with($s, 'p'); str_ends_with($s, 's');
strpos($s, 'x'); substr($s, 1, 3); mb_substr($s, 0, 5);
strtoupper($s); mb_strtoupper($s); ucfirst($s); trim($s); str_replace('a', 'b', $s);
explode(',', $s); implode(', ', $arr); sprintf('%05.2f %s', 3.14159, 'x'); number_format(1234.5, 2, ',', ' ');
preg_match('/(\d+)/', $s, $m); preg_replace('/\s+/', ' ', $s); preg_split('/,\s*/', $s);
htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); // экранирование для HTML
md5($s); hash('sha256', $s); password_hash($pw, PASSWORD_DEFAULT); password_verify($pw, $hash);
Массивы
$a = [3, 1, 2];
$a[] = 4; array_push($a, 5); array_pop($a); array_shift($a); array_unshift($a, 0); count($a);
sort($a); rsort($a); usort($a, fn($x, $y) => $x <=> $y); asort($m); ksort($m);
array_map(fn($x) => $x * 2, $a); array_filter($a, fn($x) => $x > 1); array_reduce($a, fn($c, $x) => $c + $x, 0);
array_keys($m); array_values($m); array_merge($a, $b); [...$a, ...$b]; array_slice($a, 1, 2); array_splice($a, 1, 1);
in_array(2, $a, true); array_search(2, $a); array_unique($a); array_reverse($a); array_sum($a); array_column($rows, 'name', 'id');
array_combine($keys, $vals); array_flip($m); array_chunk($a, 2); array_fill(0, 3, 0); range(1, 5); compact('a', 'b'); extract($m);
['a' => $x, 'b' => $y] = $m; [$p, $q] = [1, 2];
Массив это и список, и словарь. Передаётся по значению (копирование при изменении), для ссылки: &$arr.
Условия и циклы
if ($x > 0) {} elseif ($x === 0) {} else {}
$r = match (true) { $x < 0 => 'минус', $x === 0 => 'ноль', default => 'плюс' }; // 8.0+, строгое сравнение, исчерпывающее
switch ($d) { case 1: break; default: break; }
for ($i = 0; $i < 3; $i++) {}
foreach ($arr as $k => $v) {} foreach ($arr as &$v) {} unset($v);
while ($cond) {} do {} while ($cond); break 2; continue;
Функции
function add(int $a, int $b = 0, int ...$rest): int { return $a + $b + array_sum($rest); }
add(b: 2, a: 1); // именованные аргументы (8.0)
$mul = fn($x) => $x * $factor; // стрелочная, захватывает внешние переменные
$f = function ($x) use ($y, &$z) { }; // замыкание
function gen() { yield 1; yield 2; } // генератор
function nullable(?string $s = null): ?int {}
function u(int|string $v): static {} // union types
$callable = strlen(...); // first-class callable (8.1)
Классы и ООП
interface Repo { public function find(int $id): ?User; }
trait Loggable { public function log(string $m): void { echo $m; } }
enum Status: string { // 8.1
case Active = 'active'; case Blocked = 'blocked';
public function label(): string { return ucfirst($this->value); }
}
final class User implements JsonSerializable
{
use Loggable;
public const ROLE = 'user';
private static int $count = 0;
public function __construct(
public readonly int $id, // property promotion (8.0), readonly (8.1)
private string $name,
protected ?string $email = null,
) { self::$count++; }
public function getName(): string { return $this->name; }
public static function count(): int { return self::$count; }
public function jsonSerialize(): array { return ['id' => $this->id, 'name' => $this->name]; }
public function __toString(): string { return $this->name; }
}
readonly class Money { public function __construct(public int $amount) {} } // 8.2
abstract class Base { abstract protected function run(): void; }
$u = new User(1, 'Аня'); $u instanceof User; User::class; static::create();
Магия: __get, __set, __call, __invoke, __clone. Видимость: public, protected, private. Немутабельные объекты и DTO предпочтительнее.
Исключения и ошибки
try { risky(); }
catch (InvalidArgumentException | RuntimeException $e) { echo $e->getMessage(); }
catch (Throwable $e) { error_log((string)$e); throw $e; }
finally { }
throw new DomainException('сообщение', 422, $previous);
set_error_handler(fn($no, $str, $file, $line) => throw new ErrorException($str, 0, $no, $file, $line));
Error (фатальные, TypeError, ValueError) и Exception реализуют Throwable.
Файлы и JSON
file_get_contents('a.txt'); file_put_contents('a.txt', $s, FILE_APPEND | LOCK_EX); file_exists('a.txt'); unlink('a.txt');
$fh = fopen('a.csv', 'r'); while (($row = fgetcsv($fh)) !== false) {} fclose($fh);
json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
json_decode($json, true, 512, JSON_THROW_ON_ERROR);
mkdir($dir, 0755, true); scandir($dir); glob('*.php'); pathinfo($p); realpath($p); basename($p);
Работа с базой (PDO) и безопасность
$pdo = new PDO('pgsql:host=localhost;dbname=app', $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
$st = $pdo->prepare('SELECT * FROM users WHERE email = :email AND active = :a');
$st->execute(['email' => $email, 'a' => 1]);
$rows = $st->fetchAll(); $row = $st->fetch(); $pdo->lastInsertId();
$pdo->beginTransaction(); $pdo->commit(); $pdo->rollBack();
Никогда не склеивайте SQL из пользовательских данных: только подготовленные запросы (защита от SQL-инъекции). Дальше: htmlspecialchars при выводе (XSS), CSRF-токены, password_hash, HTTPS, session_regenerate_id() после входа, проверка типов и filter_var($e, FILTER_VALIDATE_EMAIL).
Веб: запрос, сессии, ответ
$_GET['q']; $_POST['name']; $_SERVER['REQUEST_METHOD']; $_FILES['f']; $_COOKIE['c']; php://input
$body = json_decode(file_get_contents('php://input'), true);
session_start(); $_SESSION['uid'] = 1; session_destroy();
header('Content-Type: application/json'); http_response_code(201); header('Location: /home'); exit;
setcookie('c', 'v', ['expires' => time() + 3600, 'httponly' => true, 'secure' => true, 'samesite' => 'Lax']);
Конфигурация: php.ini (memory_limit, upload_max_filesize, display_errors=Off в продакшене), .env через vlucas/phpdotenv. Серверы: Nginx + PHP-FPM, Apache, RoadRunner, FrankenPHP, Swoole.
Асинхронность
Классическая модель синхронная, один запрос на процесс. Асинхронность: Fibers (8.1), ReactPHP, AMPHP, Swoole / OpenSwoole, очереди (Laravel Queue, Symfony Messenger, RabbitMQ).
Тесты и качество
final class CalcTest extends PHPUnit\Framework\TestCase
{
#[PHPUnit\Framework\Attributes\DataProvider('cases')]
public function testAdd(int $a, int $b, int $exp): void { $this->assertSame($exp, add($a, $b)); }
public static function cases(): array { return [[1, 2, 3], [0, 0, 0]]; }
}
Pest (it('adds', fn() => expect(add(1, 2))->toBe(3));), PHPUnit, Mockery, Behat. Запуск vendor/bin/phpunit.
Подводные камни
==с неожиданными приведениями: используйте===.strlenиsubstrна UTF-8:mb_*.- Порядок
foreachпо ссылке:unset($v). empty('0')истинно.- Отсутствие
declare(strict_types=1). - Ошибки не должны выводиться пользователю.
includeпропущенных файлов: автозагрузка Composer.
Экосистема по задачам
| Задача | Что взять |
|---|---|
| Фреймворки | Laravel, Symfony, Slim, Yii, CodeIgniter |
| CMS | WordPress, Drupal, Joomla, October |
| ORM | Eloquent, Doctrine, Cycle ORM |
| HTTP-клиент | Guzzle, Symfony HttpClient |
| Шаблоны | Blade, Twig |
| Очереди | Laravel Horizon, Symfony Messenger, php-amqplib |
| Логи | Monolog |
| Валидация | symfony/validator, Respect |
| Тесты | PHPUnit, Pest, Mockery |
| Анализ | PHPStan, Psalm, Rector |