I need to share some associative data between different parts of my application with two requirements:
- immutability (so read-only)
- safety against mispelling or unavailable index inside the data
- mixed type
I have no need for behaviour, internal state, validation or other DDD related features, just simple read-only data.
For the past I intensively used arrays for such situations but I feel they are more prone to errors due to possible mispelling (trying to access a non existent key would just trigger a notice in standard php configuration) and easy overwriting.
So I recently came to build up a simple class that stores an associative array of data but exposes one and only one way to access it, through php built-in magic methods, throwing exceptions for undefined index inside the data and preventing clients from writing it. Code follows:
class MyData
{
protected $data;
public function __construct(array $data) {
$this->data = $data;
}
public function __get($propertyName) {
if (!array_key_exists($propertyName, $this->data)) {
throw new Exception("Missing key ".$propertyName);
}
return $this->data[$propertyName];
}
public function __set($propertyName, $value) {
throw new Exception("Cannot write ".$propertyName);
}
}
I think this approach would prevent from external writing and trying to access unavailable index, throwing related exceptions and notifying clients in a stronger way than a notice would do. Indeed this would throw an exception:
echo $data->propertyThatDoesNotExist;
and also this:
$data->propertyThatExists = $newValue;
I've already read about arrays vs objects for more or less specific purpose, such as:
- PHP: when to use arrays, and when to use objects for mostly-data-storing code constructs?
- How do I decide whether to make an Input/Output data type an array or a class?
- https://stackoverflow.com/questions/3709578/using-arrays-vs-objects-for-storing-data?noredirect=1&lq=1
- https://stackoverflow.com/questions/3193765/when-should-i-use-stdclass-and-when-should-i-use-an-array-in-php-oo-code
I am curious about what some more experienced developers (even outside of php) think about this solution, thank you very much.
-
What are you specifically curious about? Can you ask a question in which the prima facie answer isn't "I like it" or "I don't like it"?Robert Harvey– Robert Harvey05/20/2019 14:56:02Commented May 20, 2019 at 14:56
-
@RobertHarvey Is this a convenient approach that fulfills my requirements?Sir_Faenor– Sir_Faenor05/20/2019 21:31:44Commented May 20, 2019 at 21:31
-
Only you can answer that.Robert Harvey– Robert Harvey05/20/2019 21:32:45Commented May 20, 2019 at 21:32
1 Answer 1
Your approach does not address spelling issues during development. Nor do you get any type hinting for your IDE. There is however a doc annotation that comes in handy:
/**
* @property-read string $name
* @property-read string $email
* @property-read string $username
*/
class User
{
public $name;
public $email;
public $username;
With this approach your IDE knows exactly which properties your class has and will flag spelling errors. It will also warn against any attempt to assign a value to a property outside of the class. Not quite as good as run time read-only protection but it works well for me. And of course it tells your IDE what the expected types are.
The doc property also works for properties accessed via __get($name). It basically restricts $name values and again provides type hints.
Just something to consider.
-
I did not know about that doc annotation, it's interesting even it's not runtime protection. Thanks!Sir_Faenor– Sir_Faenor05/20/2019 21:29:43Commented May 20, 2019 at 21:29
-
Since Cerad is defining public fields for the class instead of magic get/set functions, you get runtime protection as well.
$user = new User(); $user->foo = 4;
will throw a runtime error when attempting to assign thefoo
property.Greg Burghardt– Greg Burghardt10/17/2019 16:55:12Commented Oct 17, 2019 at 16:55 -
@GregBurghardt I wish it worked that way but php itself has no readonly capability. Your IDE will complain. phpstorm gives you a nice red flag but the code will actually run just fine.Cerad– Cerad10/17/2019 17:41:42Commented Oct 17, 2019 at 17:41
Explore related questions
See similar questions with these tags.