Методы в PHP: синтаксис, область видимости и примеры

Раздел: Программирование на PHP -> Общие сведения о методах

Синтаксис методов в PHP

Метод это функция, объявленная внутри класса. Основной синтаксис включает модификатор доступа (public, protected, private), ключевое слово function, имя метода, круглые скобки с параметрами и тело в фигурных скобках.

<?php
class Sample {
    public function doSomething($param) {
        // ...
    }
}
?>

методы php (методы в php)

Если модификатор не указан, по умолчанию используется public. Метод вызывается через экземпляр: $obj->doSomething($value).

Как объявить метод с параметрами по умолчанию?

Параметры могут иметь значения по умолчанию. Они обязательно следуют после обязательных параметров.

<?php
class Greeter {
    public function sayHello($name, $greeting = 'Hello') {
        return "$greeting, $name!";
    }
}
?>

Типичная ошибка:

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

<?php
// Ошибка
public function sayHello($greeting = 'Hello', $name) { ... }
?>

Как указать тип параметра и возвращаемого значения?

Начиная с PHP 5 для типов классов, с PHP 7 для скалярных типов. Для включения строгой типизации используется declare(strict_types=1).

<?php
class Math {
    public function multiply(int $x, int $y): int {
        return $x * $y;
    }
}
?>

Проблема несоответствия типов:

При строгой типизации передача строки вместо числа вызывает TypeError.

<?php
declare(strict_types=1);
$math = new Math();
// $math->multiply("2", 3); // TypeError
?>

Как объявить метод с переменным числом аргументов?

Используется оператор ... перед последним параметром. Все переданные значения собираются в массив.

<?php
class Logger {
    public function log(...$messages) {
        foreach ($messages as $msg) {
            echo $msg . "\n";
        }
    }
}
?>

Распространенная ошибка:

Передача аргументов по одному не вызовет проблем, но если нужно передать массив как набор аргументов, используется распаковка: $log->log(...$array).

Как сделать метод статическим?

Статический метод принадлежит классу, а не экземпляру. Вызывается через ::.

<?php
class Utils {
    public static function welcome($name) {
        return "Welcome, $name";
    }
}
echo Utils::welcome('Alex');
?>

Типичная ошибка:

Попытка вызвать нестатический метод статически ($class::method()) вызовет уведомление в PHP 7 и фатальную ошибку в PHP 8.

Как использовать магические методы __get и __set?

Магические методы автоматически вызываются при обращении к недоступным свойствам. __get принимает имя свойства, __set – имя и значение.

<?php
class Data {
    private $data = [];
    public function __get($name) {
        return $this->data[$name] ?? null;
    }
    public function __set($name, $value) {
        $this->data[$name] = $value;
    }
}
$d = new Data();
$d->name = 'John';
echo $d->name;
?>

Проблема рекурсии:

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

Как объявить абстрактный метод?

Абстрактный метод объявляется в абстрактном классе без реализации. Подкласс обязан его реализовать.

<?php
abstract class Animal {
    abstract public function speak(): string;
}
class Dog extends Animal {
    public function speak(): string {
        return 'Bark';
    }
}
?>

Ошибка:

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

Как определить метод интерфейса?

Интерфейс содержит только объявления методов (без тела). Класс, реализующий интерфейс, обязан предоставить реализацию.

<?php
interface Flyable {
    public function fly(): void;
}
class Bird implements Flyable {
    public function fly(): void {
        echo "Flying";
    }
}
?>

Несовместимость типов:

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

Как использовать методы в трейтах?

Трейты позволяют повторно использовать методы в нескольких классах. Метод трейта может быть переопределён в классе.

<?php
trait Logger {
    public function log($msg) {
        echo "Log: $msg";
    }
}
class User {
    use Logger;
}
$user = new User();
$user->log('test');
?>

Конфликт методов:

Если два трейта имеют метод с одинаковым именем, нужно разрешить конфликт с помощью insteadof или as.

Как возвращать void из метода?

Начиная с PHP 7.1 можно указать тип void. Метод не возвращает значение (или возвращает null).

<?php
class Printer {
    public function printMessage(string $msg): void {
        echo $msg;
    }
}
?>

Ошибка при попытке вернуть значение:

Если метод с типом void пытается вернуть что-либо, кроме null, возникает TypeError.

Расширенные примеры использования методов

Fluent interface (цепочка методов)

Методы возвращают $this, что позволяет вызывать их последовательно.

Пример
<?php
class QueryBuilder {
    private $query = '';
    public function select($fields): self {
        $this->query = "SELECT $fields";
        return $this;
    }
    public function from($table): self {
        $this->query .= " FROM $table";
        return $this;
    }
    public function where($condition): self {
        $this->query .= " WHERE $condition";
        return $this;
    }
    public function getQuery(): string {
        return $this->query;
    }
}
$query = (new QueryBuilder())
    ->select('id, name')
    ->from('users')
    ->where('active = 1')
    ->getQuery();
echo $query;
?>
SELECT id, name FROM users WHERE active = 1

Метод, возвращающий static для позднего статического связывания

Используется в паттерне Builder для поддержки наследования.

Пример
<?php
class BaseBuilder {
    protected $parts = [];
    public function addPart($part): static {
        $this->parts[] = $part;
        return $this;
    }
}
class ExtendedBuilder extends BaseBuilder {
    public function build(): string {
        return implode(', ', $this->parts);
    }
}
$builder = new ExtendedBuilder();
$result = $builder->addPart('A')->addPart('B')->build();
echo $result;
?>
A, B

Использование match в методе (PHP 8)

match может быть возвращаемым выражением.

Пример
<?php
class HttpStatus {
    public function getMessage(int $code): string {
        return match ($code) {
            200 => 'OK',
            404 => 'Not Found',
            500 => 'Internal Server Error',
            default => 'Unknown'
        };
    }
}
$status = new HttpStatus();
echo $status->getMessage(404);
?>
Not Found

Метод с атрибутами (PHP 8)

Атрибуты добавляют метаданные. Можно получить их через Reflection.

Пример
<?php
#[\Attribute]
class Route {
    public function __construct(public string $path) {}
}

class UserController {
    #[Route('/users')]
    public function list() {
        echo 'User list';
    }
}

$ref = new ReflectionMethod(UserController::class, 'list');
$attrs = $ref->getAttributes(Route::class);
foreach ($attrs as $attr) {
    $route = $attr->newInstance();
    echo $route->path;
}
?>
/users

Метод с union типом и mixed (PHP 8)

Параметр или возвращаемое значение может быть одним из нескольких типов.

Пример
<?php
class Parser {
    public function parse(int|string $input): int|float {
        if (is_string($input)) {
            return strlen($input);
        }
        return $input / 2;
    }
}
$parser = new Parser();
echo $parser->parse('hello') . ' ' . $parser->parse(10);
?>
5 5

Генератор с yield в методе

Метод может быть генератором, возвращающим итератор.

Пример
<?php
class RangeGenerator {
    public function generate(int $start, int $end): \Generator {
        for ($i = $start; $i <= $end; $i++) {
            yield $i;
        }
    }
}
$gen = new RangeGenerator();
foreach ($gen->generate(1, 3) as $number) {
    echo $number . ' ';
}
?>
1 2 3

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

Можно создать объект с методом на лету.

Пример
<?php
$obj = new class {
    public function greet($name) {
        return "Hi, $name!";
    }
};
echo $obj->greet('Alice');
?>
Hi, Alice!

Использование ReflectionMethod для анализа метода

Получение информации о методе во время выполнения.

Пример
<?php
class Test {
    private function secret($a, $b = 1) {}
}
$ref = new ReflectionMethod(Test::class, 'secret');
echo 'Модификатор: ' . $ref->isPrivate() . '\n';
echo 'Кол-во параметров: ' . $ref->getNumberOfParameters() . '\n';
?>
Модификатор: 1
Кол-во параметров: 2

Методы в PHP - comments

En
методы php (php)