Хватит создавать геттеры и сеттеры: обзор пакета PHP Properties, расширяющего язык

В большинстве случаев писать геттеры или сеттеры самому — не лучшее решение. Генерировать геттеры / сеттеры с помощью IDE — лучше, но не идеально. Пакет PHP Properties решает эти проблемы и «бесплатно» добавляет другие возможности.

PHP Properties — это выполненная в виде трейта реализация геттеров и сеттеров для вашего класса, которая берет информацию о его полях из doc-block.

Использование

Но для начала давайте вспомним, как создаются обыкновенные геттеры. Может, так?

class Some
{
    private $property = 23;

    public function getProperty()
    {
        return $this->property;
    }
}

Или так?

/**
 * @property-read int $property
 */
class Some
{
    private $property = 23;
    
    public function __get($name)
    {
        if ($name === 'property') {
            return $this->property;
        }
    }
}

Выглядит ужасно, особенно если таких методов десятки.

Как мы можем избежать этого? Именно тут нам на помощь приходит пакет Properties. Давайте рассмотрим его использование на примере. Обратите внимание на doc-block, идущий перед классом:

use Serafim\Properties\Properties;

/**
 * @property-read string $some
 */
class Some
{
    use Properties;
    
    protected $some = 'olololo';
}

$object = new Some();
echo $object->some; // => olololo

// Ура, это работает! 

$object->some = 'new value'; // => Ошибка!

Да, это настоящая переменная, доступная только для чтения — информация о необходимом поведении берется из блока документации /** перед классом. Кроме того, этот блок помогает IDE подсвечивать места с логическими ошибками.

Похожая магия работает и с методами:

use Serafim\Properties\Properties;

/**
 * @property-read int $some
 * @property-read bool $any
 */
class Some
{
    use Properties;
    
    public function getSome()
    {
        return 42;
    }
    
    public function isAny()
    {
        return true;
    }
}

$object = new Some();
$object->some; // => 42
$object->any; // => true

А что на счет записи переменных класса? Это так же просто и магически:

use Serafim\Properties\Properties;

/**
 * @property-write mixed $value
 * @property-write mixed $any
 */
class WritableSome
{
    use Properties;
    
    protected $some;
    
    public function setAny($value)
    {
        //
    }
}

$object = new WritableSome();

$object->some = 42; // It works
$object->any = 100500; // It works too

// Попробуем прочитать значение?

$object->some; // => Ошибка

Установка

Добавить пакет в свой проект очень просто, если вы используете Composer:

composer require serafim/properties

… впрочем, если вы не используете Composer, то вам ведь вообще по жизни непросто, правда?