Beamtic's logo

Share via:

PHP: Prevent Adding Properties to Objects

We can prevent adding properties to instantiated objects in PHP to help enforce good coding practice; in this tutorial I show how this is accomplished.

64 views

Edited: 2020-09-06 10:06

We can prevent adding new properties to PHP Objects by using the magic __set method; this method is only called when someone attempts to add a non-existent property to an instantiated object and therefor carries no performance penalty.

To use the __set magic method, just include it in an existing class, like this:

public function __set($name, $value) {
  throw new \Exception("Adding new properties is not allowed on " . __CLASS__);
}

If you got a lot of classes, you can also create a trait that can be easily included in the classes where you want to prevent adding new properties:

trait no_set {
    public function __set($name, $value) {
      throw new \Exception("Adding new properties is not allowed on " . __CLASS__);
    }
}

To include it in a class, we employ a use statement:

class some_class_name {

  public some_method_name() {
    // Whatever ....
  }

  use lib\class_traits\no_set;
}

Why prevent adding non-existent attributes to objects?

In an objected orientated context, it will typically be possible to add new properties to instantiated objects and thereby use them as a sort of "container" for data; doing this is of course a bad practice, and should be avoided.

You might argue that most developers will know not to do that, which is probably true; but why allow it when we can easily prevent it from happening?

Ideally, we might also want to declare all our object properties as private, and only allow modifying them with pre-defined setter and getter functions. Using magic methods for this purpose is probably bad in most cases; but, we can still use the __set magic method to prevent adding new, non-existing properties. This can be done by throwing an exception when someone attempts adding a variable to an instance of our object:

public function __set($name, $value) {
  throw new \Exception("Adding new properties is not allowed on " . __CLASS__);
}

Of course, a developer might also be aware that we can do this, and therefor decide that it is not worth the risk to use our object as a "container" for their own purposes.

Why use a trait?

If you got a lot of classes that share this, and other "traits", then it makes sense to create a PHP trait, and include it in all the classes that share these characteristics; alternatively we could also use inheritance, but doing so, in this case, is probably not going to be a super effective use of inheritance.

Inheritance is generally going to make code less flexible and portable anyway, and it seems to me like it has few actual uses in the real world. Composition is better. I personally prefer instantiating dependencies in my composition root, and then pass them on through dependency injection to the classes that needs them; this allows me to easily use my classes in other projects, independent from other code that I do not need.

You might argue that a trait "hides" the magic method for the developer, but this is actually intentional, since this particular trait has nothing to do with implementation and more to do with changing a default behavior of PHP.

Comments

  1. How to create a custom error handler for PHP that handles non-fetal errors.
  2. We can access other classes properties (variables) and methods (functions) by injecting the class object in the class that needs it.
  3. Setting custom HTTP Headers with cURL is useful when changing User Agent or Cookies. Headers can be changed two ways, both using the curl_setopt function.
  4. Should you use file_get_contnts or cURL when performing HTTP requests from PHP? It does not matter; but regardless of which you use, you should still handle errors properly!
  5. When using file_get_contents to perform HTTP requests, the server response headers is stored in a reserved variable after each successful request; we can iterate over this when we need to access individual response headers.

More in: PHP Tutorials