- Магический метод set
- Несуществующее свойство
- Проверка при записи
- Применение
- Can You Create Instance Properties Dynamically in PHP
- Can you create instance properties dynamically in PHP?
- How to create new property dynamically
- PHP set object properties dynamically
- Dynamically creating instance variables in PHP classes
- How do you access a dynamic property in an object?
- How do I dynamically write a PHP object property name?
- Update for PHP 7.0
- Original answer
- Dynamically Create Instance Method in PHP
- Dynamically create PHP object based on string
- dynamic class property $$value in php
- How to Use the PHP __get and __set Magic Methods
- Actual PHP Output
Магический метод set
Магический метод __set вызывается при попытке изменить значение несуществующего или скрытого свойства. В качестве параметров он принимает имя свойства и значение, которое ему пытаются присвоить.
Давайте посмотрим на практическом примере. Пусть у нас дан вот такой класс Test :
Давайте сделаем в этом классе магический метод __set , который с помощью функции var_dump будет выводить имя свойства, к которому произошло обращение, и значение, которое этому свойству пытаются установить:
Проверим работу нашего класса:
Давайте теперь будем устанавливать значение свойству, имя которого хранится в переменной $property :
Теперь мы сможем записывать в приватные свойства снаружи класса:
Записывать мы можем, однако, проверить, записалось ли туда что-то — нет, так как свойства приватные.
Можно сделать геттер для этих свойств или просто воспользоваться магическим методом __get . Воспользуемся вторым вариантом:
Вот теперь мы можем проверить работу нашего класса. Проверим:
prop1 = 1; // запишем 1 $test->prop2 = 2; // запишем 2 echo $test->prop1; // выведет 1 echo $test->prop2; // выведет 2 ?>?php>
На самом деле, конечно же, не стоит разрешать всем подряд записывать в приватные свойства, иначе пропадает суть этих приватных свойств (проще сделать их публичными и все).
Поэтому данный метод следует применять только тогда, когда в этом действительно есть необходимость. Ниже мы еще рассмотрим примеры удачного применения.
Несуществующее свойство
Давайте попробуем записать данные в несуществующее свойство — это будет работать:
Пусть мы не хотим разрешать записывать в несуществующие свойства. И, вообще, хотим разрешить запись только в свойства prop1 и prop2 .
Это легко сделать — достаточно в методе __set добавить соответствующее условие:
Если таких свойств будет много, то не очень удобно перечислять их все в условии.
Давайте запишем разрешенные для записи свойства в массив и будем проверять наличие свойства в этом массиве с помощью функции in_array :
Проверка при записи
Давайте будем проверять значения свойств на соответствие определенному условию:
0 and $value < 10) < $this->$property = $value; > break; case ‘prop2’: // Если prop2 от 10 до 20: if ($value > 10 and $value < 20) < $this->$property = $value; > break; default: // Такого свойства нет break; > > public function __get($property) < return $this->$property; > > ?>?php>
Применение
Практическое применение метода __set вы изучите самостоятельно, решив вот такую задачу:
Пусть дан вот такой класс User с геттерами и сеттерами свойств:
Переделайте код этого класса так, чтобы вместо геттеров и сеттеров использовались магический методы __get и __set .
Can You Create Instance Properties Dynamically in PHP
Can you create instance properties dynamically in PHP?
Sort of. There are magic methods that allow you to hook your own code up to implement class behavior at runtime:
class foo public function __get($name) return('dynamic!');
>
public function __set($name, $value) $this->internalData[$name] = $value;
>
>
That’s an example for dynamic getter and setter methods, it allows you to execute behavior whenever an object property is accessed. For example
would print, in this case, «dynamic!» and you could also assign a value to an arbitrarily named property in which case the __set() method is silently invoked. The __call($name, $params) method does the same for object method calls. Very useful in special cases. But most of the time, you’ll get by with:
class foo public function __construct() foreach(getSomeDataArray() as $k => $value)
$this-> = $value;
>
>
. because mostly, all you need is to dump the content of an array into correspondingly named class fields once, or at least at very explicit points in the execution path. So, unless you really need dynamic behavior, use that last example to fill your objects with data.
This is called overloading
http://php.net/manual/en/language.oop5.overloading.php
How to create new property dynamically
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-> = $value;
>
>
$foo = new Foo();
$foo->createProperty('hello', 'something');
PHP set object properties dynamically
You can using Reflection , I think.
function set(array $array) $refl = new ReflectionClass($this);
foreach ($array as $propertyToSet => $value) $property = $refl->getProperty($propertyToSet);
if ($property instanceof ReflectionProperty) $property->setValue($this, $value);
>
>
>
$a = new A();
$a->set(
array(
'a' => 'foo',
'b' => 'bar'
)
);
var_dump($a);
object(A)[1]
public 'a' => string 'foo' (length=3)
public 'b' => string 'bar' (length=3)
Dynamically creating instance variables in PHP classes
Yes that will indeed work. Auto-created instance variables are given public visibility.
How do you access a dynamic property in an object?
$var = json_decode(json_encode(array('1' => 'Object one','2' => 'Object two')));
$num = "2";
var_dump( $var->$num );
How do I dynamically write a PHP object property name?
Update for PHP 7.0
PHP 7 introduced changes to how indirect variables and properties are handled at the parser level (see the corresponding RFC for more details). This brings actual behavior closer to expected, and means that in this case $obj->$field[0] will produce the expected result.
In cases where the (now improved) default behavior is undesired, curly braces can still be used to override it as shown below.
Original answer
Write the access like this:
This «enclose with braces» trick is useful in PHP whenever there is ambiguity due to variable variables.
Consider the initial code $obj->$field[0] — does this mean «access the property whose name is given in $field[0] «, or «access the element with key 0 of the property whose name is given in $field «? The braces allow you to be explicit.
Dynamically Create Instance Method in PHP
You are assigning the anonymous function to a property, but then try to call a method with the property name. PHP cannot automatically dereference the anonymous function from the property. The following will work
class Foo
function __construct() $this->sayHi = create_function( '', 'print "hi";');
>
>
$foo = new Foo;
$fn = $foo->sayHi;
$fn(); // hi
You can utilize the magic __call method to intercept invalid method calls to see if there is a property holding a callback/anonymous function though:
class Foo
public function __construct()
$this->sayHi = create_function( '', 'print "hi";');
>
public function __call($method, $args)
if(property_exists($this, $method)) if(is_callable($this->$method)) return call_user_func_array($this->$method, $args);
>
>
>
>
$foo = new Foo;
$foo->sayHi(); // hi
As of PHP5.3, you can also create Lambdas with
See the PHP manual on Anonymous functions for further reference.
Dynamically create PHP object based on string
But know of no way to dynamically create a type based on a string. How does one do this?
You can do it quite easily and naturally:
$type = 'myclass';
$instance = new $type;
If your query is returning an associative array, you can assign properties using similar syntax:
// build object
$type = $row['type'];
$instance = new $type;
// remove 'type' so we don't set $instance->type = 'foo' or 'bar'
unset($row['type']);
// assign properties
foreach ($row as $property => $value) $instance->$property = $value;
>
dynamic class property $$value in php
You only need to use one $ when referencing an object’s member variable using a string variable.
How to Use the PHP __get and __set Magic Methods
In this article, we show how to use the PHP __get and __set magic methods.
The PHP __get and __set magic methods function as getters and setters for object values, but it had the added advantage in that you don’t have to declare the object properties (variables) in the class.
Instead when you set a value (with the object property never declared in the class), the __set magic method is automatically called and sets the value.
The same is true for the __get method. Without the object property being declared in the class that you want to get, the __get magic method is automatically called and gets the value.
So the __get and __set magic methods function as getters and setters, without the object property variable having to be declared in the class.
We will show each of these in the code below.
In the code below, we make a class called kids. In this class, we set a child’s height through the __set method or get a child’s height through the __get method.
Getter and setter methods provide encapsulation of data so that in order to set or get data, it has to pass through a method. The reason we do this is because many times we want to test the data first to make sure that’s an appropriate or reasonable value.
In this class, we are setting the height of a kid. For example, the height cannot be negative. The height can’t be 1 inch tall. No child is one inch tall. This is the reason we only allow for heights 30 inches or grader. Imagine this is fifth grade student. They all are way past this point.
So passing data first through a method allows us to filter out bad data. It allows for this encapsulation where we don’t have to accept bad data, such as a negative height or 0.5 inches tall.
This is why getter and setter methods are commonly used.
So we create a class called kids.
Inside of this class we create the setter and getter methods.
The first method that we create the setter method using the __set function. The setter function has to accept 2 parameters, the object property you are defining and the value of this object property. As we are setting a child’s height in this code, the height is the object property and the value of the height we set it to is the value. We make it so that if the value passed into the object property is greater than 30, we set the object property to that value. If the value is less than 30, then the magic set method does not set the value.
We then create the next function, the getter method using the __get function. The get function accepts one parameter, the $property of the object. We do not need the $value as the parameter, because the $value is already set by the setter function. With the getter function, we do not set the value. We just retrieve the value that’s already been set. So in this getter function, we return the child’s height in inches by calling the $this->property function. $this->property refers to the value of the property of the object we’re getting.
All of this will make more sense now below.
So underneath this, we create an object of the kids class, $kid1.
We then the object property, height, of $kid1 equal to 45. This makes the kid’s height 45 inches.
What’a amazing about the magic method __set() in PHP is that we have defined the property variable $height anywhere in the class. Yet we’re just automatically setting the height of the $kid1 object. This triggers the PHP __set() magic method. The method sees the height as a property of the object and 45 as the value of this height property. $kid1 is the object of this call.
So because we automatically set an object property and its height without declaring them or calling a function, this automatically calls the PHP __set() magic method. So the $property value is height. The $value of this property is 45. We set the value only if the value is greater than 30. We set the value through the line, $this->property= $value. $this refers to the object kid1. We set $kid->height= 45. So now you can see how this is set through the PHP __set magic method.
To automatically get the property of an object, you call an output function such as echo or print with the parameter of an object and property. This automatically triggers the PHP __get magic method.
The only parameter needed for the __get() method is the $property variable. We return out what the child’s height is in inches.
So this is all that is required to use the PHP __get and __set magic methods. It’s very adaptable because you don’t need to declare variables in the class and you don’t need to call a function. If you set it up properly, like how demonstrated, it will automatically call the __get or __set magic methods. So in this way, it simplifies code.
Running the PHP code above yields the following output shown below.
Actual PHP Output
The child’s height is 45 inches tall