php: get property name as string

Допустим у вас есть моделька

class Model
{
    public int $id;
    public string $title;

    public function getValue(string $property): mixed
    {
        return $this->$property;
    }
}

И вам очень сильно совсем надоело хардкодить проперти и ещё больше сильнее совсем надоело их рефакторить:

$model = new Model();
$model->id = 42;
$model->title = 'my title';

$id = $model->getValue('id');
$title = $model->getValue('title');

var_dump($id, $title);

То есть преккрасное убогое решение которое поможет вам обманывать вашу IDE: автодополнение и рефакторинг работают. Но не всегда, конечно, а только в контексте исполнения.

trait PropertyNameTrait
{
    public static function __property(): object
    {
        return new class {
            public function __get(string $property): string
            {
                return $property;
            }
        };
    }

}

/** @method static Model __property() */
class Model
{
    use PropertyNameTrait;

    public int $id;
    public string $title;

    public function getValue(string $property): mixed
    {
        return $this->$property;
    }
}


$model = new Model();
$model->id = 42;
$model->title = 'my title';

$id = $model->getValue($model::__property()->id);
$title = $model->getValue(Model::__property()->title);

var_dump($id, $title);

Конечно, можно добавить ещё немного магии, но у вас не получится аккуратно чейнить __get() в трейте и классе, так что это уже по желанию (мне не очень нравится, но пользоваться этим сильно более красивее). (ну и надо не забыть кидать фатал на 404, но мне лень писать эти проверки).

/** @property-read Model $__property */
class Model
{
    public int $id;
    public string $title;

    public function getValue(string $property): mixed
    {
        return $this->$property;
    }

    public function __get(string $property): mixed
    {
        if ($property === '__property') {
            return new class {
                public function __get(string $property): string
                {
                    return $property;
                }
            };
        }
        throw new Error("404: {$property}");
    }
}

$model = new Model();
$model->id = 42;
$model->title = 'my title';

$id = $model->getValue($model->__property->id);
$title = $model->getValue($model->__property->title);

var_dump($id, $title);

#php #magic

2021.10.20 13:50