Enforce proper encapsulation in coding practices
class User {
public $name;
public $email;
public $password;
}
In the above PHP code, a class named
User
is defined with three public fields:
name
,
email
, and
password
.
The problem with this code is that it does not adhere to the principle of encapsulation. Encapsulation is one of the fundamental principles of object-oriented programming. It refers to the bundling of data, and the methods that operate on that data, into a single unit called a class.
In PHP, the visibility of a property, a method, or a constant can be defined by prefixing the declaration with the keywords public, protected, or private. Public declared items can be accessed everywhere. Protected limits access to inherited and parent classes, and private limits visibility only to the class that defines the item.
By declaring the fields as public, we are allowing these variables to be accessed and modified directly from outside the class. This can lead to unwanted side-effects, as the class cannot control what values are being assigned to its fields.
For example, the
password
field should be private and should not be directly accessible. It should only be modified through a method in the
User
class that can ensure the password meets certain requirements (e.g., minimum length, contains special characters, etc.). If the
password
field is public, any code that uses the
User
class could directly modify the
password
, potentially setting it to a value that does not meet the required standards or even worse, leaving it blank.
The same applies to the
name
and
email
fields. There might be certain restrictions on what these fields can contain (e.g.,
name
should not contain numeric or special characters,
email
should be in a valid format, etc.), and by making these fields public, we are not able to enforce these rules.
This inappropriate coding practice leads to a violation of data integrity and security, which is a major concern in any backend application.
class User {
private $name;
private $email;
private $password;
public function getName() {
return $this->name;
}
public function setName($name) {
if (!is_string($name)) {
throw new InvalidArgumentException('Name must be a string');
}
$this->name = $name;
}
public function getEmail() {
return $this->email;
}
public function setEmail($email) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Invalid email format');
}
$this->email = $email;
}
public function getPassword() {
return $this->password;
}
public function setPassword($password) {
if (strlen($password) < 8) {
throw new InvalidArgumentException('Password must be at least 8 characters long');
}
$this->password = password_hash($password, PASSWORD_DEFAULT);
}
}
The code above is a refactored version of the
User
class. The fields
$name
,
$email
, and
$password
have been changed from
public
to
private
to respect the encapsulation principle. This means that these fields can no longer be accessed directly from outside the class.
Getter and setter methods have been added for each field. The getter methods (
getName()
,
getEmail()
, and
getPassword()
) return the value of the respective field. The setter methods (
setName($name)
,
setEmail($email)
, and
setPassword($password)
) allow the value of the respective field to be changed.
In the setter methods, validation logic has been added to ensure that only valid data is set to the fields. For example, the
setName($name)
method checks that
$name
is a string, the
setEmail($email)
method checks that
$email
is a valid email format, and the
setPassword($password)
method checks that
$password
is at least 8 characters long and hashes the password before storing it.
This refactoring ensures that the
User
class is more secure and respects the encapsulation principle. All code that previously accessed the fields directly should be updated to use these new getter and setter methods.