sstringer
sstringer

Reputation: 506

How do I set PHP class properties with construct() arguments automatically?

Does anyone know of an efficient technique in PHP to auto assign class parameters with identically named __construct() method arguments?

For instance, I've always thought it was highly inefficient to do something like the following:

<?php

class Foo
{
    protected $bar;
    protected $baz;

    public function __construct($bar, $baz)
    {
        $this->bar = $bar;
        $this->baz = $baz;
    }
}

I'm wondering if there's a better/more efficient way/magic method to auto-assign class properties with identically named method parameters.

Thanks,

Steve

Upvotes: 2

Views: 2135

Answers (3)

Jehong Ahn
Jehong Ahn

Reputation: 2386

PHP 8

Constructor Promotion

function __construct(public $bar, public $baz) {}

PHP 5

function _promote(&$o) {
    $m = debug_backtrace(0, 2)[1];    
    $ref = new ReflectionMethod($m['class'], $m['function']);
    foreach($ref->getParameters() as $i=>$p) {
      $o->{$p->name} = $m['args'][$i] ?? $p->getDefaultValue();
    }
}

class Foo {
    function __construct($bar, $baz) {
        _promote($this);
    }
}

Upvotes: 5

Jeff Lambert
Jeff Lambert

Reputation: 24661

Not in a constructor. You can always wrap your properties into an array, instead, and only have a single property that needs to be set:

<?php

class SomeClass
{
    protected $data = [];

    public function __construct(array $data = [])
    {
        $this->data = $data;
    }

    public function getData()
    {
        return $this->data;
    }
}

$params = ['bar' => 'bar', 'baz' => 'baz'];
$someClass = new SomeClass($params);

echo $someClass->getData()['bar'] . PHP_EOL;

There is the magic method __set, but it is only called when attempting to write data to inaccessible properties:

<?php

class SomeClass
{
    protected $data = [];

    public function __construct(array $data = [])
    {
        $this->data = $data;
    }

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

    public function __get($name)
    {
        if(isset($this->data[$name])) {
            return $this->data[$name];
        }

        return null;
    }
}

$class = new SomeClass;
$class->bar = 'bar';
$class->baz = 'baz';

echo $class->bar . PHP_EOL . $class->baz . PHP_EOL;

If your class is starting to have a lot of parameters being passed in to the constructor, it may be a sign that your class is getting too big and trying to do too much. A refactoring may be in order.

Upvotes: 0

ajw4sk
ajw4sk

Reputation: 105

I think this way is a pretty generally accepted way to do it, although you could make getters and setters. Or, if you're looking for magic methods in php: http://php.net/manual/en/language.oop5.magic.php

Upvotes: 0

Related Questions