How to create new property dynamically
Asked Answered
F

5

97

How can I create a property from a given argument inside a object's method?

class Foo{

  public function createProperty($var_name, $val){
    // here how can I create a property named "$var_name"
    // that takes $val as value?

  }

}

And I want to be able to access the property like:

$object = new Foo();
$object->createProperty('hello', 'Hiiiiiiiiiiiiiiii');

echo $object->hello;

Also is it possible that I could make the property public/protected/private ? I know that in this case it should be public, but I may want to add some magik methods to get protected properties and stuff :)


I think I found a solution:
  protected $user_properties = array();

  public function createProperty($var_name, $val){
    $this->user_properties[$var_name] = $val;

  }

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

  }

do you think it's a good idea?

Fulmis answered 3/1, 2012 at 2:15 Comment(1)
Questions should never be edited to insert a "solution" -- that's what answers are for.Convulsant
B
131

There are two methods to doing it.

One, you can directly create property dynamically from outside the class:

class Foo{

}

$foo = new Foo();
$foo->hello = 'Something';

Or if you wish to create property through your createProperty method:

class Foo{
    public function createProperty($name, $value){
        $this->{$name} = $value;
    }
}

$foo = new Foo();
$foo->createProperty('hello', 'something');
Blackfish answered 3/1, 2012 at 2:22 Comment(8)
thank you. I need it inside the class though. It's kind of complicated to explain, the properties are actually objects which are site extensions that the site administrator can enable/disable :) But I will use my solution, I think it's better to keep them inside an array.Fulmis
Is it possible to set them as private or protectd?Amberjack
Setting property like this does not allow us to make it private or protected because it is set from public. However, you can try to work with OOP magic methods __get() and __set(). See #4714180Blackfish
Your second method of dynamic property creation will result in Notice: Undefined variable: name Please check itSand
I think sun is right on this one. The line $this->$name = $value; should actually be $this->name = $value;Lillith
Or $this->{$name} = $value;, no?Swahili
If you want a dynamic property name like in this case we want the hello attribute then use $this->{$name} istead of $this->name cause $this->name will only create a name propertyUnchartered
The first solution is deprecated in PHP 8.2 class Foo{} $foo = new Foo(); $foo->hello = 'Something';Algorism
M
26

The following example is for those who do not want to declare an entire class.

$test = (object) [];

$prop = 'hello';

$test->{$prop} = 'Hiiiiiiiiiiiiiiii';

echo $test->hello; // prints Hiiiiiiiiiiiiiiii
Microprint answered 4/3, 2017 at 18:25 Comment(0)
L
7

Property overloading is very slow. If you can, try to avoid it. Also important is to implement the other two magic methods:

__isset(); __unset();

If you don't want to find some common mistakes later on when using these object "attributes"

Here are some examples:

http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members

EDITED after Alex comment:

You can check yourself the differences in time between both solutions (change $REPEAT_PLEASE)

<?php

 $REPEAT_PLEASE=500000;

class a {}

$time = time();

$a = new a();
for($i=0;$i<$REPEAT_PLEASE;$i++)
{
$a->data = 'hi';
$a->data = 'bye'.$a->data;
}

echo '"NORMAL" TIME: '.(time()-$time)."\n";

class b
{
        function __set($name,$value)
        {
                $this->d[$name] = $value;
        }

        function __get($name)
        {
                return $this->d[$name];
        }
}

$time=time();

$a = new b();
for($i=0;$i<$REPEAT_PLEASE;$i++)
{
$a->data = 'hi';
//echo $a->data;
$a->data = 'bye'.$a->data;
}

echo "TIME OVERLOADING: ".(time()-$time)."\n";
Lyricism answered 3/1, 2012 at 2:35 Comment(4)
I'm kind of addicted to __get / __set / __call. I practically use them in every class to get nice API when using that class ... Didn't need __isset so far.. Can you provide a link or something with some benchmarks related to overloading?Fulmis
Sorry for the bad news but __call is really slow tooLyricism
Show some references/evidence to "property overloading is slow".Uppity
@Uppity use the benchmark code I put in my answer and check the time spent for both solutions in your own serversLyricism
K
6

Use the syntax: $object->{$property} where $property is a string variable and $object can be this if it is inside the class or any instance object

Live example: http://sandbox.onlinephpfunctions.com/code/108f0ca2bef5cf4af8225d6a6ff11dfd0741757f

 class Test{
    public function createProperty($propertyName, $propertyValue){
        $this->{$propertyName} = $propertyValue;
    }
}

$test = new Test();
$test->createProperty('property1', '50');
echo $test->property1;

Result: 50

Kristynkrock answered 27/4, 2015 at 23:1 Comment(1)
This is the answer I was looking for, I already new that you can just reference properties in objects that haven't previously been declared... $object->example = "hello"; I was more after how do you dynamically add the property to object whilst also dynamically specifying what you want to call the property.Cohn
G
1

WARNING

DO NOT EVER USE DYNAMIC PROPERTIES!!! IT TS BAD DESING OF YOUR CODE.

Since php 8.2 dynamic properties are deprecated

More about it - https://www.php.net/manual/en/migration82.deprecated.php

Create every property in class in advance. It might help you to avoid mistakes and confusions in future developing and help edit and scale your code faster.

Example

<?php
class User {
    public int $userid;
}
$user = new User();
$user->userid = 1234;
echo $user->userid;
Goodtempered answered 12/3, 2024 at 1:35 Comment(3)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Wakeless
I don't agree that. For decades it has been used as a standard, and now it suddenly became "bad practice". You can maybe say it is slow, you can also say it is bad practice if all the props are known and needed; but there are legit use cases of dynamic property creation. Also, dynamic props is NOT deprecated for stClass in 8.20 it is still valid. As an example; I have a shared struct class for a various amount of APIs which have tens of props in total. I will either repeat tens of lines of code and use all properties although I don't need them; or I will use a single class with dynamic props.Ecumenical
@Ecumenical my answer based on question related to properties in regular class author asked and it tagged as "object" and "properties" and not related to stdClass And in my opinion maybe not bad design ok But it may cause scaling issues you code and readability by other developer Better put all properties in class instead adding them dynamically in codeGoodtempered

© 2022 - 2025 — McMap. All rights reserved.