I need to create an immutable class which is simply a member field container. I want its fields to be instantiated once in its constructor (the values should be given as par
<?php
declare(strict_types=1);
final class Immutable
{
/** @var string */
private $value;
public static function withValue(string $value): self
{
return new self($value);
}
public function __construct(string $value)
{
$this->value = $value;
}
public function value(): string
{
return $this->value;
}
}
// Example of usage:
$immutable = Immutable::withValue("my value");
$immutable->value(); // You can get its value but there is no way to modify it.
magic methods
so you can do better - if you have a dinamyc count of fields
class ClassName {
private $fields = array();
// use class : $cl = new ClassName(array('f'=>2,'field_4'=>5,''12));
// echo $cl->field_4; echo $cl->f;
public function __construct($data= array())
{
if (!is_array($data) || !count($data)) throw new Exception('Not enough args')
foreach ($data as $key=>$val)
{
if (is_numeric($key))
$this->fields['field_'.$key] = $val;
else
$this->fields[$key] = $val;
}
}
/* in this case you can use this class like $cl = new ClassName(12,14,13,15,12); echo $cl->field_1;
public function __construct()
{
$ata = funcs_get_args();
if (!count($data)) throw new Exception('Not enough args')
foreach ($data as $key=>$val)
{
if (is_numeric($key))
$this->fields['field_'.$key] = $val;
else
$this->fields[$key] = $val;
}
}
*/
public function __get($var) {
if (isset($this->fields[$var]))
return $this->fields[$var];
return false;
//or throw new Exception ('Undeclared property');
}
}
You should use __set
and __get
magic methods and declare that property as protected or private:
/**
* @property-read string $value
*/
class Example
{
private $value;
public function __construct()
{
$this->value = "test";
}
public function __get($key)
{
if (property_exists($this, $key)) {
return $this->{$key};
} else {
return null; // or throw an exception
}
}
public function __set($key, $value)
{
return; // or throw an exception
}
}
Example:
$example = new Example();
var_dump($example->value);
$example->value = "invalid";
var_dump($example->value);
Outputs:
string(4) "test"
string(4) "test"
@property-read should help your IDE acknowledge existence of this magic property.
You could use the __set()
magic method and throw an exception when someone tries to set a property directly.
class ClassName {
public function __set($key, $value) {
throw new Exception('Can't modify property directly.');
}
}
However, this would prevent modification of properties regardless of whether they're public or not.