Практика создания классов в 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() ничего не возвращает)