Question
I am converting a PHP 5.3 library so it can run on PHP 5.2. One of the main issues is code that uses late static binding, such as:
return new static($options);
If I change that to:
return new self($options);
will it behave the same way?
What is the difference between new self and new static in PHP?
Short Answer
By the end of this page, you will understand how self and static behave differently in PHP class methods, especially when inheritance is involved. You will see why new self() creates an instance of the class where the code is written, while new static() creates an instance of the class that was actually called. This distinction is essential when working with parent and child classes, factory methods, and libraries that rely on extensibility.
Concept
In PHP, self and static can both refer to classes, but they are not resolved the same way.
selfrefers to the class where the method is defined.staticrefers to the class used at runtime to call the method.
This difference matters in inherited code.
new self()
When you write:
return new self($options);
PHP creates an object of the class that contains that code. It does not change based on which subclass called the method.
new static()
When you write:
return new static($options);
PHP uses late static binding. That means PHP waits until runtime and creates an object of the actual called class.
Why this matters
If a base class contains a factory method and a child class inherits it:
new self()always returns the base classnew static()can return the child class
This is very important in reusable libraries, ORMs, fluent APIs, and factory patterns, where parent classes are designed to be extended.
PHP version note
Late static binding was introduced in PHP 5.3. PHP 5.2 does not support static in this way. So replacing new static() with new self() may make the code run, but it can also change behavior in inherited classes.
Mental Model
Think of self and static like two different ways of reading a label.
selfsays: "Use the class name printed in this file."staticsays: "Use the class name of whoever actually called me."
Imagine a blueprint for a vehicle factory:
- With
new self(), the blueprint always says: "Build aVehicle." - With
new static(), the blueprint says: "Build whatever type of vehicle requested this method, such asCarorTruck."
So if Car inherits a method from Vehicle:
new self()still builds aVehiclenew static()builds aCar
That is the key idea behind late static binding.
Syntax and Examples
Here is the basic syntax:
self::methodName();
static::methodName();
new self();
new static();
Example 1: new self()
<?php
class Base {
public static function make() {
return new self();
}
}
class Child extends Base {}
$object = Child::make();
echo get_class($object);
Output:
Base
Even though Child::make() was called, the method is defined in Base, so new self() creates a Base object.
Example 2: new static()
<?php
class Base {
public static function make() {
return new static();
}
}
class Child extends Base {}
$object = Child::make();
echo get_class($object);
Output:
Child
This time, late static binding makes PHP create an object of the called class, which is Child.
Example 3: Why libraries use static
<?php
class Model {
protected $data;
public function __construct($data = array()) {
$this->data = $data;
}
public static function create($data) {
return new static($data);
}
}
class User extends Model {}
$user = User::create(array('name' => 'Ava'));
echo get_class($user);
Output:
User
This is useful for reusable parent classes that should return subclass instances automatically.
Step by Step Execution
Consider this example:
<?php
class Animal {
public static function build() {
return new static();
}
}
class Dog extends Animal {}
$pet = Dog::build();
echo get_class($pet);
Step by step
-
PHP defines the
Animalclass. -
PHP defines the
Dogclass, which extendsAnimal. -
The code calls:
Dog::build(); -
PHP looks for
build()inDog. -
Dogdoes not definebuild(), so PHP uses the inherited method fromAnimal. -
Inside
build(), the code says:return new static(); -
Because
staticuses late static binding, PHP checks which class made the call at runtime. -
The call came from
Dog, so PHP creates aDogobject. -
get_class($pet)returns:Dog
If you change it to new self()
<?php
class Animal {
public static function build() {
return new self();
}
}
class Dog extends Animal {}
$pet = Dog::build();
echo get_class($pet);
Now the result is:
Animal
Why? Because self points to the class where build() was defined: Animal.
Real World Use Cases
This difference appears in many real applications.
1. Factory methods
A parent class may provide a helper like create() or make():
class Response {
public static function make($data) {
return new static($data);
}
}
Subclasses such as JsonResponse or XmlResponse can inherit the method and still get the correct type.
2. ORM and Active Record models
Database libraries often use parent model classes:
$user = User::create($row);
If the base model uses new static(), the returned object is a User, not just a generic Model.
3. Fluent APIs and builders
Some class methods return a new instance of the current subclass.
4. Reusable library code
When writing extendable frameworks, base classes should often respect inheritance. static helps preserve subclass behavior.
5. Named constructors
Methods like fromArray(), fromJson(), or createFromConfig() often need to return the called class:
class Config {
public static function fromArray($data) {
return new static($data);
}
}
Real Codebase Usage
In real codebases, developers choose between self and static based on whether inheritance should affect the result.
Use self when the method is intentionally fixed to the base class
class Token {
public static function internalFactory() {
return new self();
}
}
This is appropriate when you do not want subclasses to change the returned type.
Use static when the class is designed for extension
class Collection {
public static function fromArray($items) {
return new static($items);
}
}
This is common in libraries that expect child classes.
Common patterns
- Named constructors:
fromArray(),fromString(),create() - Factory methods: return subclass instances correctly
- Extensible base models: ORMs, entities, records
- Framework base classes: reusable logic in parent classes
Migration consideration for PHP 5.2
If your PHP 5.3 code relies on new static(), replacing it with new self() is only safe if:
- the class is never subclassed, or
- returning the parent class is acceptable
If subclasses depend on correct late-bound instances, behavior will change and may break the library.
In PHP 5.2, developers sometimes worked around this by:
- passing class names explicitly
- overriding factory methods in each subclass
- using
get_class()or string class names carefully
Those workarounds are more manual and less elegant than late static binding.
Common Mistakes
1. Assuming self and static are interchangeable
They are not the same when inheritance is involved.
Broken expectation:
<?php
class ParentClass {
public static function make() {
return new self();
}
}
class ChildClass extends ParentClass {}
$obj = ChildClass::make();
echo get_class($obj); // ParentClass, not ChildClass
2. Replacing new static() with new self() during migration without checking subclass usage
This may silently change returned object types.
How to avoid it:
- inspect whether classes are extended
- inspect whether factory methods are inherited
- test returned object types with
get_class()orinstanceof
3. Using static in PHP 5.2
This syntax is not available for late static binding in PHP 5.2.
4. Forgetting constructor compatibility
If a parent method does this:
return new static($options);
then child classes must be able to accept the same constructor arguments, or object creation may fail.
5. Confusing self:: with static::
The same late-binding idea applies to static method calls too.
self::who();
static::who();
static::who() can resolve to an overridden child method, while self::who() points to the current class definition.
Comparisons
| Concept | self | static |
|---|---|---|
| Resolution time | Compile-time style class reference | Runtime class reference |
| Inheritance-aware | No | Yes |
new behavior | Creates the defining class | Creates the called class |
| Works with late static binding | No | Yes |
| Available in PHP 5.2 for this behavior | self works | Late static binding does not |
| Best for | Fixed base-class behavior | Extendable library behavior |
new self() vs new static()
class A {
public static function makeSelf() {
return new self();
}
public static function makeStatic() {
return new static();
}
}
class B extends A {}
echo get_class(B::makeSelf()); // A
echo get_class(B::makeStatic()); // B
When to choose each
- Choose
selfwhen the method should always return the exact class where it is defined. - Choose
staticwhen inherited classes should get their own type back.
Cheat Sheet
new self()= create an instance of the class where the code is writtennew static()= create an instance of the class used to call the methodselfdoes not support late static bindingstaticdoes support late static bindingnew static()requires PHP 5.3+- Replacing
new static()withnew self()can change behavior in subclasses
Quick example
class Base {
public static function a() { return new self(); }
public static function b() { return new static(); }
}
class Child extends Base {}
get_class(Child::a()); // Base
get_class(Child::b()); // Child
Rule of thumb
- Use
selffor fixed behavior - Use
staticfor inheritance-friendly behavior
Migration warning for PHP 5.2
If the original code depended on subclass-aware factories, self is not a true replacement for static.
FAQ
Does new self() always return the parent class?
It returns the class where that code is defined. If the method is defined in a parent class, then yes, it returns the parent class.
Does new static() work in PHP 5.2?
No. Late static binding was introduced in PHP 5.3.
Can I safely replace new static() with new self()?
Only if inheritance does not matter for that code path. Otherwise, the returned object type may change.
Why do frameworks and libraries often use static?
Because they are designed to be extended, and they want inherited methods to return subclass instances.
What is late static binding in simple terms?
It means PHP decides the class at runtime based on who made the call, rather than the class where the code was originally written.
Is the same idea true for self::method() and static::method()?
Yes. static::method() uses late static binding, while self::method() refers to the defining class.
What should I do in PHP 5.2 if I need subclass-aware factories?
You may need manual workarounds, such as overriding the method in each subclass or passing class names explicitly.
Mini Project
Description
Build a small PHP example that demonstrates how inherited factory methods behave with new self() and new static(). This project is useful because it shows the exact situation that often appears in reusable libraries and older PHP migrations.
Goal
Create parent and child classes, call inherited factory methods, and observe how the returned object type changes depending on whether self or static is used.
Requirements
- Create a parent class with one factory method that uses
new self() - Create a second factory method that uses
new static() - Create a child class that extends the parent class
- Call both factory methods from the child class
- Print the class name of each returned object
Keep learning
Related questions
Are PDO Prepared Statements Enough to Prevent SQL Injection in PHP?
Learn how PDO prepared statements prevent SQL injection in PHP, what they protect, and the mistakes that still leave MySQL apps vulnerable.
Can You Bind an Array to an IN Clause in PHP PDO?
Learn how PDO handles placeholders in IN() clauses, why arrays cannot be bound directly, and the safe PHP pattern to build dynamic queries.
Choosing the Right MySQL Collation for PHP and UTF-8
Learn how MySQL character sets and collations work with PHP, and how to choose a practical UTF-8 setup for web applications.