As a rule, opinions differ on whether it is good practice to use public properties in PHP classes, or should you use getters and setters (and keep properties private or protected). Another compromise is to use the
__get()
and
__set()
magic methods.
Each approach has its advantages and disadvantages, let's take a look at them ...
An example of using public properties: class Foo { public $bar; } $foo = new Foo(); $foo->bar = 1; $foo->bar++;
In this example,
bar is a public property of the class
Foo . With this approach, we can manipulate this property as you please and store any data in it.
Advantages of public properties- Compared to getters and setters, you need to print a lot less text!
- The code looks more readable and easier to work with than the calls to getters and setters.
- Calling a public property (instead of
set
or get
) is faster and uses less memory than a method call, but the benefit from this will be almost imperceptible until you call the method many times in a long loop. - Objects with public properties can be used as parameters for some PHP functions (such as
http_build_query
).
The disadvantages of public properties- It is not possible to control exactly what data is contained in properties - it is very easy to fill them with data that are incorrect for the methods of this class. For example, if a class will be used by a third-party developer other than the author of the class, then there may be problems related to the fact that he may not be aware of (and he does not have to) the internal structure of the class. In the end, it is not a secret to anyone that often after several months have passed, even the author himself forgets the logic of the code written by him.
- If you want to use public properties in the API, then this cannot be done using the interface, as in PHP interfaces only allow definitions of method signatures.
')
An example of using getters and setters: class Foo { private $bar; public function getBar() { return $this->bar; } public function setBar($bar) { $this->bar = $bar; } } $foo = new Foo(); $foo->setBar(1); $foo->setBar($foo->getBar() + 1);
The
bar
property here is private; therefore, it cannot be accessed directly. In order to get the value of a property, you have to use the
getBar
method, or
setBar
to assign a value to a property. So that you can be sure that the input data is completely correct, these methods can include the appropriate functionality for their validation.
Advantages of getters and setters- Using getters and setters, you can control exactly what data is contained in the properties of the object, and reject any incorrect values.
- You can also perform additional operations before setting or getting the property value (for example, if updating this property should trigger some action, such as notifying the user).
- When setting a value that is an object or an array, you can explicitly specify the type of the variable in the function signature (note
public function setBar(Bar $bar)
). Unfortunately, PHP does not allow doing the same with the types int
and string
! - If the property value is to be obtained from an external source or runtime environment, you can use lazy data loading — thus, the resources required to load the data will be used directly during the retrieval of the property value. Of course, in this case, care must be taken, and you should not receive data from an external source each time the property is accessed. It would be better to make one call to the database and fill in the values ​​of all properties at once, than to do it for each separately.
- You can make a property read-only or write-only, by creating only a getter or only a setter.
- You can add getters and setters to the interface in order to display them in the API.
Disadvantages getters and setters- For developers who use direct access to properties, getters and setters seem to be a real headache! For each property, you need to define the property itself, the getter and the setter; and in order to use this property in code, you need to make additional method calls - it is much easier to write
$foo->bar++;
instead of $foo->setBar($foo->getBar() + 1);
(although, of course, you can add another method $foo->incrementBar();
) - As noted above, there is a small additional cost involved in calling a method.
- Names of getters and setters are usually started with the verbs
get
and set
, but these verbs can also be used in other methods that in no way relate to the properties of a class.
An example of the use of magic getters and setters: class Foo { protected $bar; public function __get($property) { switch ($property) { case 'bar': return $this->bar;
In this case, the
bar
property is not public, but in the code it is used as if it were public. When PHP cannot find the corresponding public property, it calls the appropriate magic method (
__get()
to get the value,
__set()
to set the value). This approach may seem like the golden mean, but it has a significant drawback (see shortcomings below!). It should also be noted that
__get()
and
__set()
methods are NOT called for public properties, and are called if the property is marked as
protected
or
private
and is outside the scope, or if the property is not defined.
Advantages of magical getters and setters- You can manipulate properties directly (as if they were public) and retain full control over which data is stored in which properties.
- Similar to using ordinary getters and setters, you can perform additional operations when the property is used.
- You can use lazy data loading.
- You can make properties read-only or write-only.
- You can use magic methods to intercept all calls to properties that have not been defined and process them in some way.
Disadvantages of magic getters and settersThe disadvantage of magical methods is that they do not make the property accessible (“visible”). In order to use or extend a class, you need to “just know” what properties it contains. In most cases this is not possible (unless you are one of the hardcore programmers who think that the notepad is an IDE!), Although there are times when the advantages mentioned above outweigh this limitation. As one commentator noted, this flaw can be eliminated using the phpDoc tags @property-read
, @property-read
, and @property-write
. Cool.
Which approach to useObviously, getters and setters have a number of significant advantages, and some people think that they should be used all the time (especially those with a past
Java
connection!). But in my opinion, by doing so they disrupt the natural development of the language, and their excessive complexity and detail force me to work with it, even if there is no need for it (it annoys me when ordinary getters and setters DO NOT do anything except get and set the property). In such cases, I try to use public properties, and I use getters and setters for critical properties that need to be more strictly controlled, or if they need to use deferred data loading.
Other alternatives?Before learning PHP, I used C #. In C #, all properties have access methods, but you do not need to call them as methods, you can manipulate your properties directly and the corresponding methods will be called magically. This is in some ways similar to the magic
__get()
and
__set()
methods in PHP, but the properties remain defined and accessible. This is the golden mean and it would be very nice to see a similar opportunity in PHP.
Sadly, however, the RFC necessary for implementing C # of a similar syntax for defining methods for accessing properties did not receive the required two-thirds of the vote:
wiki.php.net/rfc/propertygetsetsyntax-v1.2 That's it!