SITERAW

Object-Oriented Programming in PHP (2/2)

Welcome to this second chapter on object-oriented programming, or OOP for short, in PHP! In the previous chapter, we covered the theory. Great! It's even essential.

But let's be honest, learning everything without getting to do anything isn't exactly exciting. So we're going to fix that with this more hands-on chapter. We're diving into constructors, destructors, inheritance, and encapsulation... scary words, maybe, but they're some of the most useful tools in modern object-oriented programming.

So let's get to it!

Constructor, Destructor, and Other Special Functions

On top of the regular functions we created in our Member class in the previous chapter, PHP has a few "special" functions you should know about. These are called magic methods.

You can easily spot them because their names start with two underscores (__). For example: __construct, __destruct, __get, and so on.

We're going to focus on the two most important ones: the constructor and the destructor.

The constructor: __construct

When you create a new object, like we did earlier, it starts out completely empty. Its member variables don't hold anything. So, our member had no username, no email, nothing.

$member = new Member(); // The member is empty

But here's the thing — whenever you create an object with new, PHP automatically looks inside the class for a function named __construct. We hadn't defined one before, so PHP just created an empty object for us by default.

The job of a constructor is — surprise! — to construct the object, meaning it prepares it for first use. In our case, we'd probably want to pull the member's data from the database and fill in those variables right from the get-go.

<?php
class Member
{
    public function __construct($memberId)
    {
        // Fetch member info from the database
        // SELECT username, email, signature, active FROM members WHERE id = ...
        
        // Assign values to the member variables
        $this->username = $data['username'];
        $this->email = $data['email'];
        // and so on...
    }

... ?>

Our constructor takes one parameter: the member ID. From there, we can load that member's info from the database and insert it into the object: $this->username, $this->email, etc.

And since our constructor expects a parameter, we now need to pass an ID when we create the object:

$member = new Member(47); // Member #47 is loaded!

Our Member #47 is ready to go! 😄

It already contains the right username, email, and more. It's up to you to make sure that if you change, say, the username later on, that change also updates in the database.

The destructor: __destruct

Less commonly used, but still handy in some cases, the destructor is a function that PHP automatically calls when the object is destroyed.

But when is an object destroyed?

You can destroy an object manually using unset():

unset($member);

If you don't do that, the object will be destroyed automatically at the end of whatever context it was created in. If it was created inside a page (like in index.php), it'll be destroyed when the page finishes executing.

That's when the destructor kicks in. Its role is to perform any final cleanup operations before the object disappears.

For example, the PDO class uses its destructor to close the connection to the database. It sends a "Connection closed" signal to the DB server.

In the case of our Member class, we might not have anything important to clean up. But just to test how a destructor works, you can create one that simply displays a message when the object is about to be destroyed:

public function __destruct()
{
    echo 'This object is about to be destroyed!';
}

You'll see that the message appears at the end of the page. If you've created multiple objects, you'll see one message for each one — as they all get destroyed!

Other magic methods

There are quite a few other magic methods in PHP, though they're less commonly used: __get(), __set(), __call(), __sleep(), __wakeup()... These let you control other phases in the life of your object.

We won't go into detail on them here, but if you're curious and want to explore further, check out the official documentation on PHP's magic methods.

Inheritance in PHP

Inheritance is probably the most important concept in object-oriented programming. It's what gives OOP its full power. It lets you reuse classes to build new ones. You take basic "building block" classes and build more complete classes from them.

How do you recognize inheritance?

That's THE big question. Some people have been so scarred by inheritance in programming courses that they see it everywhere. Others (especially beginners) keep wondering whether inheritance should be used or not. But there's nothing mystical about it — it's actually very easy to tell whether two classes are related by inheritance.

How? Just follow this simple rule:

There's inheritance when you can say: "A is a B."

Don't panic — this isn't math class. 😄

Take a really simple example. You can say, "An admin is a member," or "A moderator is a member." So you can create inheritance like this: "The Admin class inherits from the Member class," "The Moderator class inherits from the Member class."

To get the feel of it, here are a few more good examples where inheritance makes sense:

  • A car is a vehicle (Car inherits from Vehicle)
  • A bus is a vehicle (Bus inherits from Vehicle)
  • A sparrow is a bird (Sparrow inherits from Bird)
  • A crow is a bird (Crow inherits from Bird)
  • A surgeon is a doctor (Surgeon inherits from Doctor)
  • A diplodocus is a dinosaur (Diplodocus inherits from Dinosaur)
  • And so on...

On the other hand, you can't say "A dinosaur is a diplodocus," or "A bus is a bird." So no inheritance there — or at least, not any that makes sense. 😉

Implementing inheritance in PHP

We're going to create a new Admin class that's based on the Member class. It will have all the variables and functions from Member, plus some new ones of its own.

Create a file called Admin.class.php (remember: one file per class!) and insert the following starter code:

<?php
include_once('Member.class.php');

class Admin extends Member {

} ?>

The new keyword here is extends, which means "extends." Translation: the Admin class extends (the capabilities of) the Member class. That's inheritance: the Admin class now includes everything from Member, and we can add new features specific to admins.

For this to work, PHP needs to know about the Member class beforehand — so it's essential to include Member.class.php at the top.

Now let's add some functionality that's specific to admins. For example, admins can choose the color their username is displayed in. So we'll give them a $color variable and functions to get and set it:

<?php
include_once('Member.class.php');

class Admin extends Member { private $color;

public function setColor() { // ... }

public function getColor() { // ... } } ?>

So now we have two classes: Member and Admin.

  • With Member, you can manage a username, email, signature, and whether the account is active.
  • With Admin, you can do all that too... plus extra things like setting a username color.

Some vocabulary here: we say Member is the parent class, and Admin is the child class. It's the child that inherits from the parent — that's the inescapable logic of a programmer. 😉

Now, in our index.php, we can create both regular members and admins:

<?php
$member = new Member(31); // Has a username, email, etc.
$siteMaster = new Admin(2); // Same as a member + color support

$member->setUsername('SmallBruv'); // OK $siteMaster->setUsername('BigBossMan'); // OK

$member->setColor('Red'); // Not allowed (a member doesn't have a color) $siteMaster->setColor('Red'); // OK ?>

With minimal effort, we've created a new class that reuses an existing one. We can still call setUsername() like before, but now we can also do new things like set a display color. 😄

Class Access Rights

To wrap up our introduction to object-oriented programming, there's one more big concept I need to introduce: encapsulation. OOP has a lot of rules, and nobody's forcing you to follow them. Sometimes they seem a bit heavy or even annoying. That's why some people end up writing messy object-oriented code.

Still, if there's one rule to stick to in OOP, it's encapsulation. But before explaining what that means, let me introduce the idea of access rights.

What are "access rights," anyway? I mean, I wrote this code, I have the right!!! >:(

Remember those little keywords we used in front of our variables and functions earlier? Yep, I'm talking about public and private. These are what we call access modifiers — they define whether someone using the class has the right to access a part of it or not.

There are 3 types of access modifiers you need to know:

  • public: everyone can access it.
  • private: nobody (except the class itself) can access it.
  • protected: like private, but child classes can access it.

Let's try to put all this in human terms, shall we? 😄

Here's a simplified version of our Member class:

<?php
class Member
{
    private $username;
    private $email;
    private $signature;
    private $active;

public function getUsername() { }

public function setUsername($newUsername) { } } ?>

As you can see, the functions are public, and the variables are private. Nothing's stopping us from doing the opposite — but for variables, that's really not recommended, as you'll soon see.

So what does this mean in practice? It means that someone using the class through an object (like in index.php) can only access the public parts — not the private ones:

<?php
$member = new Member(4);
$member->setUsername('BigBossMan'); // OK, setUsername is public
$member->username = 'BigBossMan';   // Not allowed, $username is private
?>

So it's up to you to decide, using public, private, or protected, whether users of your class can access each function or variable.

What about protected?

It's just like private, except that child classes can still access the protected elements. For example, if $email is declared as protected in Member, then the Admin class can access it too. If it were private, that wouldn't be possible.

Encapsulation in OOP

Why all this trouble? Wouldn't it be simpler to just make everything public? Less hassle, right?

Well, if everything were public — including member variables — anyone could do this:

<?php
$member = new Member(4);
$member->email = 'RandomGarbage';
?>

And clearly, "RandomGarbage" is not a valid email address. I think we can all agree on that. 😅

To prevent people from messing up your objects, we've come up with a very simple rule called the encapsulation principle, which goes like this:

All class variables should always be private or protected. If you want to change them, you must go through setter functions. Period!

That's why we get into the habit of writing get and set functions — they let us validate input and prevent people from assigning junk to variables (like an invalid email). 😉

There are cases, though, where we create private member functions. These are internal functions that users shouldn't call directly.

Generally, it's better to use protected rather than private — especially if you plan on using inheritance. They behave the same, but protected gives you more flexibility if child classes come into play later.

The whole goal of encapsulation is to hide the inner workings of a class from the people using it. When you create an object, you shouldn't have to worry about what variables it contains or how they're structured. You're just someone pushing buttons to make the object do stuff. That's why you go through functions to make changes.

To force users to "push the buttons" rather than "mess with dangerous chemicals they don't understand," we use access rights. So, most functions are public (except for the ones used internally), and variables are always private or protected, so users can't mess them up.

If you understand and remember this principle, you'll be well on your way to writing solid object-oriented code. 😊

That's the end of our introduction to object-oriented programming in PHP. We've covered most of the basics, but OOP goes much deeper. As I said at the start, this probably still feels pretty abstract. I know the feeling — it's a mix of frustration and fascination for something you don't fully understand yet. 😄

Take your time and read through both chapters again if there are parts you're still unsure about. And if needed, hop over to the PHP forum at SiteRaw.com — they'll be happy to help, whether it's about OOP or anything else.

How to Build a Website in HTML and CSS

Enjoyed this PHP & MySQL course?

If you liked this lesson, you can find the book "How to Build a Website in HTML and CSS" from the same authors, available on SiteRaw, in bookstores and in online libraries in either digital or paperback format. You will find a complete PHP & MySQL workshop with many exclusive bonus chapters.

More information