Перейти к содержимому

8. Функции

Иллюстрация к уроку

Функции — это переиспользуемые блоки кода. Они помогают организовать программу, избежать дублирования и упростить тестирование.

  • DRY принцип (Don’t Repeat Yourself) — не повторяйся
  • Модульность — код разбит на логические части
  • Тестируемость — каждую функцию можно протестировать отдельно
  • Читаемость — функции с хорошими именами документируют код
<?php
// Простейшая функция
function sayHello() {
echo "Привет!";
}
sayHello(); // Привет!
// Функция с параметрами
function greet($name) {
echo "Привет, $name!";
}
greet("Иван"); // Привет, Иван!
// Функция с возвратом значения
function add($a, $b) {
return $a + $b;
}
$result = add(5, 3);
echo $result; // 8
?>
```text
### Параметры по умолчанию
```php
<?php
function greet($name = "Гость", $greeting = "Привет") {
return "$greeting, $name!";
}
echo greet(); // Привет, Гость!
echo greet("Иван"); // Привет, Иван!
echo greet("Мария", "Доброе утро"); // Доброе утро, Мария!
?>
```text
### Именованные аргументы (PHP 8+)
```php
<?php
function createUser($name, $email, $age, $role = 'user') {
return [
'name' => $name,
'email' => $email,
'age' => $age,
'role' => $role
];
}
// Обычный вызов
$user1 = createUser("Иван", "[email protected]", 25);
// Именованные аргументы (PHP 8+)
$user2 = createUser(
name: "Мария",
age: 30,
role: "admin"
);
// Можно менять порядок
$user3 = createUser(
age: 28,
name: "Петр",
);
?>
```text
## Type Hints и Return Types
### Скалярные типы (PHP 7+)
```php
<?php
declare(strict_types=1);
function calculateTax(float $amount, float $rate): float {
return $amount * $rate;
}
$tax = calculateTax(1000.00, 0.20);
echo $tax; // 200.0
// Строгая типизация
// calculateTax("1000", 0.20); // TypeError!
?>
```text
### Составные типы
```php
<?php
declare(strict_types=1);
function getUserData(int $id): array {
return [
'id' => $id,
'name' => 'User_' . $id,
'email' => "user{$id}@example.com"
];
}
function formatUser(array $user): string {
return "{$user['name']} ({$user['email']})";
}
$user = getUserData(42);
echo formatUser($user);
?>
```text
### Nullable types (PHP 7.1+)
```php
<?php
declare(strict_types=1);
function findUserByEmail(?string $email): ?array {
if ($email === null) {
return null;
}
// Поиск пользователя...
if ($email === "[email protected]") {
return ['name' => 'Admin', 'email' => $email];
}
return null; // Не найден
}
$user = findUserByEmail(null); // null
$admin = findUserByEmail("[email protected]"); // array
?>
```text
### Union types (PHP 8+)
```php
<?php
function processId(int|string $id): string {
if (is_int($id)) {
return "ID: " . $id;
}
return "Slug: " . $id;
}
echo processId(42); // ID: 42
echo processId("home"); // Slug: home
// Несколько типов возврата
function getData(string $key): array|string|null {
$data = [
'config' => ['theme' => 'dark'],
'title' => 'My Site'
];
return $data[$key] ?? null;
}
?>
```text
## Область видимости переменных
### Глобальные переменные
```php
<?php
$globalVar = "Я глобальная";
function test() {
// ❌ Не работает
// echo $globalVar; // Undefined variable
// ✅ Используем global
global $globalVar;
echo $globalVar;
}
test(); // Я глобальная
// Альтернатива: $GLOBALS
function test2() {
echo $GLOBALS['globalVar'];
}
?>
```text
### Статические переменные
```php
<?php
function counter() {
static $count = 0; // Сохраняется между вызовами
$count++;
return $count;
}
echo counter(); // 1
echo counter(); // 2
echo counter(); // 3
// Практический пример: генерация уникальных ID
function generateId() {
static $id = 0;
return ++$id;
}
echo generateId(); // 1
echo generateId(); // 2
?>
```text
## Передача параметров
### По значению (по умолчанию)
```php
<?php
function increment($num) {
$num++;
echo "Внутри функции: $num
";
}
$value = 5;
increment($value); // Внутри функции: 6
echo $value; // 5 (не изменилось!)
?>
```text
### По ссылке
```php
<?php
function increment(&$num) {
$num++;
echo "Внутри функции: $num
";
}
$value = 5;
increment($value); // Внутри функции: 6
echo $value; // 6 (изменилось!)
// Практический пример
function addTax(&$price, $taxRate) {
$price = $price * (1 + $taxRate);
}
$productPrice = 1000;
addTax($productPrice, 0.20);
echo $productPrice; // 1200
?>
```text
## Вариативные функции
### Переменное количество аргументов
```php
<?php
// Старый способ: func_get_args()
function sum_old() {
$args = func_get_args();
return array_sum($args);
}
echo sum_old(1, 2, 3, 4, 5); // 15
// Новый способ: ... оператор (PHP 5.6+)
function sum(...$numbers) {
return array_sum($numbers);
}
echo sum(1, 2, 3, 4, 5); // 15
echo sum(10, 20); // 30
// Смешивание с обычными параметрами
function formatList(string $separator, ...$items) {
return implode($separator, $items);
}
echo formatList(", ", "яблоко", "банан", "апельсин");
// яблоко, банан, апельсин
?>
```text
### Распаковка массивов
```php
<?php
function add($a, $b, $c) {
return $a + $b + $c;
}
$numbers = [1, 2, 3];
echo add(...$numbers); // 6 (распаковка)
// То же что
echo add($numbers[0], $numbers[1], $numbers[2]);
?>
```text
## Анонимные функции (Closures)
### Базовое использование
```php
<?php
// Анонимная функция
$greet = function($name) {
return "Привет, $name!";
};
echo $greet("Иван"); // Привет, Иван!
// Передача как callback
$numbers = [1, 2, 3, 4, 5];
$squared = array_map(function($n) {
return $n * $n;
}, $numbers);
print_r($squared); // [1, 4, 9, 16, 25]
?>
```text
### Замыкания и use
```php
<?php
$message = "Привет";
$greet = function($name) use ($message) {
return "$message, $name!";
};
echo $greet("Иван"); // Привет, Иван!
// Изменение внешней переменной
$counter = 0;
$increment = function() use (&$counter) {
$counter++;
};
$increment();
$increment();
echo $counter; // 2
?>
```text
## Стрелочные функции (PHP 7.4+)
```php
<?php
// Обычная анонимная функция
$multiply = function($x, $y) {
return $x * $y;
};
// Стрелочная функция (короче!)
$multiply = fn($x, $y) => $x * $y;
echo $multiply(5, 3); // 15
// Автоматический use (не нужен!)
$factor = 10;
// Старый способ
$scale_old = function($n) use ($factor) {
return $n * $factor;
};
// Новый способ
$scale = fn($n) => $n * $factor;
echo $scale(5); // 50
// С array_map
$numbers = [1, 2, 3, 4, 5];
$doubled = array_map(fn($n) => $n * 2, $numbers);
print_r($doubled); // [2, 4, 6, 8, 10]
?>
```text
## Рекурсия
### Факториал
```php
<?php
function factorial($n) {
if ($n <= 1) {
return 1;
}
return $n * factorial($n - 1);
}
echo factorial(5); // 120 (5! = 5*4*3*2*1)
?>
```text
### Числа Фибоначчи
```php
<?php
function fibonacci($n) {
if ($n <= 1) {
return $n;
}
return fibonacci($n - 1) + fibonacci($n - 2);
}
for ($i = 0; $i < 10; $i++) {
echo fibonacci($i) . " ";
}
// 0 1 1 2 3 5 8 13 21 34
?>
```text
### Обход дерева директорий
```php
<?php
function scanDirectory($dir, $prefix = "") {
$files = scandir($dir);
foreach ($files as $file) {
if ($file === '.' || $file === '..') continue;
$path = $dir . '/' . $file;
echo $prefix . $file . "
";
if (is_dir($path)) {
scanDirectory($path, $prefix . " "); // Рекурсия
}
}
}
scanDirectory("./my_folder");
?>
```text
## Встроенные функции PHP
### Работа со строками
```php
<?php
$str = "Hello, World!";
strlen($str); // 13 (длина)
strtoupper($str); // "HELLO, WORLD!"
strtolower($str); // "hello, world!"
str_replace("World", "PHP", $str); // "Hello, PHP!"
substr($str, 0, 5); // "Hello"
strpos($str, "World"); // 7 (позиция)
?>
```text
### Работа с массивами
```php
<?php
$arr = [1, 2, 3, 4, 5];
count($arr); // 5
array_sum($arr); // 15
array_product($arr); // 120
max($arr); // 5
min($arr); // 1
array_reverse($arr); // [5, 4, 3, 2, 1]
array_unique([1,1,2,3]); // [1, 2, 3]
?>
```text
### Работа с датой/временем
```php
<?php
echo date("Y-m-d H:i:s"); // 2024-02-17 15:30:45
echo time(); // 1708180245 (timestamp)
echo strtotime("+1 week"); // timestamp через неделю
echo date("d.m.Y", strtotime("2024-12-31"));
?>
```text
## WordPress контекст
### Hooks (actions и filters)
```php
<?php
// Action hook
function my_custom_footer() {
echo "<p>© 2024 Мой сайт</p>";
}
add_action('wp_footer', 'my_custom_footer');
// Filter hook
function modify_title($title) {
return $title . " | Мой сайт";
}
add_filter('the_title', 'modify_title');
// Удаление hook
remove_action('wp_head', 'wp_generator');
?>
```text
### Кастомные функции темы
```php
<?php
// functions.php темы
// Регистрация меню
function register_my_menus() {
register_nav_menus([
'header-menu' => 'Главное меню',
'footer-menu' => 'Меню в футере'
]);
}
add_action('init', 'register_my_menus');
// Поддержка миниатюр
function theme_setup() {
add_theme_support('post-thumbnails');
add_theme_support('title-tag');
add_theme_support('custom-logo');
}
add_action('after_setup_theme', 'theme_setup');
// Загрузка стилей и скриптов
function enqueue_assets() {
wp_enqueue_style('main-style', get_stylesheet_uri());
wp_enqueue_script('main-js', get_template_directory_uri() . '/js/main.js', [], '1.0', true);
}
add_action('wp_enqueue_scripts', 'enqueue_assets');
?>
```text
### Кастомные типы постов
```php
<?php
function register_product_post_type() {
$args = [
'labels' => [
'name' => 'Товары',
'singular_name' => 'Товар',
'add_new' => 'Добавить товар',
'add_new_item' => 'Добавить новый товар',
'edit_item' => 'Редактировать товар'
],
'public' => true,
'has_archive' => true,
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
'menu_icon' => 'dashicons-products',
'rewrite' => ['slug' => 'products']
];
register_post_type('product', $args);
}
add_action('init', 'register_product_post_type');
?>
```text
### Shortcodes
```php
<?php
// Простой shortcode
function hello_shortcode() {
return "Привет из shortcode!";
}
add_shortcode('hello', 'hello_shortcode');
// Использование: [hello]
// Shortcode с параметрами
function button_shortcode($atts) {
$atts = shortcode_atts([
'text' => 'Нажми меня',
'url' => '#',
'color' => 'blue'
], $atts);
return '<a href="' . esc_url($atts['url']) . '" class="btn btn-' . $atts['color'] . '">' .
esc_html($atts['text']) . '</a>';
}
add_shortcode('button', 'button_shortcode');
// Использование: [button text="Купить" url="/cart" color="green"]
// Shortcode с контентом
function box_shortcode($atts, $content = null) {
return '<div class="box">' . do_shortcode($content) . '</div>';
}
add_shortcode('box', 'box_shortcode');
// Использование: [box]Текст внутри бокса[/box]
?>
```text
## Практика
### Задание 1: Калькулятор
Создайте набор функций для математических операций:
```php
<?php
function add($a, $b) {
return $a + $b;
}
function subtract($a, $b) {
return $a - $b;
}
function multiply($a, $b) {
return $a * $b;
}
function divide($a, $b) {
if ($b == 0) {
return "Ошибка: деление на ноль";
}
return $a / $b;
}
// Использование
echo add(10, 5); // 15
echo subtract(10, 5); // 5
echo multiply(10, 5); // 50
echo divide(10, 5); // 2
?>
```text
### Задание 2: Валидация email
Создайте функцию валидации email с различными проверками.
### Задание 3: Генератор slug
Создайте функцию, которая преобразует заголовок в URL-friendly slug.
```php
<?php
function createSlug($text) {
// Транслитерация
$text = transliterate($text);
// В нижний регистр
$text = strtolower($text);
// Замена пробелов на дефисы
$text = str_replace(' ', '-', $text);
// Удаление спецсимволов
$text = preg_replace('/[^a-z0-9-]/', '', $text);
// Удаление множественных дефисов
$text = preg_replace('/-+/', '-', $text);
// Убрать дефисы в начале и конце
$text = trim($text, '-');
return $text;
}
echo createSlug("Привет, Мир! Это тест."); // privet-mir-eto-test
?>
```text
### Задание 4: Фильтрация массива
Создайте функции для фильтрации массива по различным критериям.
### Задание 5: WordPress шорткод
Создайте свой shortcode для WordPress с параметрами.
## Онлайн-редакторы
Тестируйте примеры:
- **PHPSandbox**: https://phpsandbox.io/
- **3v4l**: https://3v4l.org/
## Итоги
В этом уроке вы изучили:
✅ **Объявление функций** — синтаксис и параметры
✅ **Type hints** — строгая типизация (PHP 7+)
✅ **Область видимости** — global, static, local
✅ **Передача параметров** — по значению и по ссылке
✅ **Анонимные функции** — closures и стрелочные функции
✅ **Рекурсия** — функции, вызывающие сами себя
✅ **WordPress hooks** — actions и filters
✅ **Shortcodes** — создание кастомных шорткодов
### Следующий шаг
Переходите к изучению массивов: [Массивы](/php/arrays/)
### Ключевые моменты
1. **Функции делают код переиспользуемым** — DRY принцип
2. **Используйте type hints** — меньше ошибок
3. **Именованные аргументы** — читабельность (PHP 8+)
4. **Стрелочные функции** — короче код (PHP 7.4+)
5. **WordPress hooks** — основа расширяемости WP
**Совет:** Пишите небольшие функции с одной ответственностью — они проще тестировать и поддерживать!
---
**Готовы двигаться дальше?** Переходите к следующему уроку: [Массивы](/php/arrays/)