Практика создания классов в PHP 7

Раздел: Версии PHP -> Особенности PHP 7

Классы в PHP 7: основные принципы и примеры

Как создать класс с современным синтаксисом PHP 7?

В PHP 7 появились возвращаемые типы и скалярные объявления типов. Наиболее эффективное решение включает строгую типизацию, использование анонимных классов и трейтов.

<?php
declare(strict_types=1);

class Product {
    public string $name;
    private float $price;
    const TAX = 0.2;

    public function __construct(string $name, float $price) {
        $this->name = $name;
        $this->setPrice($price);
    }

    public function getPriceWithTax(): float {
        return $this->price * (1 + self::TAX);
    }

    public function setPrice(float $price): void {
        if ($price <= 0) {
            throw new InvalidArgumentException('Price must be positive');
        }
        $this->price = $price;
    }
}

// Анонимный класс для одноразового использования
$discounter = new class(0.1) {
    private float $percent;

    public function __construct(float $percent) {
        $this->percent = $percent;
    }

    public function apply(Product $product): float {
        return $product->getPriceWithTax() * (1 - $this->percent);
    }
};

$product = new Product('Laptop', 1000.0);
echo $product->getPriceWithTax(); // 1200
echo $discounter->apply($product); // 1080
?>

Php 7 class (классы в php 7)

1200
1080

Типичные ошибки: забыто declare(strict_types=1), что приводит к автоматическому преобразованию типов. В анонимных классах нельзя сериализовать объект.

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

Как объявить класс без указания типов (стиль PHP 5)?

<?php
class OldProduct {
    public $name;
    private $price;
    const TAX = 0.2;

    function __construct($name, $price) {
        $this->name = $name;
        $this->price = $price;
    }

    function getPriceWithTax() {
        return $this->price * (1 + self::TAX);
    }
}
?>

Проблема: отсутствие контроля типов может приводить к ошибкам, которые сложно отловить.

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

<?php
class Calculator {
    public function add(int $a, int $b): int {
        return $a + $b;
    }
    public function divide(float $a, float $b): float {
        if ($b == 0) {
            throw new InvalidArgumentException('Division by zero');
        }
        return $a / $b;
    }
}
?>

Ошибка: передача строки в метод add может вызвать TypeError. Решение: использовать строгий режим или преобразование.

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

<?php
$logger = new class {
    public function log(string $message): void {
        echo $message;
    }
};
$logger->log('Test'); // Test
?>
Test

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

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

<?php
trait Timestampable {
    public function getCreatedAt(): string {
        return date('Y-m-d H:i:s', $this->created ?? time());
    }
}

class Post {
    use Timestampable;
    private $created;
    public function __construct() {
        $this->created = time();
    }
}

$post = new Post();
echo $post->getCreatedAt();
?>
2025-03-25 12:00:00 (пример)

Конфликты имен методов трейтов. Решение: использовать оператор insteadof или псевдонимы.

Как задать обязательные методы с помощью интерфейса?

<?php
interface CacheInterface {
    public function set(string $key, $value, int $ttl = 3600): void;
    public function get(string $key);
}

class FileCache implements CacheInterface {
    public function set(string $key, $value, int $ttl = 3600): void {
        // Запись в файл
    }
    public function get(string $key) {
        // Чтение из файла
    }
}
?>

Ошибка: если не реализовать все методы интерфейса, произойдет фатальная ошибка.

Расширенные примеры классов в PHP 7

Пример
<?php
declare(strict_types=1);

// 1. Наследование с переопределением типов
abstract class Animal {
    abstract protected function makeSound(): string;
}

class Dog extends Animal {
    protected function makeSound(): string {
        return 'Bark';
    }
}

// 2. Использование nullable типов (PHP 7.1)
class User {
    private ?string $middleName = null;

    public function getMiddleName(): ?string {
        return $this->middleName;
    }
}

// 3. Константы класса с модификаторами видимости (PHP 7.1)
class Config {
    public const APP_NAME = 'MyApp';
    protected const DB_HOST = 'localhost';
    private const SECRET_KEY = 'abc123';

    public function getSecret(): string {
        return self::SECRET_KEY;
    }
}

// 4. Магические методы: __get, __set, __call
class Magic {
    private array $data = [];

    public function __get(string $name): mixed {
        return $this->data[$name] ?? null;
    }

    public function __set(string $name, $value): void {
        $this->data[$name] = $value;
    }

    public function __call(string $name, array $arguments): void {
        echo "Calling $name with " . implode(', ', $arguments);
    }
}

$obj = new Magic();
$obj->name = 'Test';
echo $obj->name; // Test
$obj->undefinedMethod(1, 2); // Calling undefinedMethod with 1, 2

// 5. Анонимный класс, захватывающий переменные
$factor = 10;
$multiplier = new class($factor) {
    private int $factor;
    public function __construct(int $factor) {
        $this->factor = $factor;
    }
    public function multiply(int $value): int {
        return $value * $this->factor;
    }
};
echo $multiplier->multiply(5); // 50

// 6. Комбинация трейтов с разрешением конфликтов
trait A {
    public function sayHello(): string {
        return 'Hello from A';
    }
}

trait B {
    public function sayHello(): string {
        return 'Hello from B';
    }
}

class Greeting {
    use A, B {
        A::sayHello insteadof B;
        B::sayHello as sayHelloFromB;
    }
}

$g = new Greeting();
echo $g->sayHello(); // Hello from A
echo $g->sayHelloFromB(); // Hello from B

// 7. Групповое объявление use (PHP 7.0)
use App\Models\{User, Post, Comment};

// 8. Использование void как возвращаемый тип (PHP 7.1)
class Printer {
    public function printMessage(string $msg): void {
        echo $msg;
    }
}

// Результаты всех примеров (выводятся, если запустить)
?>
Test
Calling undefinedMethod with 1, 2
50
Hello from A
Hello from B
(вызов Printer::printMessage() ничего не возвращает)

Классы в PHP 7 - comments

En
Php 7 class (php)