Геттеры и сеттеры
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 40 из 91.
Теперь, когда вы понимаете модификаторы доступа, как безопасно взаимодействовать с приватными свойствами извне класса? Ответ — геттеры и сеттеры — публичные методы, которые обеспечивают контролируемый доступ к приватным данным.
Геттер извлекает значение свойства, в то время как сеттер изменяет его. Этот паттерн позволяет добавить валидацию или логику при доступе к данным или их изменении:
<?php
class User {
private string $email;
private int $age;
public function getEmail(): string {
return $this->email;
}
public function setEmail(string $email): void {
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->email = $email;
}
}
public function getAge(): int {
return $this->age;
}
public function setAge(int $age): void {
if ($age >= 0 && $age <= 150) {
$this->age = $age;
}
}
}
$user = new User();
$user->setEmail("john@example.com");
$user->setAge(25);
echo $user->getEmail() . "\n";
echo $user->getAge();
Вывод:
john@example.com
25Сеттер проверяет формат электронной почты и гарантирует, что возраст является допустимым, перед сохранением значений. Без сеттеров кто угодно мог бы напрямую присвоить некорректные данные. Вы также можете создавать свойства только для чтения, предоставляя только геттер, или свойства только для записи, предоставляя только сеттер.
Ключевой момент: Геттеры и сеттеры дают вам контроль над тем, как осуществляется доступ к приватным данным и их изменение, позволяя выполнять валидацию, форматирование или любую другую пользовательскую логику.
Задание
ЛегкоДавайте создадим систему инвентаризации товаров, которая использует геттеры и сеттеры для защиты и валидации данных о продукте. Вы создадите класс Product, который гарантирует, что цены всегда положительны, а количество на складе никогда не бывает отрицательным — демонстрируя, как сеттеры могут обеспечивать соблюдение бизнес-правил.
Вы организуете свой код в двух файлах:
Product.php— Создайте классProductс тремя приватными свойствами:$name(string),$price(float) и$stock(integer). Реализуйте геттеры и сеттеры для каждого свойства со следующими правилами валидации:setName()должен принимать только непустые строки — если после обрезки пробелов (trimming) строка пуста, не обновляйте свойствоsetPrice()должен принимать только значения больше 0 — отклоняйте нулевые или отрицательные ценыsetStock()должен принимать только значения 0 или больше — отклоняйте отрицательное количество товара
getInfo(), который возвращает"[name]: $[price] ([stock] in stock)"с ценой, отформатированной до 2 знаков после запятой.main.php— Подключите файл Product. Вы получите четыре входных значения: название продукта, цену, количество на складе и новую цену для обновления. Создайте экземплярProductи используйте сеттеры для присвоения начального имени, цены (преобразованной в float) и количества (преобразованного в integer). Выведите результатgetInfo(). Затем попытайтесь обновить цену новым значением цены (преобразованным в float) и снова выведитеgetInfo(). Наконец, попытайтесь установить количество на складе в-5(недопустимое значение) и выведитеgetInfo()еще раз, чтобы подтвердить, что количество не изменилось.
Ваши сеттеры действуют как привратники — они проверяют входящие данные перед тем, как разрешить изменения приватных свойств. Когда передаются недопустимые данные (например, отрицательное количество на складе), сеттер просто игнорирует их, сохраняя существующее допустимое значение нетронутым. В этом заключается сила инкапсуляции: ваш объект сохраняет свою целостность независимо от того, что пытается сделать внешний код.
Шпаргалка
Используйте геттеры и сеттеры для обеспечения контролируемого доступа к приватным свойствам. Геттер извлекает значение, в то время как сеттер изменяет его с возможностью валидации:
<?php
class User {
private string $email;
private int $age;
public function getEmail(): string {
return $this->email;
}
public function setEmail(string $email): void {
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->email = $email;
}
}
public function getAge(): int {
return $this->age;
}
public function setAge(int $age): void {
if ($age >= 0 && $age <= 150) {
$this->age = $age;
}
}
}
$user = new User();
$user->setEmail("john@example.com");
$user->setAge(25);
echo $user->getEmail(); // john@example.com
echo $user->getAge(); // 25
Сеттеры могут проверять данные перед их сохранением. Если валидация не проходит, сеттер может проигнорировать обновление, сохраняя существующее значение нетронутым. Вы можете создавать свойства только для чтения, предоставляя только геттер, или свойства только для записи, предоставляя только сеттер.
Попробуйте сами
<?php
require_once 'Product.php';
// Чтение входных данных
$name = trim(fgets(STDIN));
$price = trim(fgets(STDIN));
$stock = trim(fgets(STDIN));
$newPrice = trim(fgets(STDIN));
// TODO: Создать новый экземпляр Product
// TODO: Использовать сеттеры для назначения начального имени, цены (как float) и остатка (как integer)
// TODO: Вывести результат getInfo()
// TODO: Обновить цену на newPrice (как float) и снова вывести getInfo()
// TODO: Попытаться установить остаток на -5 (недопустимо) и вывести getInfo(), чтобы подтвердить, что остаток не изменился
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Итоги — Простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыИтоги — Иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateПодробный разбор модификаторов доступаГеттеры и сеттерыСокрытие данныхConstructor Promotion (8.0)Итоги — Система учета студентов10Продвинутые концепции ООП
Композиция против наследованияВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы13Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий2Пространства имен и автозагрузка
Введение в пространства именКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerИтоги: структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс против абстрактного классаType Hinting с интерфейсамиИтоги — Калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeИтоги — Кастомная коллекция11Система типов и обработка ошибок
Объявление типовNullable-типыТипы объединения и пересеченияКлассы исключенийИерархия пользовательских исключенийTry, Catch, FinallyИтоги — Валидатор форм14Проект: Управление библиотекой
Обзор проектаКлассы Book и User3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищенные свойстваСвойства Readonly (PHP 8.1)Итоги — Менеджер банковского счета6Полиморфизм
Снова о переопределении методовПолиморфизм через интерфейсыType Hinting и Union TypesПозднее статическое связываниеИтоги — Payment Processor9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy