Menu
Coddy logo textTech

Геттеры и сеттеры

Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy. Урок 40 из 91.

Теперь, когда вы понимаете модификаторы доступа, как безопасно взаимодействовать с private-свойствами из-за пределов класса? Ответ — getters and setters — public-методы, которые обеспечивают контролируемый доступ к private-данным.

getter получает значение свойства, а сеттер изменяет его. Этот шаблон позволяет добавлять проверку или логику при доступе к данным или их изменении:

<?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

Сеттер проверяет формат email и убеждается, что age имеет разумное значение, прежде чем сохранить эти значения. Без сеттеров любой мог бы напрямую присвоить недопустимые данные. Вы также можете создать свойства только для чтения, предоставив лишь getter, или свойства только для записи, используя лишь сеттер.

Ключевой момент: getter и сеттеры дают вам контроль над тем, как осуществляется доступ к private данным и их изменение, позволяя выполнять проверку, форматирование или любую пользовательскую логику.

challenge icon

Задание

Легко

Давайте создадим систему учёта товаров, которая использует геттеры и сеттеры для защиты и проверки данных о товарах. Вы создадите класс Product, который гарантирует, что цены всегда положительны, а количества на складе никогда не отрицательны: это демонстрирует, как сеттеры могут обеспечивать соблюдение бизнес-правил.

Вы организуете код в двух файлах:

  • Product.php: Создайте класс Product с тремя private-свойствами: $name (строка), $price (float) и $stock (integer). Implement геттеры и сеттеры для каждого свойства со следующими правилами проверки:
    • setName() должен accept только непустые строки; если строка пуста после удаления пробелов, не изменяйте свойство
    • setPrice() должен accept только значения, greater 0: отклоняйте нулевые и отрицательные цены
    • setStock() должен accept только значения 0 или greater: отклоняйте отрицательные количества на складе
    Каждый геттер должен просто возвращать соответствующее значение свойства. Добавьте public method getInfo(), который возвращает "[name]: $[price] ([stock] in stock)", при этом цена должна быть отформатирована с точностью до 2 десятичных разрядов.
  • main.php: Подключите файл Product. Вы получите четыре входных значения: название товара, цену, количество на складе и новую цену для обновления. Создайте экземпляр Product и используйте сеттеры, чтобы assign initial имя, цену (преобразованную в float) и количество на складе (преобразованное в integer). Print результат getInfo(). Затем попытайтесь обновить цену новым значением (преобразованным в float) и снова выведите getInfo(). Наконец, попытайтесь установить количество на складе равным -5 (invalid значение) и ещё раз выведите getInfo(), чтобы confirm, что количество на складе не изменилось.

Ваши сеттеры действуют как привратники. Они проверяют входящие данные перед тем, как разрешить изменения private-свойств. Когда передаются недопустимые данные (например, отрицательное количество на складе), сеттер просто игнорирует их, сохраняя существующее корректное значение. В этом заключается сила инкапсуляции: ваш объект сохраняет свою целостность независимо от того, что пытается сделать внешний код.

Попробуйте сами

<?php
require_once 'Product.php';

// Чтение входных данных
$name = trim(fgets(STDIN));
$price = trim(fgets(STDIN));
$stock = trim(fgets(STDIN));
$newPrice = trim(fgets(STDIN));

// TODO: Создать новый экземпляр Product

// TODO: Использовать сеттеры для назначения начальных name, price (как float) и stock (как integer)

// TODO: Вывести результат getInfo()

// TODO: Обновить price значением newPrice (как float) и снова вывести getInfo()

// TODO: Попытаться установить stock равным -5 (недопустимо) и вывести getInfo(), чтобы подтвердить, что stock не изменился

?>
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор PHP