Ce n'est pas tout à fait juste concernant le changement de valeur des attributs.
Il est juste de dire que PHP intègre systématiquement une méthode appelée lors de l'instanciation : le contructeur. C'est le cas dans tous les langages orientés objet.
En php, c'est bien __construct() mais çe peut aussi être le nom de la classe :
<?php
class Foo
{
public function Foo()
{
}
}
Le constructeur, comme n'importe quelle autre méthode dans le classe, peuvent créer des attributs à la voler. Ils seront alors publics.
<?php
class Foo
{
public function bar()
{
$this->bob = true;
}
}
$foo = new Foo();
var_dump(isset($foo->bob)); // false
$foo->bar();
var_dump(isset($foo->bob), $foo->bob); // true, true
$foo->bob = 'issou';
var_dump($foo->bob); // 'issou'
Quand tu fais :
$foo->bar = $value; // ou $this->bar = $value quand t'es dans une méthode
Alors la méthode magique __set() est alors appelée (tu comprends maintenant le nom du constructeur : __construct()). Tu peux ainsi surcharger le comportement de ta classe quand quelque fais : $foo->truc = qqchose.
Tu as la même chose pour récupérer la valeur : echo $foo->bob appelle derrière __get() (que tu peux aussi surcharger).
Les getters et les setters get|setAttribute() sont des conventions de codage. Par ailleurs, elles permettent d'accéder, potentiellement, à des attributs privés (private) et protégés (protected). Ces mêmes attributs qui ne sont pas accessible de la même façon de bob.
De mon coté, je n'aurais pas écrit la classe de cette façon :
<?php
/**
* class Foo.
*/
class Foo
{
/**
* @var string|null
*/
protected $firstname;
/**
* @var string|null
*/
protected $lastname;
/**
* @var int|null
*/
protected $age;
/*
* Contructor.
*
* @param string $firstname
* @param string $lastname
* @param int $age
*/
public function __construct($firstname, $lastname, $age)
{
$this
->setFirstname($firstname)
->setLastname($lastname)
->setAge($age);
}
/*
* Set the value of "firstname".
*
* @param string $firstname
*
* @return Foo
*/
public function setFirstname($firstname)
{
if (empty($firstname)) {
throw new InvalidArgumentException('The firstname can not be empty.');
}
if (!is_string($firstname)) {
throw new InvalidArgumentException('The firstname must be a string.');
}
$this->firstname = $firstname;
return $this;
}
/*
* Get the value of "firstname".
*
* @return string
*/
public function getFirstname()
{
return $this->firstname;
}
/*
* Set the value of "lastname".
*
* @param int $lastname
*
* @return Foo
*/
public function setLastname($lastname)
{
if (empty($lastname)) {
throw new InvalidArgumentException('The lastname can not be empty.');
}
if (!is_string($lastname)) {
throw new InvalidArgumentException('The lastname must be a string.');
}
$this->lastname = $lastname;
return $this;
}
/*
* Get the value of "lastname".
*
* @return int
*/
public function getLastname()
{
return $this->lastname;
}
/*
* Set the value of "age".
*
* @param int $age
*
* @return Foo
*/
public function setAge($age)
{
if (!is_int($age)) {
throw new InvalidArgumentException('The lastname can not be an integer.');
}
$this->age = $age;
return $this;
}
/*
* Get the value of "age".
*
* @return int
*/
public function getAge()
{
return $this->age;
}
}
L'intérêt majeur avec un getter et un setter, c'est que tu peux contrôler les données que tu récupères ou que tu retournes.