Rápli András
Rápli András

Reputation: 3923

Set object properties at constructor call time (PHP)

I wonder if it's possible to achieve similar functionality to C#'s compact instantiation syntax:

itemView.Question = new ItemViewQuestion()
{
  AnswersJSON = itemView.Answer.ToJSONString(),
  Modified = DateTime.Now,
  ModifiedBy = User.Identity.Name
};

I wish to be able to create an object of arbitrary class passing their properties without having to set up constructor code for these properties.

To put up another example, this can be done with stdClass like this:

(object) ["name" => "X", "age" => 30]

Type juggling does not work for custom classes, however.

Upvotes: 3

Views: 61

Answers (3)

ryantxr
ryantxr

Reputation: 4219

Obviously php doesn't have this. Somewhere a function is required. I did an implementation using a trait which is close.

<?php

Trait Init {
    public function init($arr) {
        $vars = get_object_vars($this);
        foreach($arr as $k => $v) {
            if ( array_key_exists($k, $vars) ) $this->$k = $v;
        }
    }
}

class Demo {
use Init;
    public $answersJSON;
    public $modified;
    public $modifiedBy;
}

$obj = new Demo();
$obj->init(['modified' => 'now']);

print_r($obj);

Upvotes: 0

dkasipovic
dkasipovic

Reputation: 6120

This is valid in PHP though:

<?php
    class Demo {

        public function getA() {
            return $this->Options['A'];
        }

    }

    $D = new Demo();
    $D->Options = Array(
        'A' => '1',
        'B' => '2',
        'C' => '3'
    );

    var_dump($D->getA());

Or, something like this:

<?php
    class Demo {

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

        public function getA() {
            return $this->Options['A'];
        }

    }

    $D = new Demo(Array(
        'A' => '1',
        'B' => '2',
        'C' => '3'
    ));


    var_dump($D->getA());

Or even this:

<?php
    class Demo {

        public function __construct($Options) {
            foreach ($Options as $key=>$value) $this->$key = $value;
        }

        public function getA() {
            return $this->A;
        }

    }

    $D = new Demo(Array(
        'A' => '1',
        'B' => '2',
        'C' => '3'
    ));


    var_dump($D->getA());

I guess it really depends what are you trying to achieve? You said you do not want to use magic functions or setters, but is there more to it?

Upvotes: 0

Phiter
Phiter

Reputation: 14992

There is no such functionality natively in PHP, unfortunately.

But you can create a class in your project and extend it in the classes you wish to instantiate without a constructor. Something like this:

<?php

class Fillable{
    public static function fill($props)
    {
        $cls = new static;
        foreach($props as $key=>$value){
            if (property_exists(static::class,$key)){
                $cls->$key = $value;
            }
        }
        return $cls;
    }
}
class Vegetable extends Fillable
{

    public $edible;
    public $color;
}

$veg = Vegetable::fill([
    'edible' => true,
    'color' => 'green',
    'name' => 'potato' //Will not get set as it's not a property of Vegetable. (you could also throw an error/warning here)
]);

var_dump($veg);

Checkout this fiddle for the working example

Upvotes: 3

Related Questions