PHP Encapsulation Tutorial with Examples

Encapsulation is one of the fundamental principles of Object-Oriented Programming (OOP). In PHP, encapsulation allows you to control access to the properties and methods of a class. I

t is achieved by defining the visibility of class members (properties and methods) using access modifiers: public, protected, and private. Encapsulation helps to protect data from unauthorized access and unintended modifications.

In this tutorial, we will cover:

Let’s dive into each of these topics with examples and explanations.

1. What is Encapsulation?

Encapsulation is the process of wrapping data (properties) and methods (functions) within a class, restricting direct access to some of the object’s components. This allows the internal representation of an object to be hidden from the outside world and only accessible through specific methods (such as getters and setters).

Encapsulation provides:

  • Data hiding: Restricting access to the inner workings of a class.
  • Controlled access: Allowing access to class members only through well-defined interfaces (methods).

2. Access Modifiers: Public, Protected, and Private

In PHP, encapsulation is implemented using access modifiers. These control the visibility of class members (properties and methods):

  • public: Can be accessed from anywhere (inside the class, outside the class, and from subclasses).
  • protected: Can be accessed within the class and by classes derived from that class (subclasses), but not from outside the class.
  • private: Can only be accessed within the class itself, not even by subclasses.

Example (Access Modifiers):

<?php
class Car {
    public $make;        // Public: accessible from anywhere
    protected $model;    // Protected: accessible within the class and subclasses
    private $year;       // Private: accessible only within the class

    public function __construct($make, $model, $year) {
        $this->make = $make;
        $this->model = $model;
        $this->year = $year;
    }

    // Public method to display car details
    public function displayDetails() {
        echo "Make: " . $this->make . "\n";
        echo "Model: " . $this->model . "\n";
        echo "Year: " . $this->year . "\n";
    }
}

// Instantiate a Car object
$car = new Car("Toyota", "Corolla", 2020);
$car->displayDetails();

// Direct access to the public property
echo $car->make;  // Outputs: Toyota

// Direct access to protected and private properties will cause an error
// echo $car->model;  // Error: Cannot access protected property
// echo $car->year;   // Error: Cannot access private property
?>

Output:

Make: Toyota
Model: Corolla
Year: 2020
Toyota
  • In this example, $make is public and can be accessed from outside the class, while $model is protected and $year is private. Attempting to access them directly from outside the class will result in errors.

3. Using Getters and Setters

In PHP, getters and setters are methods that allow you to access and modify private or protected properties while maintaining control over how they are accessed or changed. This is a common way to implement encapsulation while still providing access to class members.

Example (Using Getters and Setters):

<?php
class Car {
    private $make;
    private $model;
    private $year;

    public function __construct($make, $model, $year) {
        $this->make = $make;
        $this->model = $model;
        $this->year = $year;
    }

    // Getter for the make
    public function getMake() {
        return $this->make;
    }

    // Setter for the make
    public function setMake($make) {
        $this->make = $make;
    }

    // Getter for the model
    public function getModel() {
        return $this->model;
    }

    // Setter for the model
    public function setModel($model) {
        $this->model = $model;
    }

    // Getter for the year
    public function getYear() {
        return $this->year;
    }

    // Setter for the year
    public function setYear($year) {
        if ($year > 1885) {  // Cars were invented in 1886
            $this->year = $year;
        } else {
            echo "Invalid year.\n";
        }
    }
}

// Instantiate a Car object
$car = new Car("Honda", "Civic", 2018);

// Use getters to access properties
echo $car->getMake() . "\n";   // Outputs: Honda
echo $car->getModel() . "\n";  // Outputs: Civic
echo $car->getYear() . "\n";   // Outputs: 2018

// Use setters to modify properties
$car->setMake("Ford");
$car->setModel("Mustang");
$car->setYear(1965);

echo $car->getMake() . "\n";   // Outputs: Ford
echo $car->getModel() . "\n";  // Outputs: Mustang
echo $car->getYear() . "\n";   // Outputs: 1965

// Attempt to set an invalid year
$car->setYear(1800);  // Outputs: Invalid year.
?>

Output:

Honda
Civic
2018
Ford
Mustang
1965
Invalid year.
  • In this example, we use getters to access the private properties and setters to modify them. The setYear() method also includes validation to ensure the year is valid, demonstrating controlled access to the properties.

4. Why Encapsulation is Important

Encapsulation provides several key benefits in object-oriented programming:

  1. Data Protection: By using private and protected members, encapsulation ensures that data is not accessed or modified directly, protecting it from unintended changes.
  2. Controlled Access: Getters and setters allow controlled access to properties, making it possible to add validation or constraints on the values being assigned.
  3. Flexibility: Encapsulation allows the internal structure of a class to change without affecting other parts of the code that interact with the class.
  4. Maintainability: It makes your code more maintainable and easier to refactor by hiding implementation details.

5. Example Use Case: Bank Account Class

Let’s consider a practical use case for encapsulation by creating a BankAccount class where balance is a private property, and only specific methods (like deposit() and withdraw()) can modify the balance.

Example (BankAccount Class):

<?php
class BankAccount {
    private $accountHolder;
    private $balance;

    public function __construct($accountHolder, $balance = 0) {
        $this->accountHolder = $accountHolder;
        $this->balance = $balance;
    }

    // Getter for the account holder
    public function getAccountHolder() {
        return $this->accountHolder;
    }

    // Getter for the balance
    public function getBalance() {
        return $this->balance;
    }

    // Method to deposit money
    public function deposit($amount) {
        if ($amount > 0) {
            $this->balance += $amount;
            echo "$amount deposited. New balance: " . $this->getBalance() . "\n";
        } else {
            echo "Invalid deposit amount.\n";
        }
    }

    // Method to withdraw money
    public function withdraw($amount) {
        if ($amount > 0 && $amount <= $this->balance) {
            $this->balance -= $amount;
            echo "$amount withdrawn. New balance: " . $this->getBalance() . "\n";
        } else {
            echo "Invalid withdrawal amount or insufficient balance.\n";
        }
    }
}

// Create a new bank account
$account = new BankAccount("John Doe", 500);

// Display account details
echo "Account holder: " . $account->getAccountHolder() . "\n";
echo "Current balance: " . $account->getBalance() . "\n";

// Deposit money
$account->deposit(300);

// Withdraw money
$account->withdraw(200);

// Attempt to withdraw more than the balance
$account->withdraw(1000);  // Outputs: Invalid withdrawal amount or insufficient balance.
?>

Output:

Account holder: John Doe
Current balance: 500
300 deposited. New balance: 800
200 withdrawn. New balance: 600
Invalid withdrawal amount or insufficient balance.
  • In this example, the BankAccount class encapsulates the balance property, allowing it to be modified only through deposit() and withdraw() methods. This ensures that the balance is always updated in a controlled manner, preventing direct access to the property.

6. Encapsulation and Data Hiding

Data hiding

is an important aspect of encapsulation. By marking properties as private or protected, you prevent direct access to them from outside the class, ensuring that data can only be modified through well-defined methods.

  • Private properties cannot be accessed or modified directly from outside the class, ensuring that internal state changes are done through specific methods (getters, setters).
  • This ensures data integrity and controlled access.

7. Constructor and Encapsulation

Encapsulation can be applied in constructors to initialize private properties. The constructor allows you to set initial values when the object is created, and getters/setters allow controlled access to these values later on.

Example (Constructor with Encapsulation):

<?php
class Person {
    private $name;
    private $age;

    public function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }

    public function getName() {
        return $this->name;
    }

    public function getAge() {
        return $this->age;
    }

    public function setAge($age) {
        if ($age > 0) {
            $this->age = $age;
        } else {
            echo "Invalid age.\n";
        }
    }
}

// Create a new person object
$person = new Person("Alice", 25);
echo "Name: " . $person->getName() . "\n";  // Outputs: Name: Alice
echo "Age: " . $person->getAge() . "\n";    // Outputs: Age: 25

// Modify the age using the setter
$person->setAge(30);
echo "Updated Age: " . $person->getAge() . "\n";  // Outputs: Updated Age: 30

// Attempt to set an invalid age
$person->setAge(-5);  // Outputs: Invalid age.
?>

Output:

Name: Alice
Age: 25
Updated Age: 30
Invalid age.
  • In this example, the Person class uses encapsulation to protect the $age and $name properties, allowing controlled access and modification through getter and setter methods.

Summary of PHP Encapsulation:

Concept Description
public Allows access to properties or methods from anywhere (inside/outside the class).
protected Allows access within the class and subclasses, but not from outside.
private Restricts access to within the class only.
Getters and Setters Methods that allow controlled access and modification of private/protected properties.
Data Hiding Protects internal state by restricting access to properties using access modifiers.
Constructor with Encapsulation Initializes private properties and allows access via getters/setters.

Conclusion

Encapsulation is a critical concept in PHP OOP that helps protect class data and ensure that objects behave in a predictable manner.

By using access modifiers such as public, protected, and private, along with getters and setters, you can control how data is accessed and modified.

In this tutorial, we covered:

  • Access modifiers to control visibility of properties and methods.
  • How to implement getters and setters for controlled access to private or protected properties.
  • A practical use case with a BankAccount class to demonstrate encapsulation.
  • The importance of data hiding and ensuring the integrity of data using encapsulation techniques.

Related posts

PHP Static Methods: A Tutorial with Examples

PHP Deleting Files: A Tutorial with Examples

PHP Copying Files: A Tutorial with Examples