Методы в 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