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.