# Deep Dive into Classes and Objects in PHP

*Never used a class before? Read the* [*introduction to OOP in PHP*](https://linu.us/introduction-to-object-oriented-programming-in-php) *first.*

Hey again!

In the last post, we created our first class and discovered some benefits of using OOP in PHP. However, in this post, we'll dive deeper into classes and what we can do with them. So, let's get to work!

## Class Properties and Methods

We'll use the following class as starting point:

```php
<?php

class User {

}
```

### Properties

Properties are variables attached to an instance of a class. For example, every user has a name. So, we can add a $name property to the class:

```php
class User {
    public $name = "John";
}
```

We can access these properties using the arrow syntax:

```php
$user = new User;
echo $user->name; // "John"
```

We can also modify the property:

```php
$user = new User;
$user->name = "John Doe";
echo $user->name; // "John Doe"
```

Just like arguments of functions, we can also add type declarations to our properties to ensure type safety:

```php
<?php
declare(strict_types=1);

class User {
    public string $name = "John";
}
```

Now, if we assign a different type than we specified in the class, we will get an error:

```php
$user = new User;
$user->name = 10;
// Fatal error: Uncaught TypeError:
// Cannot assign int to property User::$name of type string
```

We can also define a property without initialising it:

```php
class User {
    public string $name;
}
```

A common use case is to define properties and then initialise them with values in the class constructor.

## Methods

Methods are functions attached to an instance of a class. Inside a method, we have access to the current instance of the class and can access and modify the properties and call other methods.

```php
class User {
    public string $name = "John";

    public function greet() {
        echo "Hello!";
    }
}

$user = new User;
$user->greet(); // "Hello!"
```

The variable `$this` references the current instance of the class. So if we want to use the user's name in the greeting, we can do so by referencing the `$this->name`:

```php
class User {
    public string $name = "John";

    public function greet() {
        echo "Hello " . $this->name . "!";
    }
}

$user = new User;
$user->greet(); // "Hello John!"
```

Like normal functions, methods can also have arguments, type-hinted arguments, and return types:

```php
class User {
    public string $name = "John";

    public function greet(): void {
        echo "Hello " . $this->name . "!";
    }

    public function sayHello(string $name): string {
        return "Hello $name";
    }
}

$user = new User;
$user->greet(); // "Hello John!"

$hello = $user->sayHello("Linus");
echo $hello; // "Hello Linus";
```

### The Class Constructor

The constructor is a [magic method](https://www.php.net/manual/en/language.oop5.magic.php) that gets executed every time a new instance of that class is constructed. For example:

```php
class User {
    public function __construct() {
        echo "New user created!";
    }
}

$user = new User; // "New user created!"
```

We can also add arguments to the constructor method which then need to be passed when creating a new instance:

```php
class User {
    public function __construct(string $name) {
        echo "New user created: " . $name;
    }
}

$user = new User("John"); // "New user created: John"
```

But for now, the `$name` variable is only available in the constructor. But we can define a property on the class and initialise it in the constructor:

```php
class User {
    public string $name;

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

$user = new User("John");
echo $user->name; // "John"
```

Note that `$name` refers to the value passed to the constructor, while `$this->name` refers to the property `$name` on the class.

### PHP 8: Constructor Property Promotion

The constructor is commonly used to initialise class properties, just like we did above. However, this requires a bunch of code just to assign a variable. Take a look at this:

```php
class User {
    public string $firstname;
    public string $lastname;
    public bool $admin;

    public function __construct(string $firstname, string $lastname, bool $admin) {
        $this->firstname = $firstname;
        $this->lastname = $lastname;
        $this->admin = $admin;
    }
}
```

Thankfully, PHP 8 introduced us to [constructor property promotion](https://www.php.net/manual/en/language.oop5.decon.php#language.oop5.decon.constructor.promotion): This allows us to refactor the code above like this:

```php
class User {
    public function __construct(
        public string $firstname,
        public string $lastname,
        public bool $admin,
    ) {
        //
    }
}
```

Very cool!

### The Class Destructor

There is a constructor that runs when constructing a new instance, so there also is a destructor that runs when an instance is destroyed.

```php
class User {
    public function __construct(
        public string $name,
    ) {
        echo "Constructed " . $this->name;
    }
  
    public function __destruct() {
        echo "Destructing " . $this->name;
    }
}

$user = new User("John");
// "Constructed John"

unset($user);
// "Destructing John"
```

### More Magic Methods

There are a lot more magic methods that we haven't covered yet, like clone, get, set, [and more](https://www.php.net/manual/en/language.oop5.magic.php).

If you stumble over a method starting with "\_\_" (two underscores), you just found a magic method. They are reserved to PHP (so don't create your own), but you can implement them, just like we did with the constructor and destructor.

## Visibility: Public, Private, and Protected

You probably have noticed that we added a `public` in front of all properties and methods we added to our classes to far. But what does it actually mean?

`public`, `private`, and `protected` define the visibility, or in other words, where the property/method can be accessed from:

### Public

Public means just what it says: It's public, so you can access it from both inside and outside the class:

```php
class User {
    public string $name = "John";

    public function __construct() {
        $this->doSomething(); // ✅ Works (call method from inside the class)
    }
    
    public function doSomething(): void {
        $name = $this->name; // ✅ Works (use property from inside the class)
    }
}

$user = new User;
echo $user->name; // ✅ Works (use property from outside the class)

echo $user->doSomething(); // ✅ Works (call method from outside the class)
```

### Private

Private means the opposite: It can only be accessed from inside the class and not the outside:

```php
class User {
    private string $name = "John";

    public function __construct() {
        $this->doSomething(); // ✅ Works (call method from inside the class)
    }
    
    private function doSomething(): void {
        $name = $this->name; // ✅ Works (use property from inside the class)
    }
}

$user = new User;
echo $user->name; // ❌ Fails (use property from outside the class)

echo $user->doSomething(); // ❌ Fails (call method from outside the class)
```

### Protected

Just like private, protected means you can't access the property/method from outside the class, but you can from the inside.

To understand the difference, we need an example with a class that extends another class:

```php
class User {
    public string $name "John";
    private string $password = "12345";
    protected int $balance = 200;
}

class SuperUser extends User {
    public function doSomething() {
        $name = $this->name; // ✅ Works
        $password = $this->password; // ❌ Fails
        $balance = $this->balance; // ✅ Works
    }
}

$superuser = new SuperUser;
$name = $superuser->name; // ✅ Works
$password = $superuser->password; // ❌ Fails
$balance = $superuser->balance; // ❌ Fails
```

As you might can see, the difference lies in the visibility to the subclass. If the User class defines a property that is protected, it can't be accessed from the outside, but a class that extends the User class can access it.

If a property is private, it is only accessible from inside that class, and cannot be accessed from the outside or a class that extends it.

*Don't worry if you don't yet understand how extends work, we'll take about that later in this series!*

| Visibility | Visible to own class | Visible to subclass | Visible to the outside |
| --- | --- | --- | --- |
| public | ✅ | ✅ | ✅ |
| protected | ✅ | ✅ | ❌ |
| private | ✅ | ❌ | ❌ |

Note: If you don't define the visibility, it will automatically be public.

## Getters and Setters

Now we know about properties, methods, and visibility, we can talk about getters and setters.

Getters and setters are functions that allow you to get and set something:

```php
class User {
    private string $name;

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

    public function setName(string $name): void {
        $this->name = $name;
    }
}

// Usage
$user = new User;
$user->setName("John");
echo "Hello " . $user->getName(); // Hello John
```

As you can see, since we now have two public methods to get and set the name, we can change the visibility of the `$name` property to private.

This in itself might not seem too helpful, but this enables us a few things:

### Validation

We can add validation to the setter:

```php
class User {
    private string $name;

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

    public function setName(string $name): void {
        if(strlen($name) < 2) {
            throw new Exception("Name must be at least 2 characters long");
        }

        $this->name = $name;
    }
}

// Usage
$user = new User;
$user->setName("J"); // ❌ Exception: "Name must be at least 2 characters long"
$user->setName("John"); // ✅ Works
```

### Hide Internal Representation of the Data

Let's say we have a first and last name. The getter can return the full name, while the data is actually stored in two different properties:

```php
class User {
    private string $firstname;
    private string $lastname;

    public function setFirstName(string $firstname): void {
        $this->firstname = $firstname;
    }

    public function setLastName(string $lastname): void {
        $this->lastname = $lastname;
    }

    public function getFullName(): string {
        return $this->firstname . ' ' . $this->lastname;
    }
}

// Usage
$user = new User;
$user->setFirstName("John");
$user->setLastName("Doe");
$fullname = $user->getFullName(); // "John Doe"
```

## Next Steps

To recap, in this post you have learned:

* How to create a class
    
* How to define and use properties and methods
    
* What the constructor is (and the destructor)
    
* The different visibilities (public, private, protected)
    
* Getters and setters
    

In the next part of this series, we'll dive into inheritance and the `extends` keyword (you have already seen an example in this post!)

But feel free to play around with classes before continuing. Understanding how classes work is fundamental for this series.

Whenever you feel ready, continue to the next part about [inheritance](https://linu.us/exploring-inheritance-in-php).
