0

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:

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 May 20 at 14:56
  • @RobertHarvey Is this a convenient approach that fulfills my requirements? – Sir_Faenor May 20 at 21:31
  • Only you can answer that. – Robert Harvey May 20 at 21:32
0

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 May 20 at 21:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.