What Are We Doing in This Post?
This is the final Core PHP episode. After this, we start Laravel.
In Episode 13 we learned classes, objects, inheritance, and encapsulation. Those are the foundations. This episode covers three more OOP concepts that are used everywhere in Laravel's source code — interfaces, abstract classes, and namespaces.
You will not build a full Laravel application using these directly as a beginner. But you will encounter them constantly while reading Laravel code. Understanding them now means Laravel will make sense immediately instead of feeling like an alien codebase.
Let us finish Core PHP strong.
Part 1 — Interfaces
The Problem Interfaces Solve
Imagine you are building a payment system. Your application needs to support multiple payment gateways — Razorpay, PayPal, and Stripe. Each gateway has different internal code, different API calls, different response formats.
But from your application's point of view, you want to treat them all the same way. You want to call charge(), refund(), and get_transaction_id() on any of them without caring which one you are using.
How do you guarantee that every payment gateway class has exactly these methods? You use an interface.
What is an Interface?
An interface is a contract. It says: any class that implements this interface must have these specific methods. The interface does not provide any implementation — just the list of method signatures that must exist.
Real world analogy: Think of an interface like a job description. The job description for a Driver says: must be able to start the vehicle, steer, and stop. Whether you are driving a car, a bus, or a truck — different vehicles, different internal mechanics — you must be able to do all three things. The job description enforces the contract without caring how each vehicle implements it internally.
<?php
interface PaymentGateway {
public function charge($amount, $currency);
public function refund($transaction_id);
public function get_transaction_id();
}
?>
An interface only contains method signatures — the method name, parameters, and return nothing. No code inside the methods. No properties. Just the contract.
Implementing an Interface
<?php
interface PaymentGateway {
public function charge($amount, $currency);
public function refund($transaction_id);
public function get_transaction_id();
}
class RazorpayGateway implements PaymentGateway {
private $transaction_id;
public function charge($amount, $currency) {
$this->transaction_id = "RPY-" . rand(100000, 999999);
echo "Charged Rs. $amount via Razorpay. Transaction: $this->transaction_id";
echo "<br>";
}
public function refund($transaction_id) {
echo "Refund initiated on Razorpay for transaction: $transaction_id";
echo "<br>";
}
public function get_transaction_id() {
return $this->transaction_id;
}
}
class PayPalGateway implements PaymentGateway {
private $transaction_id;
public function charge($amount, $currency) {
$this->transaction_id = "PPL-" . rand(100000, 999999);
echo "Charged $currency $amount via PayPal. Transaction: $this->transaction_id";
echo "<br>";
}
public function refund($transaction_id) {
echo "Refund initiated on PayPal for transaction: $transaction_id";
echo "<br>";
}
public function get_transaction_id() {
return $this->transaction_id;
}
}
function process_payment(PaymentGateway $gateway, $amount) {
$gateway->charge($amount, "INR");
echo "Transaction ID: " . $gateway->get_transaction_id();
echo "<br>";
}
$razorpay = new RazorpayGateway();
$paypal = new PayPalGateway();
process_payment($razorpay, 1999);
process_payment($paypal, 2999);
?>
Output:
Charged Rs. 1999 via Razorpay. Transaction: RPY-847291 Transaction ID: RPY-847291 Charged INR 2999 via PayPal. Transaction: PPL-192847 Transaction ID: PPL-192847
The process_payment() function accepts any object that implements PaymentGateway. It does not care whether it is Razorpay or PayPal — it just knows both of them have the charge() and get_transaction_id() methods because the interface guarantees it.
If you create a new StripeGateway class but forget to implement the refund() method, PHP throws a fatal error immediately. The interface enforces the contract strictly.
This is called polymorphism — different classes being used interchangeably because they all follow the same interface contract.
In Laravel: interfaces are used everywhere. Laravel's Cache, Mail, Queue, and Storage systems all work through interfaces. This is why you can switch from file-based caching to Redis caching by changing one line in a config file — both implement the same interface.
Part 2 — Abstract Classes
The Difference Between Interface and Abstract Class
An interface is a pure contract — no implementation at all. An abstract class sits in the middle — it can have some implemented methods and some unimplemented methods.
Think of it this way. An interface says: you must have these methods, figure out the implementation yourself. An abstract class says: here are some methods I have already implemented for you, but you must implement these specific ones yourself.
Real world analogy: An abstract class is like a house blueprint that already has the foundation and walls drawn in — the structural parts are fixed. But the interior layout, the rooms, the furniture placement — those are left for the specific house design to decide. You cannot build directly from an abstract blueprint. You must extend it and fill in the missing pieces.
<?php
abstract class Shape {
protected $color;
public function __construct($color) {
$this->color = $color;
}
abstract public function area();
abstract public function perimeter();
public function describe() {
echo "This is a $this->color shape.";
echo "<br>";
echo "Area: " . $this->area();
echo "<br>";
echo "Perimeter: " . $this->perimeter();
echo "<br>";
}
}
class Circle extends Shape {
private $radius;
public function __construct($color, $radius) {
parent::__construct($color);
$this->radius = $radius;
}
public function area() {
return round(M_PI * $this->radius ** 2, 2);
}
public function perimeter() {
return round(2 * M_PI * $this->radius, 2);
}
}
class Rectangle extends Shape {
private $width;
private $height;
public function __construct($color, $width, $height) {
parent::__construct($color);
$this->width = $width;
$this->height = $height;
}
public function area() {
return $this->width * $this->height;
}
public function perimeter() {
return 2 * ($this->width + $this->height);
}
}
$circle = new Circle("red", 7);
$rectangle = new Rectangle("blue", 10, 5);
$circle->describe();
echo "<br>";
$rectangle->describe();
?>
Output:
This is a red shape. Area: 153.94 Perimeter: 43.98
This is a blue shape. Area: 50 Perimeter: 30
The abstract keyword on area() and perimeter() means: every class that extends Shape must implement these methods. Shape provides the shared describe() method — both Circle and Rectangle get it for free through inheritance.
You cannot do new Shape() directly — PHP will throw an error. You can only instantiate the concrete child classes.
Interface vs Abstract Class — When to Use Which
Use an interface when you want to define a contract that completely unrelated classes must follow. A Car and a Bird are very different things — but both can implement a Moveable interface.
Use an abstract class when you have a group of related classes that share some common implementation but must each provide specific behavior. Circle and Rectangle are both Shapes — they share the describe() method but each calculates area differently.
In Laravel: the base Controller class is abstract. Eloquent's Model class has abstract-like behavior. Middleware classes implement an interface called Handle. You will see both constantly.
Part 3 — Namespaces
The Problem Namespaces Solve
As a project grows, you end up with hundreds of PHP files and classes. Name conflicts become a real problem. What if you have a User class in your authentication system and another User class in your admin panel? PHP cannot have two classes with the same name loaded at the same time.
Real world analogy: Think of namespaces like addresses. There can be a "Main Street" in Delhi and a "Main Street" in Mumbai — same street name, two completely different locations. The city name distinguishes them. Namespaces work the same way — they give your classes a unique address so they never conflict with each other.
<?php
namespace App\Auth;
class User {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function get_role() {
return "Authenticated User";
}
}
?>
<?php
namespace App\Admin;
class User {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function get_role() {
return "Administrator";
}
}
?>
Both files have a class called User. But they live in different namespaces — App\Auth and App\Admin. PHP treats them as completely separate classes.
Using Namespaced Classes
<?php
require_once "AuthUser.php";
require_once "AdminUser.php";
use App\Auth\User as AuthUser;
use App\Admin\User as AdminUser;
$auth_user = new AuthUser("Gagan");
$admin_user = new AdminUser("Rahul");
echo $auth_user->name . " — " . $auth_user->get_role();
echo "<br>";
echo $admin_user->name . " — " . $admin_user->get_role();
?>
Output:
Gagan — Authenticated User Rahul — Administrator
The use keyword imports a namespaced class so you can refer to it by a shorter name. as gives it an alias when two classes share the same short name.
In Laravel: every file starts with namespace App\Http\Controllers or namespace App\Models or similar. Every time you open a Laravel controller or model, you see use statements at the top importing other classes. Now you know exactly what those mean.
Part 4 — Autoloading With Composer
Right now we use require_once to include every file we need. In a large project with hundreds of classes, this becomes unmanageable — you would need dozens of require_once statements at the top of every file.
Autoloading solves this. With autoloading, PHP automatically loads the right class file the moment you use that class — no manual require_once needed.
Composer is PHP's dependency manager and it handles autoloading for us. Laravel uses Composer — you will install it before starting Laravel. Let us set it up now so you are ready.
Install Composer:
Go to getcomposer.org and download the Windows installer. Run it and follow the steps. After installation, open a new Command Prompt and type:
composer --version
You should see a version number. Composer is installed.
Setting Up Autoloading in a Project:
In your phplearning folder, create a file called composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
This tells Composer: any class in the App namespace should be loaded from the src/ folder.
Create the folder src/ inside phplearning. Now create a class file src/Product.php:
<?php
namespace App;
class Product {
public $name;
public $price;
public function __construct($name, $price) {
$this->name = $name;
$this->price = $price;
}
public function get_formatted_price() {
return "Rs. " . number_format($this->price, 2);
}
}
?>
Now open Command Prompt, navigate to your phplearning folder, and run:
composer dump-autoload
Composer generates an autoload file. Now create index_autoload.php in phplearning:
<?php
require_once "vendor/autoload.php";
use App\Product;
$product = new Product("Mechanical Keyboard", 2499);
echo $product->name . " — " . $product->get_formatted_price();
?>
Visit http://localhost:8080/phplearning/index_autoload.php
Output: Mechanical Keyboard — Rs. 2,499.00
No manual require_once for the Product class. Composer loaded it automatically the moment you used it. This is exactly how Laravel works — you never manually include class files in Laravel. Composer's autoloader handles everything.
PSR-4 is a PHP standard that maps namespaces to folder structures. App\Models\User maps to src/Models/User.php. App\Http\Controllers\UserController maps to src/Http/Controllers/UserController.php. Laravel follows this standard throughout its entire codebase.
Putting It All Together — What You Now Know
Let us take a step back and look at what you have learned across all 14 Core PHP episodes.
Variables, data types, operators — how PHP stores and works with data.
Conditionals and loops — how PHP makes decisions and repeats tasks.
Arrays and functions — how PHP manages collections and reusable logic.
Forms, sessions, cookies — how PHP interacts with users and remembers state.
MySQL with PDO and prepared statements — how PHP stores and retrieves data permanently.
OOP — classes, objects, constructors, access modifiers, encapsulation, inheritance, interfaces, abstract classes.
Namespaces and autoloading — how PHP organizes large codebases.
This is a complete foundation. Most developers who struggle with Laravel struggled because they skipped this foundation. You did not skip it.
What Did We Learn in This Post?
Interfaces define a contract — a list of methods that any implementing class must provide. They enable polymorphism — different classes used interchangeably through a shared contract.
Abstract classes sit between interfaces and regular classes — they can have both implemented and unimplemented methods. You cannot instantiate an abstract class directly.
Use an interface for unrelated classes sharing a behavior contract. Use an abstract class for related classes sharing partial implementation.
Namespaces give classes a unique address to prevent naming conflicts in large projects. The use keyword imports namespaced classes. Laravel uses namespaces in every single file.
Composer manages PHP dependencies and handles autoloading via PSR-4. Every class in the right namespace and folder is loaded automatically — no manual require_once needed. Laravel is entirely Composer-based.
What is Coming in Episode 15?
Episode 15 is a major milestone. Core PHP is complete. We start Laravel.
We will install Laravel using Composer, understand what gets created, start the development server, and explore the folder structure in detail. Every folder, every file — what it is, what it does, and why it exists.
This is where everything accelerates. The foundation is solid. Now we build on it.
See you in the next one.
Next Episode: Installing Laravel and Understanding the Project Structure
This is Episode 14 of the PHP and Laravel — Zero to Hero series.
No comments:
Post a Comment