From class User to new User() — understanding PHP objects without the usual OOP jargon

If you have been writing PHP for some time, you have probably written this line more times than you can remember:

$user = new User();

It looks incredibly simple.

We have a class called User, we use the new keyword, and now we have a $user object.

Done.

But here’s the interesting part.

What actually happened when PHP executed that line?

Where did this object come from?

Where is its name stored?

Does PHP create a complete copy of the class every time we use new?

If we create 100 User objects, do we also get 100 copies of the sayHello() method?

And perhaps the most confusing question for beginners:

What exactly is $this?

We use it everywhere:

$this->name

But what is $this actually pointing to?

These questions are not just about PHP syntax.

They are about understanding what an object really is.

So in this article, let’s slow things down and build the mental model from the ground up.

No Laravel.

No framework magic.

No complicated engine internals.

Just raw PHP, classes, objects, properties, methods, and what happens when an object is created.

Let’s Start With a Class

Consider a very simple class:

class User
{
public string $name;

public function sayHello(): string
{
return "Hello, {$this->name}";
}
}

At first glance, we might say:

“We created a User.”

But technically, that’s not what happened.

We created a class definition.

That’s a very important distinction.

The class is telling PHP:

“If someone creates a User object, that object can have a name, and it can perform a sayHello() operation."

So the class describes the structure and behavior.

But there is no actual user yet.

We haven’t created:

Siam
Rahim
Karim

or anyone else.

We have only described what a User is supposed to look like and what it can do.

You can think about it like this:

User Class
┌────────────────────┐
│ name │
│ sayHello() │
└────────────────────┘

It’s a definition. It’s a plan. It’s a description.

It is not yet an object.

Then We Write new

Now we write:

$user = new User();

This is the moment where things become interesting.

The new keyword tells PHP:

“I want an actual object based on the User class."

Conceptually, PHP now creates an instance of that class.

So we can think of it like this:

User class
│
│ new User()
▼
User object

And now we have an actual object that can hold its own state.

For example:

$user->name = "Siam";

Now our object has state:

User Object
┌─────────────────┐
│ name = "Siam" │
└─────────────────┘

This is one of the biggest differences between a class and an object.

The class describes.

The object exists.

So What Is an Object?

Let’s make this even simpler.

Suppose our class is:

class User
{
public string $name;
}

And we create:

$user1 = new User();
$user2 = new User();

We now have two different objects.

Even though both objects were created from the same class, they are separate instances.

We can do:

$user1->name = "Siam";
$user2->name = "Rahim";

Now:

$user1
┌─────────────────┐
│ name = "Siam" │
└─────────────────┘

$user2
┌─────────────────┐
│ name = "Rahim" │
└─────────────────┘

They are both User objects. But they don’t share the same name value.

Changing one doesn’t automatically change the other.

That’s because instance properties belong to the individual object.

The Class Defines the Property, the Object Holds the Value

This distinction is worth understanding properly.

When we write:

class User
{
public string $name;
}

we are defining that a User object can have a property called name.

We are not saying:

“Every User has the name Siam.”

We’re saying:

“Every User object has its own name property."

So when we create:

$user1 = new User();
$user2 = new User();

each object has its own instance state.

Then:

$user1->name = "Siam";
$user2->name = "Rahim";

gives each object a different value.

This is why objects are useful.

The same class can describe thousands of objects, while each object can maintain its own state.

What About Methods?

Now let’s talk about the other part of our class:

public function sayHello(): string
{
return "Hello, {$this->name}";
}

A method describes behavior.

The property represents something the object knows.

The method represents something the object can do.

So you can start thinking of an object like this:

Object
│
├── State
│ └── name
│
└── Behavior
└── sayHello()

This is a very useful mental model.

An object combines:

data + behavior

or, in more familiar PHP terms:

properties + methods

But Does Every Object Get a Copy of the Method?

This is probably one of the most important misconceptions to clear up.

Suppose we create:

$user1 = new User();
$user2 = new User();
$user3 = new User();

A beginner might imagine something like:

$user1
├── name
└── sayHello() code

$user2
├── name
└── sayHello() code

$user3
├── name
└── sayHello() code

In other words:

“PHP creates three objects, so PHP must copy the method three times.”

That’s not a good mental model.

The method definition belongs to the class.

The objects have their own instance state, but you should not think of the method’s source code as being physically copied into every object.

A better mental picture is:

User Class
┌────────────────────────┐
│ name │
│ │
│ sayHello() │
│ │
│ method definition │
└───────────┬────────────┘
│
┌─────────┼─────────┐
│ │ │
▼ ▼ ▼

Object Object Object
#1 #2 #3
name name name
= Siam = Rahim = Karim

The important idea is:

Objects have their own state; methods are defined by the class.

When you call:

$user1->sayHello();

PHP knows that $user1 is a User object, so it knows which class behavior to use.

Then What Is $this?

Now we arrive at one of the most important concepts in PHP OOP.

Look at this method again:

public function sayHello(): string
{
return "Hello, {$this->name}";
}

What is $this?

Simply put:

$this refers to the current object whose method is being executed.

Let’s see why that matters.

Suppose:

$user1 = new User();
$user1->name = "Siam";

Then:

$user1->sayHello();

Inside sayHello(), $this refers to $user1.

So:

$this->name

means:

$user1->name

Conceptually.

Now suppose:

$user2 = new User();
$user2->name = "Rahim";

And we call:

$user2->sayHello();

Now $this refers to $user2.

So the same method:

return "Hello, {$this->name}";

can produce different results.

For $user1:

$this → $user1
$this->name → "Siam"

For $user2:

$this → $user2
$this->name → "Rahim"

And this is where object-oriented programming starts to become really interesting.

The method is the same, but the object providing the state is different.

The Same Method Can Behave Differently

Let’s put everything together:

class User
{
public string $name;

public function sayHello(): string
{
return "Hello, {$this->name}";
}
}

Now:

$user1 = new User();
$user1->name = "Siam";

$user2 = new User();
$user2->name = "Rahim";

echo $user1->sayHello();
echo $user2->sayHello();

The method definition is the same.

But the result is different.

Why?

Because $this is different.

For the first call:

$user1->sayHello();

$this means:

User object #1

For the second call:

$user2->sayHello();

$this means:

User object #2

So you can mentally translate:

$this->name

into:

“Give me the name belonging to the object that is currently executing this method."

That’s a much more useful way to understand $this than simply memorizing:

“$this means current object."

What Happens When a Constructor Exists?

Now let’s make object creation a little more realistic.

class User
{
public string $name;

public function __construct(string $name)
{
$this->name = $name;
}
public function sayHello(): string
{
return "Hello, {$this->name}";
}
}

Now we can write:

$user = new User("Siam");

Notice that we’re passing "Siam".

What happens?

Conceptually:

new User("Siam")
│
▼
Create User object
│
▼
Run __construct("Siam")
│
▼
$this->name = "Siam"
│
▼
Object is initialized

After that, we have:

User Object
┌─────────────────┐
│ name = "Siam" │
└─────────────────┘

So the constructor is not the thing that magically creates the class itself.

The new operation creates the object instance, and the constructor is used to initialize that newly created object.

That distinction is important.

Creation and Initialization Are Not the Same Thing

This is another concept that becomes clearer once you slow down.

Consider:

$user = new User("Siam");

There are conceptually two things happening:

1. Creation

PHP creates an instance of User.

2. Initialization

The constructor receives "Siam" and uses it to initialize the object's state.

So:

new User("Siam")

can be thought of as:

Create object
↓
Initialize object
↓
Give object back

The constructor is therefore primarily about getting the new object’s initial state into a valid condition.

What Exactly Is $user?

Now let’s look at this:

$user = new User("Siam");

A common beginner question is:

“Is $user the object?"

For everyday PHP programming, we normally say:

“$user is a variable containing a reference to the object.”

That’s a more useful mental model.

Think of it like this:

$user
│
│ refers to
▼
┌─────────────────┐
│ User Object │
│ │
│ name = "Siam" │
└─────────────────┘

So $user is not the class.

And it is not simply a copy of the object’s contents.

It gives your PHP code a way to access that object.

That’s why this works:

$user->name

and:

$user->sayHello();

What Happens When We Assign One Object Variable to Another?

This is where things can become a little surprising.

Suppose:

$user1 = new User("Siam");
$user2 = $user1;

A beginner might expect PHP to create a completely new object.

But that’s not what happens.

Both variables now refer to the same object.

Conceptually:

$user1 ───────┐
│
▼
┌───────────────┐
│ User Object │
│ name = Siam │
└───────────────┘
▲
│
$user2 ───────┘

So:

$user2->name = "Rahim";

will also affect what you see through $user1, because both variables refer to the same object.

For example:

$user1 = new User("Siam");
$user2 = $user1;

$user2->name = "Rahim";
echo $user1->name;

The output will be:

Rahim

This is an extremely important concept when working with PHP objects.

What If We Actually Want Another Object?

Then we can use clone.

For example:

$user1 = new User("Siam");
$user2 = clone $user1;

Now PHP creates another object based on the first object’s current state.

Conceptually:

$user1
│
▼
┌─────────────────┐
│ User Object #1 │
│ name = "Siam" │
└─────────────────┘
$user2
│
▼
┌─────────────────┐
│ User Object #2 │
│ name = "Siam" │
└─────────────────┘

Now they are separate objects.

So:

$user2->name = "Rahim";

doesn’t change:

$user1->name

The distinction is:

$user2 = $user1;

means:

“Both variables refer to the same object.”

While:

$user2 = clone $user1;

means:

“Create another object based on this object’s state.”

Objects Can Contain Other Objects

An object doesn’t have to contain only strings, integers, or booleans.

An object can have another object as a property.

For example:

class Address
{
public string $city;

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

And:

class User
{
public string $name;
public Address $address;

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

Now:

$address = new Address("Dhaka");
$user = new User("Siam", $address);

Our object relationship now looks something like:

User Object
┌─────────────────────────┐
│ name = "Siam" │
│ │
│ address ────────────────┼──────┐
└─────────────────────────┘ │
▼
Address Object
┌────────────────┐
│ city = Dhaka │
└────────────────┘

This is a very important part of object-oriented design.

Objects can work together.

One object doesn’t need to know everything.

It can hold or work with another object that has its own responsibility.

But even here, the same fundamental idea remains:

Each object is an actual instance with its own state.

Properties and Methods: State vs Behavior

At this point, we can make a very useful distinction.

Consider:

class User
{
public string $name;

public function sayHello(): string
{
return "Hello, {$this->name}";
}
}

The property:

$name

represents state.

The method:

sayHello()

represents behavior.

So:

User
│
├── State
│ └── name = "Siam"
│
└── Behavior
└── sayHello()

This is one of the simplest ways to understand an object.

An object is not just “a variable with some data.”

It represents something that has:

  • some state
  • some behavior
  • and rules about how that state can be changed or used

That’s the heart of object-oriented programming.

What About Static Properties?

Now we need to make one important distinction.

Not every property belongs to an individual object.

Consider:

class User
{
public string $name;
public static int $count = 0;
}

Here:

$name

is an instance property.

It belongs to each object.

But:

$count

is static.

It belongs to the class-level state rather than to each individual object.

So:

$user1->name

is about a particular object.

While:

User::$count

is about the class-level static property.

A simple mental model is:

Instance property
↓
belongs to an object

Static property
↓
belongs to the class

This distinction becomes important when designing classes because not every piece of information should be stored per object.

And Static Methods Are Different Too

Consider:

class MathHelper
{
public static function add(int $a, int $b): int
{
return $a + $b;
}
}

We can call:

$result = MathHelper::add(10, 20);

Notice something?

We didn’t create an object.

There is no:

$helper = new MathHelper();

And there is no $this inside that static method.

That’s because a static method is called in the context of the class rather than a particular object instance.

So this:

$user->sayHello();

is instance behavior.

While this:

MathHelper::add(10, 20);

is class-level behavior.

This gives us another useful mental separation:

Object-oriented instance world
↓
$this
properties
object state
instance methods

Class-level static world
↓
ClassName::
static properties
static methods

What Happens With Inheritance?

Now let’s take the idea one step further.

Suppose we have:

class User
{
public string $name;

public function sayHello(): string
{
return "Hello, {$this->name}";
}
}

And:

class Admin extends User
{
public function deleteUser(): string
{
return "User deleted";
}
}

Now:

$admin = new Admin();

What is $admin?

It is an object of the Admin class.

But because Admin extends User, it also has access to the inherited behavior and properties defined by User, subject to PHP's visibility and inheritance rules.

Conceptually:

User
│
├── name
└── sayHello()
│
│ inherited by
▼
Admin
│
└── deleteUser()

So inheritance allows one class to build upon another class’s definition.

But once again, when we write:

$admin = new Admin();

we are creating an actual Admin object.

The class hierarchy tells PHP what that object can have and what behavior is available to it.

What About Interfaces?

Interfaces are another place where beginners sometimes get confused.

Consider:

interface PaymentGateway
{
public function pay(float $amount): bool;
}

This doesn’t create an object.

It doesn’t even provide the actual implementation of pay().

Instead, it defines a contract.

A class can implement it:

class BkashGateway implements PaymentGateway
{
public function pay(float $amount): bool
{
return true;
}
}

Then:

$gateway = new BkashGateway();

Now an object is created.

The interface helped define what behavior the class must provide.

So we can distinguish:

Class
→ defines implementation
Object
→ actual instance
Interface
→ defines a contract

Keeping these three ideas separate makes PHP OOP much easier to understand.

What Happens to the Object Later?

An object doesn’t necessarily live forever.

At some point, PHP no longer needs it.

When an object becomes unreachable and is eligible for cleanup, PHP’s memory management can reclaim the memory associated with it.

You may also define a destructor:

class User
{
public function __destruct()
{
echo "Object is being destroyed";
}
}

The destructor is called when PHP destroys the object.

However, it’s important not to think of __destruct() as a precise manual memory-management command.

PHP manages object lifetime and memory for you.

Your job is usually to define what should happen when the object is being destroyed, particularly when cleanup of resources is relevant.

So the lifecycle is roughly:

Class definition
↓
new User()
↓
Object created
↓
Constructor runs
↓
Object is used
↓
Object becomes unreachable
↓
PHP can destroy it
↓
Destructor may run

So What Does “Object Creation” Really Mean?

Now let’s return to our original line:

$user = new User("Siam");

We can finally describe it more accurately.

PHP sees:

new User("Siam")

and conceptually performs a sequence like:

1. Identify the User class
↓
2. Create a new User instance
↓
3. Prepare the object's instance state
↓
4. Run the constructor
↓
5. Initialize the object
↓
6. Return access to the object
↓
7. Store that reference in $user

So after:

$user = new User("Siam");

we can think of the result as:

User Class
┌─────────────────────────┐
│ name │
│ sayHello() │
└────────────┬────────────┘
│
│ creates
▼
User Object
┌─────────────────────────┐
│ name = "Siam" │
└────────────┬────────────┘
▲
│
│ refers to
│
$user

That is the mental model we want.

One More Important Thing: The Class Is Not “Running”

Sometimes we casually say:

“PHP runs the class.”

That’s not really the best way to think about it.

A class definition primarily describes what an object of that class looks like and what it can do.

When you write:

class User
{
...
}

you’re defining the class.

When you write:

$user = new User();

you’re creating an object.

And when you write:

$user->sayHello();

you’re asking that object to execute one of its methods.

So these are three different moments:

class User { ... }
↓
Define the class
new User()
↓
Create an object
$user->sayHello()
↓
Execute behavior on that object

Keeping these three things separate removes a lot of OOP confusion.

The Most Useful Mental Model

If you forget everything else from this article, remember this:

CLASS
┌─────────────────────┐
│ Defines │
│ │
│ Properties │
│ Methods │
│ Rules │
└──────────┬──────────┘
│
new User()
│
┌────────┼────────┐
▼ ▼ ▼
Object Object Object
#1 #2 #3
state state state
↓ ↓ ↓
Siam Rahim Karim

The class is the definition.

new creates an instance.

Each object has its own instance state.

Methods are defined by the class rather than being thought of as a separate source-code copy inside every object.

And $this tells the method:

“Which object am I currently working with?”

The Real Beauty of $this

Let’s go back to our tiny example one last time:

class User
{
public string $name;

public function sayHello(): string
{
return "Hello, {$this->name}";
}
}

Now create two objects:

$user1 = new User();
$user1->name = "Siam";

$user2 = new User();
$user2->name = "Rahim";

Then:

$user1->sayHello();

Inside the method:

$this

means:

$user1

And when:

$user2->sayHello();

runs:

$this

means:

$user2

Same class.

Same method.

Different object.

Different state.

Different result.

That’s the point.

The method doesn’t need to know whether the user is Siam, Rahim, or Karim.

It simply works with:

$this

— the object that is currently calling the method.

And that’s one of the fundamental ideas that makes object-oriented programming so powerful.

Final Mental Picture

When you see:

$user = new User("Siam");

don’t just read it as:

“Create a User.”

Try to visualize the whole process:

User
Class Definition
┌─────────────────────┐
│ name │
│ sayHello() │
└──────────┬──────────┘
│
│ new User("Siam")
▼
┌──────────────────┐
│ User Object │
│ │
│ name = "Siam" │
└────────┬─────────┘
▲
│
│ reference
│
$user

Then when you write:

$user->sayHello();

think:

$user
↓
User Object
↓
sayHello()
↓
$this = current User Object
↓
$this->name
↓
"Siam"

Once this picture becomes clear, a lot of PHP OOP syntax stops feeling mysterious.

You no longer see:

$this->name

as some strange piece of PHP syntax.

You see it as:

“The name belonging to the object that is currently executing this method."

And you no longer see:

new User()

as just a line of code you have memorized.

You see it as:

“Create an actual instance of the User class, initialize it, and give me access to that object."

That’s the mental model that makes the rest of PHP OOP much easier to understand.

One Last Takeaway

Object-oriented programming becomes much easier when you stop thinking only in terms of syntax.

Instead of memorizing:

class
new
$this
extends
implements
clone

try to see the relationships between them:

CLASS
│
│ describes
▼
OBJECT
│
├── has STATE
│ └── properties
│
└── has BEHAVIOR
└── methods
│
└── $this
↓
current object

A class tells PHP what an object can be.

An object is the actual instance.

Properties represent the object’s state.

Methods represent its behavior.

new creates an object.

The constructor initializes it.

And $this gives a method access to the particular object currently using that behavior.

Once you genuinely understand that relationship, PHP OOP stops looking like a collection of keywords.

It starts looking like a system.

And that’s when things get interesting.