Classes and Objects
Not to be confused with the HTML/CSS ‘class’ attribute, a class in PHP may be regarded as a data type. It can contain properties (variables) and methods (functions). Use new to instantiate an object out of a class. Use -> on an instantiated object to access the object properties and methods. A string may be used as the class name, the method name or the object name.
<!DOCTYPE html>
<html>
<head></head>
<body><?php
class MyClass{
public $v=10; // a property
function shout(){ // a method
echo "Hello World! <br />";
}
function smile(){ // another method
echo "Smile World! <br />";
}
}
$test=new MyClass;
$test->shout();
echo $test->v."<br />";
$s="MyClass";
$test2=new $s;
$test2->smile();
$s="shout";
$test->$s();
$s="test";
$$s->smile();
?></body>
</html>
<!DOCTYPE html>
<html>
<head></head>
<body><?php
class MyClass{
public $v=10; // a property
function shout(){ // a method
echo "Hello World! <br />";
}
function smile(){ // another method
echo "Smile World! <br />";
}
}
$test=new MyClass;
$test->shout();
echo $test->v."<br />";
$s="MyClass";
$test2=new $s;
$test2->smile();
$s="shout";
$test->$s();
$s="test";
$$s->smile();
?></body>
</html>
Hello World!
10
Smile World!
Hello World!
Smile World!
Historically, assigning to a property that was never declared in the class (a dynamic property) simply created it on the fly. Since PHP 8.2, doing so emits a deprecation notice instead – dynamic properties still work, but are discouraged, since a typo in a property name now silently created a whole new property rather than raising an error:
<?php
class Point {
public $x;
public $y;
}
$p = new Point();
$p->x = 1;
$p->y = 2;
$p->z = 3;
echo "$p->x, $p->y, $p->z\n";
?>
<?php
class Point {
public $x;
public $y;
}
$p = new Point();
$p->x = 1;
$p->y = 2;
$p->z = 3;
echo "$p->x, $p->y, $p->z\n";
?>
Deprecated: Creation of dynamic property Point::$z is deprecated in D:\xampp\htdocs\dynamic-properties-deprecation.php on line 10
1, 2, 3
Two ways to keep allowing dynamic properties without the notice: mark the class with the #[\AllowDynamicProperties] attribute, or have it extend stdClass (which was always exempt, since dynamic data is stdClass's whole purpose):
<?php
#[\AllowDynamicProperties]
class FlexiblePoint {
public $x;
}
class LegacyPoint extends \stdClass {
public $x;
}
$f = new FlexiblePoint();
$f->x = 1;
$f->extra = "no deprecation notice";
$l = new LegacyPoint();
$l->x = 1;
$l->extra = "no deprecation notice either";
echo $f->extra . "\n";
echo $l->extra . "\n";
?>
<?php
#[\AllowDynamicProperties]
class FlexiblePoint {
public $x;
}
class LegacyPoint extends \stdClass {
public $x;
}
$f = new FlexiblePoint();
$f->x = 1;
$f->extra = "no deprecation notice";
$l = new LegacyPoint();
$l->x = 1;
$l->extra = "no deprecation notice either";
echo $f->extra . "\n";
echo $l->extra . "\n";
?>
no deprecation notice
no deprecation notice either
Before PHP 8.4, chaining straight off a new expression – eg. new Foo()->bar() – was a parse error; you had to wrap it in parentheses first, as in (new Foo())->bar(). Since PHP 8.4, the parentheses around new are no longer required, so method calls, property access, and array access can all follow a new expression directly:
<?php
class Greeter {
public function __construct(private string $name) {}
public function greet(): string {
return "Hello, {$this->name}!";
}
}
echo new Greeter("World")->greet();
?>
<?php
class Greeter {
public function __construct(private string $name) {}
public function greet(): string {
return "Hello, {$this->name}!";
}
}
echo new Greeter("World")->greet();
?>
Hello, World!
The clone keyword has always worked as an operator (clone $obj). Since PHP 8.5, clone() can also be called as a real function, optionally taking a second argument: an associative array of property names and values to overwrite on the cloned copy in one step, instead of assigning them afterwards on separate lines:
<?php
class Person {
public function __construct(public string $name, public int $age) {}
}
$original = new Person("Alice", 30);
$copy = clone($original, ['name' => 'New Name']);
echo $original->name . " " . $original->age . "\n";
echo $copy->name . " " . $copy->age . "\n";
$plainCopy = clone($original);
echo $plainCopy->name . " " . $plainCopy->age . "\n";
?>
<?php
class Person {
public function __construct(public string $name, public int $age) {}
}
$original = new Person("Alice", 30);
$copy = clone($original, ['name' => 'New Name']);
echo $original->name . " " . $original->age . "\n";
echo $copy->name . " " . $copy->age . "\n";
$plainCopy = clone($original);
echo $plainCopy->name . " " . $plainCopy->age . "\n";
?>
Alice 30
New Name 30
Alice 30