At first glance, it would seemingly make sense to define classes with public properties, which can then be directly read or written. It is considered a best practice, however, to make properties protected, and to then define a getter and setter for each. As the name implies, a getter retrieves the value of a property. A setter is used to set the value.
Best practice
Define properties as protected to prevent accidental outside access. Use public get* and set* methods to provide access to these properties. In this manner, not only can you more precisely control access, but you can also make formatting and data type changes to the properties while getting and setting them.
get or set. The name of the property becomes the suffix. It is a convention to make the first letter of the variable uppercase. Thus, if the property is $testValue, the getter would be getTestValue().$date. Notice that the get and set methods allow for treatment as either a DateTime object or as a string. The value is actually stored in any event as a DateTime instance:$a = new class() {
protected $date;
public function setDate($date)
{
if (is_string($date)) {
$this->date = new DateTime($date);
} else {
$this->date = $date;
}
}
public function getDate($asString = FALSE)
{
if ($asString) {
return $this->date->format('Y-m-d H:i:s');
} else {
return $this->date;
}
}
};$intVal and $arrVal, which are set to a default initial value of NULL. Notice that not only are the return values for the getters data-typed, but they also provide defaults. The setters also either enforce the incoming data-type, or type-cast the incoming value to a certain data-type:<?php
class GetSet
{
protected $intVal = NULL;
protected $arrVal = NULL;
// note the use of the null coalesce operator to return a default value
public function getIntVal() : int
{
return $this->intVal ?? 0;
}
public function getArrVal() : array
{
return $this->arrVal ?? array();
}
public function setIntVal($val)
{
$this->intVal = (int) $val ?? 0;
}
public function setArrVal(array $val)
{
$this->arrVal = $val ?? array();
}
}__call(). The following class defines nine different properties. Instead of having to define nine getters and nine setters, we define a single method, __call(), which makes a determination whether or not the usage is get or set. If get, it retrieves the key from an internal array. If set, it stores the value in the internal array.<?php
class LotsProps
{
protected $firstName = NULL;
protected $lastName = NULL;
protected $addr1 = NULL;
protected $addr2 = NULL;
protected $city = NULL;
protected $state = NULL;
protected $province = NULL;
protected $postalCode = NULL;
protected $country = NULL;
protected $values = array();
public function __call($method, $params)
{
preg_match('/^(get|set)(.*?)$/i', $method, $matches);
$prefix = $matches[1] ?? '';
$key = $matches[2] ?? '';
$key = strtolower($key);
if ($prefix == 'get') {
return $this->values[$key] ?? '---';
} else {
$this->values[$key] = $params[0];
}
}
}Copy the code mentioned in step 1 into a new file, chap_10_oop_using_getters_and_setters.php. To test the class, add the following:
// set date using a string
$a->setDate('2015-01-01');
var_dump($a->getDate());
// retrieves the DateTime instance
var_dump($a->getDate(TRUE));
// set date using a DateTime instance
$a->setDate(new DateTime('now'));
var_dump($a->getDate());
// retrieves the DateTime instance
var_dump($a->getDate(TRUE));In the output (shown next), you can see that the $date property can be set using either a string or an actual DateTime instance. When getDate() is executed, you can return either a string or a DateTime instance, depending on the value of the $asString flag:

Next, have a look at the code defined in step 2. Copy this code into a file, chap_10_oop_using_getters_and_setters_defaults.php, and add the following:
// create the instance
$a = new GetSet();
// set a "proper" value
$a->setIntVal(1234);
echo $a->getIntVal();
echo PHP_EOL;
// set a bogus value
$a->setIntVal('some bogus value');
echo $a->getIntVal();
echo PHP_EOL;
// NOTE: boolean TRUE == 1
$a->setIntVal(TRUE);
echo $a->getIntVal();
echo PHP_EOL;
// returns array() even though no value was set
var_dump($a->getArrVal());
echo PHP_EOL;
// sets a "proper" value
$a->setArrVal(['A','B','C']);
var_dump($a->getArrVal());
echo PHP_EOL;
try {
$a->setArrVal('this is not an array');
var_dump($a->getArrVal());
echo PHP_EOL;
} catch (TypeError $e) {
echo $e->getMessage();
}
echo PHP_EOL;As you can see from the following output, setting a proper integer value works as expected. A non-numeric value defaults to 0. Interestingly, if you supply a Boolean TRUE as an argument to setIntVal(), it is interpolated to 1.
If you call getArrVal() without setting a value, the default is an empty array. Setting an array value works as expected. However, if you supply a non-array value as an argument, the type hint of the array causes a TypeError to be thrown, which can be caught as shown here:

Finally, take the LotsProps class defined in step 3 and place it in a separate file, chap_10_oop_using_getters_and_setters_magic_call.php. Now add code to set values. What will happen, of course, is that the magic method __call() is invoked. After running preg_match(), the remainder of the non-existent property, after the letters set, will become a key in the internal array $values:
$a = new LotsProps();
$a->setFirstName('Li\'l Abner');
$a->setLastName('Yokum');
$a->setAddr1('1 Dirt Street');
$a->setCity('Dogpatch');
$a->setState('Kentucky');
$a->setPostalCode('12345');
$a->setCountry('USA');
?>You can then define HTML that displays the values using the corresponding get methods. These will in turn return keys from the internal array:
<div class="container">
<div class="left blue1">Name</div>
<div class="right yellow1">
<?= $a->getFirstName() . ' ' . $a->getLastName() ?></div>
</div>
<div class="left blue2">Address</div>
<div class="right yellow2">
<?= $a->getAddr1() ?>
<br><?= $a->getAddr2() ?>
<br><?= $a->getCity() ?>
<br><?= $a->getState() ?>
<br><?= $a->getProvince() ?>
<br><?= $a->getPostalCode() ?>
<br><?= $a->getCountry() ?>
</div>
</div>Here is the final output:
