class
Basic class definitions begin with the
keyword class
, followed by a class name,
followed by a pair of curly braces which enclose the definitions
of the properties and methods belonging to the class.
The class name can be any valid label, provided it is not a
PHP reserved word. A valid class
name starts with a letter or underscore, followed by any number of
letters, numbers, or underscores. As a regular expression, it
would be expressed thus:
^[a-zA-Z_x80-xff][a-zA-Z0-9_x80-xff]*$
.
A class may contain its
own constants, variables
(called “properties”), and functions (called “methods”).
Example #1 Simple Class definition
<?php
class SimpleClass
{
// property declaration
public $var = 'a default value';// method declaration
public function displayVar() {
echo $this->var;
}
}
?>
The pseudo-variable $this is available when a
method is called from within an object context.
$this is the value of the calling object.
Warning
Calling a non-static method statically throws an
Error.
Prior to PHP 8.0.0, this would generate a deprecation notice,
and $this would be undefined.
Example #2 Some examples of the $this pseudo-variable
<?php
class A
{
function foo()
{
if (isset($this)) {
echo '$this is defined (';
echo get_class($this);
echo ")n";
} else {
echo "$this is not defined.n";
}
}
}
class
B
{
function bar()
{
A::foo();
}
}$a = new A();
$a->foo();A::foo();$b = new B();
$b->bar();B::bar();
?>
Output of the above example in PHP 7:
$this is defined (A) Deprecated: Non-static method A::foo() should not be called statically in %s on line 27 $this is not defined. Deprecated: Non-static method A::foo() should not be called statically in %s on line 20 $this is not defined. Deprecated: Non-static method B::bar() should not be called statically in %s on line 32 Deprecated: Non-static method A::foo() should not be called statically in %s on line 20 $this is not defined.
Output of the above example in PHP 8:
$this is defined (A) Fatal error: Uncaught Error: Non-static method A::foo() cannot be called statically in %s :27 Stack trace: #0 {main} thrown in %s on line 27
Readonly classes
As of PHP 8.2.0, a class can be marked with the
readonly modifier.
Marking a class as readonly will add the
readonly modifier
to every declared property, and prevent the creation of
dynamic properties.
Moreover, it is impossible to add support for them by using the
AllowDynamicProperties attribute. Attempting to do so
will trigger a compile-time error.
<?php
#[AllowDynamicProperties]
readonly class Foo {
}// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo
?>
As neither untyped, nor static properties can be marked with the
readonly
modifier, readonly classes cannot declare
them either:
<?php
readonly class Foo
{
public $bar;
}// Fatal error: Readonly property Foo::$bar must have type
?>
<?php
readonly class Foo
{
public static int $bar;
}// Fatal error: Readonly class Foo cannot declare static properties
?>
A readonly class can be
extended
if, and only if, the child class is also a
readonly class.
new
To create an instance of a class, the new
keyword must
be used. An object will always be created unless the object has a
constructor defined that throws an
exception on error. Classes
should be defined before instantiation (and in some cases this is a
requirement).
If a string containing the name of a class is used with
new
, a new instance of that class will be created. If
the class is in a namespace, its fully qualified name must be used when
doing this.
Note:
If there are no arguments to be passed to the class’s constructor,
parentheses after the class name may be omitted.
Example #3 Creating an instance
<?php
$instance = new SimpleClass();// This can also be done with a variable:
$className = 'SimpleClass';
$instance = new $className(); // new SimpleClass()
?>
As of PHP 8.0.0, using new
with arbitrary expressions
is supported. This allows more complex instantiation if the expression
produces a string. The expressions must be wrapped in parentheses.
Example #4 Creating an instance using an arbitrary expression
In the given example we show multiple examples of valid arbitrary expressions that produce a class name.
This shows a call to a function, string concatenation, and the ::class
constant.
<?phpclass ClassA extends stdClass {}
class ClassB extends stdClass {}
class ClassC extends ClassB {}
class ClassD extends ClassA {}
function
getSomeClass(): string
{
return 'ClassA';
}var_dump(new (getSomeClass()));
var_dump(new ('Class' . 'B'));
var_dump(new ('Class' . 'C'));
var_dump(new (ClassD::class));
?>
Output of the above example in PHP 8:
object(ClassA)#1 (0) { } object(ClassB)#1 (0) { } object(ClassC)#1 (0) { } object(ClassD)#1 (0) { }
In the class context, it is possible to create a new object by
new self
and new parent
.
When assigning an already created instance of a class to a new variable, the new variable
will access the same instance as the object that was assigned. This
behaviour is the same when passing instances to a function. A copy
of an already created object can be made by
cloning it.
Example #5 Object Assignment
<?php
$instance
= new SimpleClass();$assigned = $instance;
$reference =& $instance;$instance->var = '$assigned will have this value';$instance = null; // $instance and $reference become nullvar_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
The above example will output:
NULL NULL object(SimpleClass)#1 (1) { ["var"]=> string(30) "$assigned will have this value" }
It’s possible to create instances of an object in a couple of ways:
Example #6 Creating new objects
<?php
class Test
{
static public function getNew()
{
return new static;
}
}
class
Child extends Test
{}$obj1 = new Test();
$obj2 = new $obj1;
var_dump($obj1 !== $obj2);$obj3 = Test::getNew();
var_dump($obj3 instanceof Test);$obj4 = Child::getNew();
var_dump($obj4 instanceof Child);
?>
The above example will output:
bool(true) bool(true) bool(true)
It is possible to access a member of a newly created object
in a single expression:
Example #7 Access member of newly created object
<?php
echo (new DateTime())->format('Y');
?>
The above example will output
something similar to:
Note:
Prior to PHP 7.1, the arguments are not evaluated if there is no constructor
function defined.
Properties and methods
Class properties and methods live in separate “namespaces”, so it is
possible to have a property and a method with the same name. Referring to
both a property and a method has the same notation, and whether a property
will be accessed or a method will be called, solely depends on the context,
i.e. whether the usage is a variable access or a function call.
Example #8 Property access vs. method call
<?php
class Foo
{
public $bar = 'property';
public function
bar() {
return 'method';
}
}$obj = new Foo();
echo $obj->bar, PHP_EOL, $obj->bar(), PHP_EOL;
The above example will output:
That means that calling an anonymous
function which has been assigned to a property is not directly
possible. Instead the property has to be assigned to a variable first, for
instance. It is possible to call such a property directly
by enclosing it in parentheses.
Example #9 Calling an anonymous function stored in a property
<?php
class Foo
{
public $bar;
public function
__construct() {
$this->bar = function() {
return 42;
};
}
}$obj = new Foo();
echo (
$obj->bar)(), PHP_EOL;
The above example will output:
extends
A class can inherit the constants, methods, and properties of another class by
using the keyword extends
in the class
declaration. It is not possible to extend multiple classes; a
class can only inherit from one base class.
The inherited constants, methods, and properties can be overridden by
redeclaring them with the same name defined in the parent
class. However, if the parent class has defined a method or constant
as final,
they may not be overridden. It is possible to access the overridden
methods or static properties by referencing them
with parent::.
Note:
As of PHP 8.1.0, constants may be declared as final.
Example #10 Simple Class Inheritance
<?php
class ExtendClass extends SimpleClass
{
// Redefine the parent method
function displayVar()
{
echo "Extending classn";
parent::displayVar();
}
}$extended = new ExtendClass();
$extended->displayVar();
?>
The above example will output:
Extending class a default value
Signature compatibility rules
When overriding a method, its signature must be compatible with the parent
method. Otherwise, a fatal error is emitted, or, prior to PHP 8.0.0, an
E_WARNING
level error is generated.
A signature is compatible if it respects the
variance rules, makes a
mandatory parameter optional, adds only optional new parameters and
doesn’t restrict but only relaxes the visibility.
This is known as the Liskov Substitution Principle, or LSP for short.
The constructor,
and private
methods are exempt from these signature
compatibility rules, and thus won’t emit a fatal error in case of a
signature mismatch.
Example #11 Compatible child methods
<?phpclass Base
{
public function foo(int $a) {
echo "Validn";
}
}
class
Extend1 extends Base
{
function foo(int $a = 5)
{
parent::foo($a);
}
}
class
Extend2 extends Base
{
function foo(int $a, $b = 5)
{
parent::foo($a);
}
}$extended1 = new Extend1();
$extended1->foo();
$extended2 = new Extend2();
$extended2->foo(1);
The above example will output:
The following examples demonstrate that a child method which removes a parameter, or makes an optional
parameter mandatory, is not compatible with the parent method.
Example #12 Fatal error when a child method removes a parameter
<?phpclass Base
{
public function foo(int $a = 5) {
echo "Validn";
}
}
class
Extend extends Base
{
function foo()
{
parent::foo(1);
}
}
Output of the above example in PHP 8 is similar to:
Fatal error: Declaration of Extend::foo() must be compatible with Base::foo(int $a = 5) in /in/evtlq on line 13
Example #13 Fatal error when a child method makes an optional parameter mandatory
<?phpclass Base
{
public function foo(int $a = 5) {
echo "Validn";
}
}
class
Extend extends Base
{
function foo(int $a)
{
parent::foo($a);
}
}
Output of the above example in PHP 8 is similar to:
Fatal error: Declaration of Extend::foo(int $a) must be compatible with Base::foo(int $a = 5) in /in/qJXVC on line 13
Warning
Renaming a method’s parameter in a child class is not a signature
incompatibility. However, this is discouraged as it will result in a
runtime Error if
named arguments
are used.
Example #14 Error when using named arguments and parameters were renamed in a child class
<?phpclass A {
public function test($foo, $bar) {}
}
class
B extends A {
public function test($a, $b) {}
}$obj = new B;// Pass parameters according to A::test() contract
$obj->test(foo: "foo", bar: "bar"); // ERROR!
The above example will output
something similar to:
Fatal error: Uncaught Error: Unknown named parameter $foo in /in/XaaeN:14 Stack trace: #0 {main} thrown in /in/XaaeN on line 14
::class
The class
keyword is also used for class
name resolution.
To obtain the fully qualified name of a class ClassName
use ClassName::class
. This is particularly useful with
namespaced classes.
Example #15 Class name resolution
<?php
namespace NS {
class ClassName {
}
echo
ClassName::class;
}
?>
The above example will output:
Note:
The class name resolution using
::class
is a
compile time transformation. That means at the time the class name string
is created no autoloading has happened yet. As a consequence, class names
are expanded even if the class does not exist. No error is issued in
that case.Example #16 Missing class name resolution
<?php
print DoesNotExist::class;
?>
The above example will output:
As of PHP 8.0.0, ::class
may also be used on
objects. This resolution happens at runtime, not compile time. Its effect is
the same as calling get_class() on the object.
Example #17 Object name resolution
<?php
namespace NS {
class ClassName {
}
}
$c = new ClassName();
print $c::class;
?>
The above example will output:
Nullsafe methods and properties
As of PHP 8.0.0, properties and methods may also be accessed with the
“nullsafe” operator instead: ?->
. The nullsafe operator
works the same as property or method access as above, except that if the
object being dereferenced is null
then null
will be returned rather than an exception thrown. If the dereference is part of a
chain, the rest of the chain is skipped.
The effect is similar to wrapping each access in an is_null()
check first, but more compact.
Example #18 Nullsafe Operator
<?php// As of PHP 8.0.0, this line:
$result = $repository?->getUser(5)?->name;// Is equivalent to the following code block:
if (is_null($repository)) {
$result = null;
} else {
$user = $repository->getUser(5);
if (is_null($user)) {
$result = null;
} else {
$result = $user->name;
}
}
?>
Note:
The nullsafe operator is best used when null is considered a valid and expected
possible value for a property or method return. For indicating an error,
a thrown exception is preferable.
aaron at thatone dot com ¶
15 years ago
I was confused at first about object assignment, because it's not quite the same as normal assignment or assignment by reference. But I think I've figured out what's going on.
First, think of variables in PHP as data slots. Each one is a name that points to a data slot that can hold a value that is one of the basic data types: a number, a string, a boolean, etc. When you create a reference, you are making a second name that points at the same data slot. When you assign one variable to another, you are copying the contents of one data slot to another data slot.
Now, the trick is that object instances are not like the basic data types. They cannot be held in the data slots directly. Instead, an object's "handle" goes in the data slot. This is an identifier that points at one particular instance of an obect. So, the object handle, although not directly visible to the programmer, is one of the basic datatypes.
What makes this tricky is that when you take a variable which holds an object handle, and you assign it to another variable, that other variable gets a copy of the same object handle. This means that both variables can change the state of the same object instance. But they are not references, so if one of the variables is assigned a new value, it does not affect the other variable.
<?php
// Assignment of an object
Class Object{
public $foo="bar";
};$objectVar = new Object();
$reference =& $objectVar;
$assignment = $objectVar//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="bar"
//
?>
$assignment has a different data slot from $objectVar, but its data slot holds a handle to the same object. This makes it behave in some ways like a reference. If you use the variable $objectVar to change the state of the Object instance, those changes also show up under $assignment, because it is pointing at that same Object instance.
<?php
$objectVar->foo = "qux";
print_r( $objectVar );
print_r( $reference );
print_r( $assignment );//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
//
?>
But it is not exactly the same as a reference. If you null out $objectVar, you replace the handle in its data slot with NULL. This means that $reference, which points at the same data slot, will also be NULL. But $assignment, which is a different data slot, will still hold its copy of the handle to the Object instance, so it will not be NULL.
<?php
$objectVar = null;
print_r($objectVar);
print_r($reference);
print_r($assignment);//
// $objectVar --->+---------+
// | NULL |
// $reference --->+---------+
//
// +---------+
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
?>
pawel dot zimnowodzki at gmail dot com ¶
11 months ago
Although there is no null-safe operator for not existed array keys I found workaround for it: ($array['not_existed_key'] ?? null)?->methodName()
kStarbe at gmail point com ¶
6 years ago
You start using :: in second example although the static concept has not been explained. This is not easy to discover when you are starting from the basics.
Doug ¶
12 years ago
What is the difference between $this and self ?
Inside a class definition, $this refers to the current object, while self refers to the current class.
It is necessary to refer to a class element using self ,
and refer to an object element using $this .
Note also how an object variable must be preceded by a keyword in its definition.
The following example illustrates a few cases:
<?php
class Classy {
const
STAT = 'S' ; // no dollar sign for constants (they are always static)
static $stat = 'Static' ;
public $publ = 'Public' ;
private $priv = 'Private' ;
protected $prot = 'Protected' ;
function
__construct( ){ }
public function
showMe( ){
print '<br> self::STAT: ' . self::STAT ; // refer to a (static) constant like this
print '<br> self::$stat: ' . self::$stat ; // static variable
print '<br>$this->stat: ' . $this->stat ; // legal, but not what you might think: empty result
print '<br>$this->publ: ' . $this->publ ; // refer to an object variable like this
print '<br>' ;
}
}
$me = new Classy( ) ;
$me->showMe( ) ;/* Produces this output:
self::STAT: S
self::$stat: Static
$this->stat:
$this->publ: Public
*/
?>
Hayley Watson ¶
5 years ago
Class names are case-insensitive:
<?php
class Foo{}
class foo{} //Fatal error.
?>
Any casing can be used to refer to the class
<?php
class bAr{}
$t = new Bar();
$u = new bar();
echo ($t instanceof $u) ? "true" : "false"; // "true"
echo ($t instanceof BAR) ? "true" : "false"; // "true"
echo is_a($u, 'baR') ? "true" : "false"; // "true"
?>
But the case used when the class was defined is preserved as "canonical":
<?php
echo get_class($t); // "bAr"
?>
And, as always, "case-insensitivity" only applies to ASCII.
<?php
class пасха{}
class Пасха{} // valid
$p = new ПАСХА(); // Uncaught warning.
?>
wbcarts at juno dot com ¶
14 years ago
CLASSES and OBJECTS that represent the "Ideal World"
Wouldn't it be great to get the lawn mowed by saying $son->mowLawn()? Assuming the function mowLawn() is defined, and you have a son that doesn't throw errors, the lawn will be mowed.
In the following example; let objects of type Line3D measure their own length in 3-dimensional space. Why should I or PHP have to provide another method from outside this class to calculate length, when the class itself holds all the neccessary data and has the education to make the calculation for itself?
<?php/*
* Point3D.php
*
* Represents one locaton or position in 3-dimensional space
* using an (x, y, z) coordinate system.
*/
class Point3D
{
public $x;
public $y;
public $z; // the x coordinate of this Point.
/*
* use the x and y variables inherited from Point.php.
*/
public function __construct($xCoord=0, $yCoord=0, $zCoord=0)
{
$this->x = $xCoord;
$this->y = $yCoord;
$this->z = $zCoord;
}/*
* the (String) representation of this Point as "Point3D(x, y, z)".
*/
public function __toString()
{
return 'Point3D(x=' . $this->x . ', y=' . $this->y . ', z=' . $this->z . ')';
}
}/*
* Line3D.php
*
* Represents one Line in 3-dimensional space using two Point3D objects.
*/
class Line3D
{
$start;
$end;
public function
__construct($xCoord1=0, $yCoord1=0, $zCoord1=0, $xCoord2=1, $yCoord2=1, $zCoord2=1)
{
$this->start = new Point3D($xCoord1, $yCoord1, $zCoord1);
$this->end = new Point3D($xCoord2, $yCoord2, $zCoord2);
}/*
* calculate the length of this Line in 3-dimensional space.
*/
public function getLength()
{
return sqrt(
pow($this->start->x - $this->end->x, 2) +
pow($this->start->y - $this->end->y, 2) +
pow($this->start->z - $this->end->z, 2)
);
}/*
* The (String) representation of this Line as "Line3D[start, end, length]".
*/
public function __toString()
{
return 'Line3D[start=' . $this->start .
', end=' . $this->end .
', length=' . $this->getLength() . ']';
}
}/*
* create and display objects of type Line3D.
*/
echo '<p>' . (new Line3D()) . "</p>n";
echo '<p>' . (new Line3D(0, 0, 0, 100, 100, 0)) . "</p>n";
echo '<p>' . (new Line3D(0, 0, 0, 100, 100, 100)) . "</p>n";?>
<-- The results look like this -->
Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=1, y=1, z=1), length=1.73205080757]
Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=100, y=100, z=0), length=141.421356237]
Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=100, y=100, z=100), length=173.205080757]
My absolute favorite thing about OOP is that "good" objects keep themselves in check. I mean really, it's the exact same thing in reality... like, if you hire a plumber to fix your kitchen sink, wouldn't you expect him to figure out the best plan of attack? Wouldn't he dislike the fact that you want to control the whole job? Wouldn't you expect him to not give you additional problems? And for god's sake, it is too much to ask that he cleans up before he leaves?
I say, design your classes well, so they can do their jobs uninterrupted... who like bad news? And, if your classes and objects are well defined, educated, and have all the necessary data to work on (like the examples above do), you won't have to micro-manage the whole program from outside of the class. In other words... create an object, and LET IT RIP!
johannes dot kingma at gmail dot com ¶
1 year ago
BEWARE!
Like Hayley Watson pointed out class names are not case sensitive.
<?php
class Foo{}
class foo{} // Fatal error: Cannot declare class foo, because the name is already in use
?>
As well as
<?php
class BAR{}
$bar = new Bar();
echo get_class($bar);
?>
Is perfectly fine and will return 'BAR'.
This has implications on autoloading classes though. The standard spl_autoload function will strtolower the class name to cope with case in-sensitiveness and thus the class BAR can only be found if the file name is bar.php (or another variety if an extension was registered with spl_autoload_extensions(); ) not BAR.php for a case sensitive file and operating system like linux. Windows file system is case sensitive but the OS is not and there for autoloading BAR.php will work.
Notes on stdClass ¶
13 years ago
stdClass is the default PHP object. stdClass has no properties, methods or parent. It does not support magic methods, and implements no interfaces.
When you cast a scalar or array as Object, you get an instance of stdClass. You can use stdClass whenever you need a generic object instance.
<?php
// ways of creating stdClass instances
$x = new stdClass;
$y = (object) null; // same as above
$z = (object) 'a'; // creates property 'scalar' = 'a'
$a = (object) array('property1' => 1, 'property2' => 'b');
?>
stdClass is NOT a base class! PHP classes do not automatically inherit from any class. All classes are standalone, unless they explicitly extend another class. PHP differs from many object-oriented languages in this respect.
<?php
// CTest does not derive from stdClass
class CTest {
public $property1;
}
$t = new CTest;
var_dump($t instanceof stdClass); // false
var_dump(is_subclass_of($t, 'stdClass')); // false
echo get_class($t) . "n"; // 'CTest'
echo get_parent_class($t) . "n"; // false (no parent)
?>
You cannot define a class named 'stdClass' in your code. That name is already used by the system. You can define a class named 'Object'.
You could define a class that extends stdClass, but you would get no benefit, as stdClass does nothing.
(tested on PHP 5.2.8)
Anonymous ¶
4 years ago
At first I was also confused by the assignment vs referencing but here's how I was finally able to get my head around it. This is another example which is somewhat similar to one of the comments but can be helpful to those who did not understand the first example. Imagine object instances as rooms where you can store and manipulate your properties and functions. The variable that contains the object simply holds 'a key' to this room and thus access to the object. When you assign this variable to another new variable, what you are doing is you're making a copy of the key and giving it to this new variable. That means these two variable now have access to the same 'room' (object) and can thus get in and manipulate the values. However, when you create a reference, what you doing is you're making the variables SHARE the same key. They both have access to the room. If one of the variable is given a new key, then the key that they are sharing is replaced and they now share a new different key. This does not affect the other variable with a copy of the old key...that variable still has access to the first room
moty66 at gmail dot com ¶
13 years ago
I hope that this will help to understand how to work with static variables inside a class
<?phpclass a {
public static
$foo = 'I am foo';
public $bar = 'I am bar';
public static function
getFoo() { echo self::$foo; }
public static function setFoo() { self::$foo = 'I am a new foo'; }
public function getBar() { echo $this->bar; }
}$ob = new a();
a::getFoo(); // output: I am foo
$ob->getFoo(); // output: I am foo
//a::getBar(); // fatal error: using $this not in object context
$ob->getBar(); // output: I am bar
// If you keep $bar non static this will work
// but if bar was static, then var_dump($this->bar) will output null
// unset($ob);
a::setFoo(); // The same effect as if you called $ob->setFoo(); because $foo is static
$ob = new a(); // This will have no effects on $foo
$ob->getFoo(); // output: I am a new foo ?>
Regards
Motaz Abuthiab
Jeffrey ¶
14 years ago
A PHP Class can be used for several things, but at the most basic level, you'll use classes to "organize and deal with like-minded data". Here's what I mean by "organizing like-minded data". First, start with unorganized data.
<?php
$customer_name;
$item_name;
$item_price;
$customer_address;
$item_qty;
$item_total;
?>
Now to organize the data into PHP classes:
<?php
class Customer {
$name; // same as $customer_name
$address; // same as $customer_address
}
class
Item {
$name; // same as $item_name
$price; // same as $item_price
$qty; // same as $item_qty
$total; // same as $item_total
}
?>
Now here's what I mean by "dealing" with the data. Note: The data is already organized, so that in itself makes writing new functions extremely easy.
<?php
class Customer {
public $name, $address; // the data for this class...
// function to deal with user-input / validation
// function to build string for output
// function to write -> database
// function to read <- database
// etc, etc
}
class
Item {
public $name, $price, $qty, $total; // the data for this class...
// function to calculate total
// function to format numbers
// function to deal with user-input / validation
// function to build string for output
// function to write -> database
// function to read <- database
// etc, etc
}
?>
Imagination that each function you write only calls the bits of data in that class. Some functions may access all the data, while other functions may only access one piece of data. If each function revolves around the data inside, then you have created a good class.
Anonymous ¶
6 years ago
Understanding what does $this exactly do:
<?php
class toop {
public $i = "1234";
public function setv($a) {
$this->i = $a;
}
public function returnthis() {
return $this;
}
}
$ob = new toop();
$ob1 = new toop();
$obthis = $ob->returnthis();
echo $ob->i."n";
$ob->setv("$ob set");
echo $ob->i."n";
$obthis->setv("$obthis set");
echo $ob->i."n";
$ob1->setv('$ob1 set');
echo $ob->i."n";
?>
This will output:
1234
$ob set
$obthis set
$obthis set
thisleenoble at DOPEOPLESTILLNOSPAM dot me dot com ¶
2 years ago
Instantiating an object with a string variable defaults to non-namespaced scope. Given two classes in the same namespace.
<?php
namespace foo;
class
bar {
public function createSubclass(string $type) {
return new $type();
}
?>
<?php
namespace foo;
class
baz {
}
?>
<?php
$barObj = new bar();
$barObj->createSubclass('baz');// result: Uncaught Error: Class 'baz' not found
?>
Change bar class to:
<?php
namespace foo;
class
bar {
public function createSubclass(string $type) {
type = '\'.__NAMESPACE__.'\'.type;
return new $type();
}
?>
Класс — это шаблон для объектов, а объект — это экземпляр класса.
Представьте, что у нас есть класс Car
. Car
может иметь такие свойства, как название, цвет, диски и т.д. Мы можем определить переменные класса например, $name
, $color
и $disk
для хранения значений этих свойств.
Если мы создадим отдельные объекты (BMW, Mercedes Benz и т.д.), то они будут наследовать все свойства и поведение класса Car
, но каждый объект будет иметь разные значения свойств.
Что такое класс PHP?
Класс определяется с помощью ключевого слова class
, за которым следует имя класса и пара фигурных скобок ({}). Все его свойства и методы заключены в фигурные скобки:
Синтаксис
<?php class Car { // код идёт здесь...
} ?>
Ключевое слово class
используется для определения класса в PHP. Ниже приведены правила создания класса в PHP:
- Пишем название класса с большой буквы.
- Если имя класса содержит более одного слова, мы пишем каждое слово с большой буквы. Это известный стиль верблюда. Например, JapaneseCars, AmericanIdol, EuropeTour и др.
- Имя класса не может быть зарезервированным словом PHP.
- Имя класса не может содержать пробелов.
Как добавить свойства к классу?
Мы вызываем свойства внутри класса. Свойства могут принимать такие значения, как строки, целые числа и логические значения (true/false), как и любые другие переменные. Добавим несколько свойств в класс Car:
class Car { public $name; public $color = 'green'; public $hasSunRoof = true; }
Приведем правила создания свойств к классу:
- Мы используем ключевое слово
public
перед свойством класса. - Согласно соглашению об именах, имя свойства начинается со строчной буквы.
- Если имя содержит более одного слова, все слова, кроме первого слова, начинаются с заглавной буквы. Например, $color или $hasSunRoof (Верблюжий регистр camelCase).
- Свойство может иметь значение по умолчанию. Например, $color = ‘green’.
- Мы также можем создать свойство без значения по умолчанию. Например, $name.
Объявим класс с именем Car
, который будет состоять из двух свойств ($name
и $color
) и двух методов set_name()
и get_name()
для установки и получения свойства $name
:
Пример
<?php
class Car {
// Свойства
public $name;
public $color;
// Методы
function set_name($name) {
$this->name = $name;
}
function get_name() {
return $this->name;
}
}
?>
Данный код ничего не выведет, поскольку мы создали класс, но не создали пока ни одного объекта.
Примечание: В классе переменные называются свойствами, а функции — методами!
Что такое объект PHP?
Объект — это экземпляр класса. Из класса мы можем создать столько объектов, сколько может понадобиться для проекта. Каждый объект имеет все свойства и методы, определенные в классе, но у них будут разные значения свойств.
Для объявления объекта необходимо использовать ключевое слово new
.
Далее создадим из класса Car
два объекта — $bmw
и $mercedes
.
$bmw = new Car(); $mercedes = new Car();
Процесс создания объекта также известен как создание экземпляра.
Объекты, для чего они нужны?
В то время как в процедурном стиле программирования все функции и переменные находятся вместе в глобальной области видимости таким образом, чтобы их можно было использовать, просто вызывая их имя, использование классов делает манипуляции с кодом внутри классов скрытыми от глобальной области. Это происходит потому, что код внутри классов инкапсулируется в пределах класса, вне досягаемости глобальной области. Итак, нам нужен способ, позволяющий коду из глобальной области видимости использовать код внутри класса, и этот способ базируется на создании объектов из класса.
Мы можем создать столько объектов, сколько захотим, из одного и того же класса, и все они будут совместно использовать методы и свойства класса. См. изображение ниже:
Из одного и того же класса Car мы создали три отдельных объекта с названиями: Mercedes , Bmw и Audi .
Хотя все объекты были созданы из одного и того же класса и, следовательно, имеют методы и свойства класса, они все же разные. Это не только потому, что они имеют разные названия, но и потому, что их свойствам могут быть присвоены разные значения. Например, на изображении выше они различаются свойством цвета: Mercedes зеленый, Bmw синий, а Audi оранжевый.
Примечание: Класс содержит методы и свойства, общие для всех созданных из него объектов.
Хотя объекты используют один и тот же код, они могут вести себя по-разному, поскольку им могут быть присвоены разные значения.
Как получить свойства объекта?
Создав объект, мы можем получить его свойства. Например:
echo $bmw -> color; echo $mercedes -> color;
Когда объект создан, мы можем получить доступ к свойствам класса с помощью оператора (->)
.
Обратите внимание, что имя свойства не начинается со знака $
; только имя объекта начинается с символа $
.
<?php
class Car { // создадим класс Car
// Свойства
public $name;
public $color = 'green';
public $hasSunRoof = true;
}
// создадим из класса Car два объекта
$bmw = new Car();
$mercedes = new Car();
echo $bmw -> color;
echo "<br>";
echo $mercedes -> color;
?>
Результат выполнения кода:
green
green
Свойство color
было установлено в классе по умолчанию (green), поэтому все объекты его унаследовали.
Как установить свойства объекту?
Чтобы установить свойство объектe, мы используем аналогичный подход.
Например, установим синий цвет объекту bmw
:
Таким же способом установим значение свойства $name
для обоих объектов:
$bmw ->name = "BMW"; $mercedes ->name = "Mercedes Benz";
Установив значение свойства, мы можем получить его значение.
Чтобы получить цвет объекта $bmw
, мы используем следующую строку кода:
<?php
class Car {
// Свойства
public $name;
public $color = 'green';
public $hasSunRoof = true;
}
$bmw = new Car();
$bmw ->name = "BMW";
$bmw -> color = 'blue';
$mercedes = new Car();
$mercedes ->name = "Mercedes Benz";
echo $bmw -> name . ": ";
echo $bmw -> color;
echo "<br>";
echo $mercedes -> name . ": ";
echo $mercedes -> color;
?>
Результат выполнения кода:
BMW: blue
Mercedes Benz: green
Как добавить методы в класс?
Классы могут содержать различные функции. Функция внутри класса называется методом. Здесь мы добавляем в класс метод hello()
с префиксом public
:
class Car { public $comp; public $color = 'green'; public $hasSunRoof = true; public function hello() { return "beep"; } }
Правила создания методов:
- Прописываем ключевое слово public перед методом.
- Согласно соглашению об именах, имя метода начинается со строчной буквы.
- Если имя содержит более одного слова, то все слова, кроме первого слова, начинаются с заглавной буквы. Например, helloUser() или flyPanAm().
Мы можем подходить к методам так же, как и к свойствам:
<?php
class Car {
// свойства
public $name;
public $color = 'green';
public $hasSunRoof = true;
// метод, который говорит привет
public function hello()
{
return "beep";
}
}
// Создать экземпляр
$bmw = new Car ();
$mercedes = new Car ();
// Получить значения
echo $bmw -> color; // green
echo "<br >";
echo $mercedes -> color; // green
echo "<hr >";
// Установите значения
$bmw -> color = 'blue';
$bmw -> name = "BMW";
$mercedes -> name = "Mercedes Benz";
// Получить значения
echo $bmw -> color; // blue
echo "<br >";
echo $mercedes -> color; // green
echo "<br >";
echo $bmw -> name; // BMW
echo "<br >";
echo $mercedes -> name; // Mercedes Benz
echo "<hr >";
// Используем метод, чтобы получить звуковой сигнал
echo $bmw -> hello(); // beep
echo "<br >";
echo $mercedes -> hello(); // beep
?>
В приведенном ниже примере создадим два метода set_name()
и get_name()
для установки и получения свойства $name
для объектов $bmw
и $mercedes
:
<?php
class Car {
// Свойства
public $name;
public $color;
// Методы
function set_name($name) {
$this->name = $name;
}
function get_name() {
return $this->name;
}
}
$bmw = new Car();
$mercedes = new Car();
$bmw->set_name("BMW");
$mercedes->set_name("Mercedes Benz");
echo $bmw->get_name();
echo "<br>";
echo $mercedes->get_name();
?>
Результат выполнения кода:
BMW
Mercedes Benz
Для установки и получения свойства $color
, созданных объектов, добавляем в класс Car
еще два метода:
<?php
class Car {
// Свойства
public $name;
public $color;
// Методы
function set_name($name) {
$this->name = $name;
}
function get_name() {
return $this->name;
}
function set_color($color) {
$this->color = $color;
}
function get_color() {
return $this->color;
}
}
$bmw = new Car();
$bmw->set_name("BMW");
$bmw->set_color('blue');
echo "Название: " . $bmw->get_name();
echo "<br>";
echo "Цвет: " . $bmw->get_color();
?>
Результат выполнения кода:
Название: BMW
Цвет: blue
Ключевое слово $this в PHP
Ключевое слово $this
указывает на то, что мы используем собственные методы и свойства класса, и позволяет нам получить доступ к ним в пределах области видимости класса.
Ключевое слово $this
позволяет нам получить доступ к свойствам и методам класса внутри класса, используя следующий синтаксис:
$this -> propertyName; $this -> methodName();
Примечание: Только ключевое слово $this
начинается со знака $
, а имена свойств и методов нет.
Ключевое слово $this
относится к текущему объекту и доступно только внутри методов.
В следующем примере создан класс Car и объект $bmw.
Пример
<?php
class Car {
public $name;
}
$bmw = new Car();
?>
Перед нами стоит задача изменить свойство $name объекта.
Сделать это можно двумя способами:
1. Изменение свойства внутри класса путём добавления метода set_name()
и используя ключевое слово $this
:
<?php
class Car {
public $name;
// Метод
function set_name($name) {
$this->name = $name;
}
}
$bmw = new Car();
$bmw->set_name("BMW");
echo $bmw -> name; // BMW
?>
Результат выполнения кода:
BMW
2-й способ — это изменение свойства вне класса путем прямого изменения значения $name:
<?php
class Car {
public $name;
}
$bmw = new Car();
$bmw->name = "BMW";
echo $bmw -> name; // BMW
?>
Результат выполнения кода:
BMW
Является ли объект экземпляром класса?
Оператор instanceof
используется для определения того, является ли текущий объект экземпляром указанного класса:
<?php
$bmw = new Car();
var_dump($bmw instanceof Car);
?>
Результат выполнения кода:
bool(true)
Оператор instanceof
не генерирует никаких ошибок, если проверяемая переменная не является объектом. В этом случае он просто возвращает FALSE
.
Итоги
В этом уроке вы сделали свои первые шаги в мир объектно-ориентированного программирования PHP, узнав о классах и об объектах, которые могут быть созданы из них. Кликните здесь, чтобы попрактиковаться в предмете. Сегодня вы также узнали, как использовать ключевое слово $this для получения собственных свойств и методов класса изнутри класса. Закрепите полученные знания о ключевике $this.
It sounds like you answered your own question. get_class
will get you the class name. It is procedural and maybe that is what is causing the confusion. Take a look at the php documentation for get_class
Here is their example:
<?php
class foo
{
function name()
{
echo "My name is " , get_class($this) , "n";
}
}
// create an object
$bar = new foo();
// external call
echo "Its name is " , get_class($bar) , "n"; // It's name is foo
// internal call
$bar->name(); // My name is foo
To make it more like your example you could do something like:
<?php
class MyClass
{
public static function getClass()
{
return get_class();
}
}
Now you can do:
$className = MyClass::getClass();
This is somewhat limited, however, because if my class is extended it will still return ‘MyClass’. We can use get_called_class
instead, which relies on Late Static Binding, a relatively new feature, and requires PHP >= 5.3.
<?php
class MyClass
{
public static function getClass()
{
return get_called_class();
}
public static function getDefiningClass()
{
return get_class();
}
}
class MyExtendedClass extends MyClass {}
$className = MyClass::getClass(); // 'MyClass'
$className = MyExtendedClass::getClass(); // 'MyExtendedClass'
$className = MyExtendedClass::getDefiningClass(); // 'MyClass'
Summary: in this tutorial, you will learn about PHP objects, how to define a class, and how to create an object from a class.
What is an Object
If you look at the world around you, you’ll find many examples of tangible objects: lamps, phones, computers, and cars. Also, you can find intangible objects such as bank accounts and transactions.
All of these objects share the two common key characteristics:
- State
- Behavior
For example, a bank account has the state that consists of:
- Account number
- Balance
A bank account also has the following behaviors:
- Deposit
- Withdraw
PHP objects are conceptually similar to real-world objects because they consist of state and behavior.
An object holds its state in variables that are often referred to as properties. An object also exposes its behavior via functions which are known as methods.
What is a class?
In the real world, you can find many same kinds of objects. For example, a bank has many bank accounts. All of them have account numbers and balances.
These bank accounts are created from the same blueprint. In object-oriented terms, we say that an individual bank account is an instance of a Bank Account class.
By definition, a class is the blueprint of objects. For example, from the Bank Account class, you can create many bank account objects.
The following illustrates the relationship between the BankAccount
class and its objects. From the BankAccount
class you can create many BankAccount
objects. And each object has its own account number and balance.
Define a class
To define a class, you specify the class
keyword followed by a name like this:
<?php
class ClassName
{
//...
}
Code language: HTML, XML (xml)
For example, the following defines a new class called BankAccount
:
<?php
class BankAccount
{
}
Code language: HTML, XML (xml)
By convention, you should follow these rules when defining a class:
- A class name should be in the upper camel case where each word is capitalized. For example,
BankAccount
,Customer
,Transaction
, andDebitNote
. - If a class name is a noun, it should be in the singular noun.
- Define each class in a separate PHP file.
From the BankAccount
class, you can create a new bank account object by using the new
keyword like this:
<?php
class BankAccount
{
}
$account = new BankAccount();
Code language: HTML, XML (xml)
In this syntax, the $account
is a variable that references the object created by the BankAccount
class. The parentheses that follow the BankAccount
class name are optional. Therefore, you can create a new BankAccount
object like this:
$account = new BankAccount;
Code language: PHP (php)
The process of creating a new object is also called instantiation. In other words, you instantiate an object from a class. Or you create a new object from a class.
The BankAccount
class is empty because it doesn’t have any state and behavior.
Add properties to a class
To add properties to the BankAccount
class, you place variables inside it. For example:
<?php
class BankAccount
{
public $accountNumber;
public $balance;
}
Code language: HTML, XML (xml)
The BankAccount
class has two properties $accountNumber
and $balance
. In front of each property, you see the public
keyword.
The public
keyword determines the visibility of a property. In this case, you can access the property from the outside of the class.
To access a property, you use the object operator (->
) like this:
<?php
$object->property;
Code language: HTML, XML (xml)
The following example shows how to set the values of the accountNumber
and balance
properties:
<?php
class BankAccount
{
public $accountNumber;
public $balance;
}
$account = new BankAccount();
$account->accountNumber = 1;
$account->balance = 100;
Code language: HTML, XML (xml)
Besides the public
keyword, PHP also has private
and protected
keywords which you’ll learn in the access modifiers tutorial.
Add methods to a class
The following shows the syntax for defining a method in a class:
<?php
class ClassName
{
public function methodName(parameter_list)
{
// implementation
}
}
Code language: HTML, XML (xml)
Like a property, a method also has one of the three visibility modifiers: public
, private
, and protected
. If you define a method without any visibility modifier, it defaults to public
.
The following example defines the deposit()
method for the BankAccount
class:
<?php
class BankAccount
{
public $accountNumber;
public $balance;
public function deposit($amount)
{
if ($amount > 0) {
$this->balance += $amount;
}
}
}
Code language: HTML, XML (xml)
The deposit()
method accepts an argument $amount
. It checks if the $amount
is greater than zero before adding it to the balance.
To call a method, you also use the object operator (->
) as follows:
$object->method(arguments)
Code language: PHP (php)
The new syntax in the deposit()
method is the $this
variable. The $this
variable is the current object of the BankAccount
class.
For example, when you create a new object $account
and call the deposit()
method, the $this
inside the method is the $account
object:
$account = new BankAccount();
$account->accountNumber = 1;
$account->balance = 100;
$account->deposit(100);
Code language: PHP (php)
Similarly, you can add the withdraw()
method to the BankAccount
class as follows:
<?php
class BankAccount
{
public $accountNumber;
public $balance;
public function deposit($amount)
{
if ($amount > 0) {
$this->balance += $amount;
}
}
public function withdraw($amount)
{
if ($amount <= $this->balance) {
$this->balance -= $amount;
return true;
}
return false;
}
}
Code language: HTML, XML (xml)
The withdraw()
method checks the current balance.
If the balance is less than the withdrawal amount, the withdraw()
method returns false
.
Later, you’ll learn how to throw an exception instead. Otherwise, it deducts the withdrawal amount from the balance and returns true
.
Summary
- Objects have states and behaviors.
- A class is a blueprint for creating objects.
- Properties represent the object’s state, and methods represent the object’s behavior. Properties and methods have visibility.
- Use the
new
keyword to create an object from a class. - The
$this
variable references the current object of the class.
Did you find this tutorial useful?
PHP Language Specification
Classes
General
A class is a type that may contain zero or more explicitly declared
members, which can be any combination of class constants;
data members, called properties; and function members, called
methods. The ability to add properties to an
instance at runtime is described in dynamic members section.
An object (often called an instance) of a class type is created (i.e., instantiated) via the
new operator.
PHP supports inheritance, a means by which a derived class can
extend and specialize a single base class (also called parent).
Classes in PHP are not all derived from a common ancestor.
An abstract class is a base type intended for
derivation, but which cannot be instantiated directly. A concrete
class is a class that is not abstract. A final class is one
from which other classes cannot be derived.
A class may implement one or more interfaces,
each of which defines a contract. Interfaces may have method and constants, but not properties.
A class can use one or more traits, which allows a class to
have some of the benefits of multiple inheritance.
A constructor is a special method that is used to initialize
an instance immediately after it has been created.
A destructor is a special method that is used to free resources when an
instance is no longer needed. Other special methods exist; they are
described in special method section.
The members of a class each have a default or explicitly declared
visibility, which determines what source code can access them. A
member with private
visibility may be accessed only from within its own
class. A member with protected
visibility may be accessed only from
within its own class and from classes above and below it in the inheritance chain.
Access to a member with public
visibility is unrestricted.
The signature of a method is a combination of that method’s class name,
name, and argument list, including argument type declarations and
indication for arguments passed byRef, and whether the resulting
value is returned byRef.
Methods and properties implemented in a base class can be overridden in a
derived class by redeclaring them with the compatible signature (see below).
If the overriding method does not have a compatible signature,
a non-fatal error is issued but the override is still permitted.
It is not recommended to use incompatible signatures for overriding methods.
When an instance is allocated, new
returns a handle that points to that
object. As such, assignment of a handle does not copy the object itself.
(See cloning objects for a discussion of shallow and deep copying).
While PHP supports anonymous class types, such a type cannot be declared using class-declaration. Instead, it must be specified at the time of instantiation; that is, as part of an object-creation-expression.
Class Declarations
Syntax
class-declaration: class-modifieropt class name class-base-clauseopt class-interface-clauseopt { class-member-declarationsopt } class-modifier: abstract final class-base-clause: extends qualified-name class-interface-clause: implements qualified-name class-interface-clause , qualified-name
Constraints
name must be a valid name, and must not be self
, parent
, or a reserved keyword.
qualified-name must be a valid qualified-name and its name element must not be self
, parent
, or a reserved keyword.
A class-declaration containing any class-member-declarations that
have the modifier abstract
must itself have an abstract
class-modifier.
class-base-clause must not name a final class.
qualified-name in class-base-clause must name an existing class.
A class must not be derived directly or indirectly from itself.
A concrete class must implement each of the methods from all the
interfaces specified in class-interface-clause.
For each interface method, the corresponding implementing method must be compatible with the interface method, including the following:
- If the interface method is defined as returning byRef, the implementing method should also return byRef.
- If the interface method is variadic, the implementing method must also be variadic (see also below).
- The number of required (i.e. having no defaults) arguments of the implementing methods can not be more than the number of required arguments of the interface method (adding non-optional arguments is not allowed).
- The overall number of arguments for the implementing method should be at least the number of the arguments of the interface method (removing arguments is not allowed).
- Each argument of the implementing method must be compatible with corresponding argument of the prototype method.
- If the interface method defines the return type, the implementing method must have the same return type.
Compatible arguments are defined as follows:
- Parameter names do not matter.
- If the argument is optional (has default) in the interface, it should be optional in the implementation. However, implementation can provide a different default value.
- byRef argument requires byRef implementation, and non-byRef argument can not have byRef implementation.
- For no argument type, only declaration with no type is compatible.
- For typed argument, only argument with the same type is compatible.
- For variadic arguments, the definition of the variadic (last) argument should be compatible as per above. The implementation can define additional optional arguments before the variadic argument, but these arguments should be compatible with the variadic argument on the interface method.
qualified-name in class-interface-clause must name an interface type.
Semantics
A class-declaration defines a class type by the name name. Class
names are case-insensitive.
The abstract
modifier declares a class usable only as a base class; the
class cannot be instantiated directly. An abstract class may contain one
or more abstract members, but it is not required to do so. When a
concrete class is derived from an abstract class, the concrete class
must include an implementation for each of the abstract members it
inherits. The implementations of abstract methods must have compatible signatures,
incompatible implementations are not permitted.
The final
modifier prevents a class from being used as a base class.
The optional class-base-clause specifies the one base class from which
the class being defined is derived. In such a case, the derived class
inherits all the members from the base class.
The optional class-interface-clause specifies the one or more
interfaces that are implemented by the class being defined.
Examples
abstract class Vehicle
{
public abstract function getMaxSpeed();
...
}
abstract class Aircraft extends Vehicle
{
public abstract function getMaxAltitude();
...
}
class PassengerJet extends Aircraft
{
public function getMaxSpeed()
{
// implement method
}
public function getMaxAltitude()
{
// implement method
}
...
}
$pj = new PassengerJet(...);
echo "$pj's maximum speed: " . $pj->getMaxSpeed() . "n";
echo "$pj's maximum altitude: " . $pj->getMaxAltitude() . "n";
// -----------------------------------------
final class MathLibrary
{
private function MathLibrary() {} // disallows instantiation
public static function sin() { ... }
// ...
}
$v = MathLibrary::sin(2.34);
// -----------------------------------------
interface MyCollection
{
function put($item);
function get();
}
class MyList implements MyCollection
{
public function put($item)
{
// implement method
}
public function get()
{
// implement method
}
...
}
Class Members
Syntax
class-member-declarations: class-member-declaration class-member-declarations class-member-declaration class-member-declaration: class-const-declaration property-declaration method-declaration constructor-declaration destructor-declaration trait-use-clause
Semantics
The members of a class are those specified by its
class-member-declarations, and the members inherited from its base
class.
A class may contain the following members:
- Constants – the constant values associated with the class.
- Properties – the variables of the class.
- Methods – the computations and actions that can be performed by the
class.
Some methods have special semantics, such as:
- Constructor – the actions required to initialize an instance of the class.
- Destructor – the actions to be performed when an instance of the
class is no longer needed. - Special (or magic) methods
Members can be imported from one or more traits via trait-use-clauses.
The class can also have dynamic members which are not part of the class definition.
Methods and properties can either be static or instance members. A
static member is declared using static
. An instance member is one that
is not static. The name of a static or instance member can never be used
on its own; it must always be used as the right-hand operand of the
scope resolution operator
or the member access operator.
Each instance of a class contains its own, unique set of instance
properties of that class. An instance member is accessed via the
->
operator. In contrast,
a static property designates exactly one VSlot for its class, which does
not belong to any instance, per se. A static property exists whether or
not any instances of that class exist. A static member is accessed via
the ::
operator.
When any instance method operates on a given instance of a class, within
that method that object can be accessed via $this
. As a
static method does not operate on a specific instance, it has no $this
.
Examples
class Point
{
private static $pointCount = 0; // static property
private $x; // instance property
private $y; // instance property
public static function getPointCount() // static method
{
return self::$pointCount; // access static property
}
public function move($x, $y) // instance method
{
$this->x = $x;
$this->y = $y;
}
public function __construct($x = 0, $y = 0) // instance method
{
$this->x = $x; // access instance property
$this->y = $y; // access instance property
++self::$pointCount; // access static property
}
public function __destruct() // instance method
{
--self::$pointCount; // access static property
...
}
...
}
echo "Point count = " . Point::getPointCount() . "n";
$cName = 'Point';
echo "Point count = " . $cName::getPointCount() . "n";
Dynamic Members
Initially, the instance only has properties that are
declared explicitly in its class’s definition. However, properties can be
added to and removed from the instance at runtime. Static properties of a
class can not be changed at runtime, attempt to access non-existing static
property results in a fatal error.
Runtime-created properties always have public visibility.
The class can also define special methods for dynamic members – methods
and properties. This facility uses the same syntax to access the members
as the regular members, but instead of accessing actual properties and
methods the engine will use special methods to simulate the access.
In the case of dynamic properties, if a class
makes provision to do so by defining a series of special methods, it can
deal with the allocation and management of storage for those properties,
by storing them in another object or in a database, for example.
For dynamic methods, both static and non-static methods can be handled
by special methods.
Consider the following scenario, which involves dynamic properties:
class Point { ... } // has no public property "color", but has made
// provision to support dynamic properties.
$p = new Point(10, 15);
$p->color = "red"; // create/set the dynamic property "color"
$v = $p->color; // get the dynamic property "color"
isset($p->color); // test if the dynamic property "color" exists
unset($p->color); // remove the dynamic property "color"
Dynamic property handling is invoked when a property with specified name
name that is not currently visible (because it is hidden or it does not
exist). If the property is used in a modifiable lvalue context (as with the assignment of
“red”), the Engine generates a call to the instance method __set
.
This method treats that name as designating a dynamic property of the instance being operated on,
and sets its value to “red”, creating the property, if necessary. Similarly, in a non-lvalue context,
(as with the assignment of color to $v), the Engine generates a call to
the instance method __get
, which treats that name as
designating a dynamic property of the instance being operated on, and
gets its value. In the case of the call to the intrinsic isset
,
this generates a call to the instance method __isset
,
while a use of the unset
statement generates a
call to the instance method __unset
. By defining these
four special methods, the implementer of a class can control how dynamic
properties are handled.
The Engine will call the methods only if they are defined, if they are not defined,
no error is produced and default behavior is used.
In the case of a dynamic method, if a call to an undefined instance method is performed
and the instance has __call
method, then this method is called.
Otherwise, as per default, a fatal error is produced.
If a static call to an undefined class method is performed, and the class defines a
__callStatic
method, this method is called.
Otherwise, as per default, a fatal error is produced.
In both cases, the return value of the call is the return value of the method called.
Consider the following code fragment, in which class Widget has neither
an instance method called iMethod
nor a static method called sMethod
,
but that class has made provision to deal with dynamic methods:
$obj = new Widget;
$obj->iMethod(10, TRUE, "abc");
Widget::sMethod(NULL, 1.234);
The call to iMethod
is treated as if it were
$obj->__call('iMethod', array(10, TRUE, "abc"))
and the call to sMethod
is treated as if it were
Widget::__callStatic('sMethod', array(NULL, 1.234))
Constants
Syntax
const-declaration: const const-elements ; class-const-declaration: visibility-modifieropt const const-elements ; const-elements: const-element const-elements , const-element const-element: name = constant-expression
Constraints:
A const-declaration must only appear at the top level of a script, and
must not redefine an existing c-constant.
A class-const-declaration must be inside a class-declaration or
interface-declaration.
A class constant must not have a static
specifier.
Semantics:
A const-declaration defines a c-constant.
If visibility-modifier for a class constant is omitted, public
is assumed.
The visibility-modifier applies to all constants defined in the const-elements list.
All constants are implicitly static
.
Examples:
const MIN_VAL = 20;
const LOWER = MIN_VAL;
// -----------------------------------------
class Automobile
{
const DEFAULT_COLOR = "white";
public DEFAULT_BRAND = 'benz';
protected WHEEL_NUM = 4;
private PRIVATE_CONST = 'const';
...
}
$col = Automobile::DEFAULT_COLOR;
Properties
Syntax
property-declaration: property-modifier property-elements ; property-modifier: var visibility-modifier static-modifieropt static-modifier visibility-modifieropt visibility-modifier: public protected private static-modifier: static property-elements: property-element property-elements property-element property-element: variable-name property-initializeropt ; property-initializer: = constant-expression
Semantics
A property-declaration defines one or more instance or static properties.
If visibility-modifier is omitted, public
is assumed. The var
modifier
implies public visibility. The static
modifier defines the member as a static member.
The property-initializer for instance properties is applied prior to
the class’s constructor being called.
An instance property that is visible may be unset
, in which
case, the property is actually removed from that instance.
Examples
class Point
{
private static $pointCount = 0; // static property with initializer
private $x; // instance property
private $y; // instance property
...
}
Methods
Syntax
method-declaration: method-modifiersopt function-definition method-modifiers function-definition-header ; method-modifiers: method-modifier method-modifiers method-modifier method-modifier: visibility-modifier static-modifier class-modifier
Constraints
The method-modifiers preceding a function-definition must not contain
the abstract
modifier.
The method-modifiers preceding a function-definition-header must
contain the abstract
modifier.
A method must not have the same modifier specified more than once. A
method must not have more than one visibility-modifier. A method must
not have both the modifiers abstract
and private
, or abstract
and final
.
Semantics
A method-declaration defines an instance or static method. A method is
a function that is defined inside a class. However, the presence of
abstract
indicates an abstract method, in which case, no implementation
is provided. The absence of abstract
indicates a concrete method, in
which case, an implementation is provided.
Method names are case-insensitive.
The presence of final
indicates the method cannot be overridden in a
derived class.
If visibility-modifier is omitted, public
is assumed.
Examples
See class members for examples of instance and static methods. See class declarations for
examples of abstract methods and their subsequent definitions.
Constructors
Syntax
constructor-declaration: method-modifiers function &opt __construct ( parameter-declaration-listopt ) compound-statement
Constraints
An overriding constructor in a derived class must have the same or a
less-restricted visibility than the one in the base class.
method-modifiers can not contain static
.
Semantics
A constructor is a specially named instance method that is used
to initialize an instance immediately after it has been created. Any
instance properties having no initializers and not explicitly initialized
by a constructor take on the value NULL
. A constructor can return a result, by
value or byRef. A constructor cannot be abstract or static.
The class does not have to define a constructor.
If visibility-modifier is omitted, public
is assumed. A private
constructor inhibits the creation of an instance of the class type except
by methods of the same class.
Constructors can be overridden in a derived class by redeclaring them.
However, an overriding constructor need not have the same or compatible signature as
one defined in the base class.
Constructors are called by object-creation-expression
and from within other (derived class) constructors.
If classes in a derived-class hierarchy have constructors, it is the
responsibility of the constructor at each level to call the constructor
in its base-class explicitly, using the notation
parent::__construct(...)
. If a constructor calls its base-class
constructor, it is recommended to do so as the first statement in
compound-statement, so the object hierarchy is built from the
bottom-up. A constructor should not call its base-class constructor more
than once. A call to a base-class constructor searches for the nearest
constructor in the class hierarchy. Not every level of the hierarchy
needs to have a constructor.
Examples
class Point
{
private static $pointCount = 0;
private $x;
private $y;
public function __construct($x = 0, $y = 0)
{
$this->x = $x;
$this->y = $y;
++self::$pointCount;
}
public function __destruct()
{
--self::$pointCount;
...
}
...
}
// -----------------------------------------
class MyRangeException extends Exception
{
public function __construct($message, ...)
{
parent::__construct($message);
...
}
...
}
Destructors
Syntax
destructor-declaration: method-modifiers function &opt __destruct ( ) compound-statement
Constraints
method-modifiers can not contain static
.
Semantics
A destructor is a special-named instance method that is used to
free resources when an instance is no longer needed. The destructors for
instances of all classes are called automatically once there are no
handles pointing to those instances or in some unspecified order during
program shutdown. Like any method, a destructor can return a result by
value or byRef. A destructor cannot be static.
Destructors are called by the Engine or from within other (derived class) destructors.
If classes in a derived-class hierarchy have destructors, it is the
responsibility of the destructor at each level to call the destructor in
the base-class explicitly, using the notation parent::__destruct()
. If
a destructor calls its base-class destructor, it is recommended to do so as the
last statement in compound-statement, so the object hierarchy is
destructed from the top-down. A destructor should not call its
base-class destructor more than once. A call to a base-class destructor
searches for the nearest destructor in the class hierarchy. Not every
level of the hierarchy need have a destructor. A private
destructor
inhibits destructor calls from derived classes.
Examples
See constructors section for an example of a constructor and destructor.
Inheritance
When a class extends
another class it can override members of the parent class by declaring a
member with the same name. Only properties and methods can be overridden.
Visibility of the overridden member can not be made more restrictive, only more permissive (from private
to protected
to public
).
When a private member is overridden, the methods of the defining class still have access to the original private
member, however non-static public and protected members are shared across the inheritance chain.
When a method is overridden, the signature of the overriding method should be compatible
with the signature of the original method, by the same rule as if the original method belonged to the interface
and the overriding method belonged to an implementation.
If an implemented method is overridden with an incompatible method, a non-fatal error is issued, however the
override is still accepted by the engine. The use of incompatible overrides is not recommended.
Methods with Special Semantics
General
If a class contains a definition for a method having one of the
following names, that method must have the prescribed visibility,
signature, and semantics:
Method Name | Description |
---|---|
__call |
Calls a dynamic method in the context of an instance method call. |
__callStatic |
Calls a dynamic method in the context of a static method call. |
__clone |
Typically used to make a deep copy of an object. |
__construct |
A constructor. |
__debugInfo |
Produce debugging information for the object. |
__destruct |
A destructor. |
__get |
Retrieves the value of a given dynamic property. |
__invoke |
Called when an object is called as a function (e.g. $a() ). |
__isset |
Reports if a given dynamic property exists. |
__set |
Sets the value of a given dynamic property. |
__set_state |
Used by export function var_export to restore the state of the object. |
__sleep |
Executed before serialization of an instance of this class. |
__toString |
Returns a string representation of the instance on which it is called. |
__unset |
Removes a given dynamic property. |
__wakeup |
Executed after unserialization of an instance of this class. |
In general, method names beginning with __
are reserved for special methods. The code should not define methods with names
beginning with __
unless it is one of the special methods described here.
Note that while syntax definitions below use the non-abstract syntax in the method definition, the special methods,
like any methods, can be declared abstract
. In this case the definition does not actually define a special method but defines that
an overriding concrete class must declare one. Nevertheless, the constraints on special methods must still be followed in such definitions.
Method __call
Syntax
method-modifiers function __call ( $name , $arguments ) return-typeopt compound-statement
Constraints
The method can not be static and must have public visibility.
The arguments passed to this method must not be passed byRef.
Semantics
This instance method is called to invoke the dynamic method
designated by $name
using the arguments specified by the elements of
the array designated by $arguments
. It can return any value deemed
appropriate.
Typically, __call
is called implicitly, when the
->
operator
is used to call an instance method that is not visible.
While __call
can be called explicitly, the two scenarios do not
necessarily produce the same result. Consider the expression p->m(...)
,
where p
is an instance and m
is an instance-method name. If m
is the
name of a visible method, p->m(...)
does not result in __call
’s being
called. Instead, the visible method is used. On the other hand, the
expression p->__call('m',array(...))
always calls the named dynamic
method, ignoring the fact that a visible method having the same name
might exist. If m
is not the name of a visible method, the two
expressions are equivalent; that is; when handling p->m(...)
, if no
visible method by that name is found, a dynamic method is assumed, and
__call
is called.
While the name source token has a prescribed syntax, there are no
restrictions on the content of the dynamic method name designated by
$name. Any source character is allowed here.
Examples
class Widget
{
public function __call($name, $arguments)
{
// using the method name and argument list, redirect/process
// the method call, as desired.
}
...
}
$obj = new Widget;
$obj->iMethod(10, TRUE, "abc"); // $obj->__call('iMethod', array(...))
Method __callStatic
Syntax
method-modifiers function __callStatic ( $name , $arguments ) return-typeopt compound-statement
Constraints
The method-modifiers must contain static
and must define public visibility.
The arguments passed to this method must not be passed byRef.
Semantics
This static method is called to invoke the dynamic method
designated by $name
using the arguments specified by the elements of
the array designated by $arguments
. It can return any value deemed
appropriate.
Typically, __callStatic
is called implicitly, when the ::
operator
is used to call a static method that is not visible.
While __callStatic
can be called explicitly, the two scenarios do not
necessarily produce the same result. Consider the expression C::m(...)
,
where C
is a class and m
is a static-method name. If m
is the name of a
visible method, C::m(...)
does not result in __callStatic
’s being
called. Instead, the visible method is used. On the other hand, the
expression C::__callStatic('m',array(...))
always calls the named
dynamic method, ignoring the fact that a static visible method having
the same name might exist. If m is not the name of a visible method, the
two expressions are equivalent; that is; when handling C::m(...)
, if no
visible method by that name is found, a dynamic method is assumed, and
__callStatic
is called.
While the name source token has a prescribed syntax, there are no
restrictions on the spelling of the dynamic method name designated by
$name
. Any source character is allowed here.
Examples
class Widget
{
public static function __callStatic($name, $arguments)
{
// using the method name and argument list, redirect/process
// the method call, as desired.
}
...
}
Widget::sMethod(NULL, 1.234); // Widget::__callStatic('sMethod', array(...))
Method __clone
Syntax
method-modifiers function __clone ( ) compound-statement
Constraints
The method-modifiers must not contain static
and must define public visibility.
Semantics
This instance method is called by the clone
operator,
typically to make a deep copy of the the instance on which it is
called. Method __clone
cannot be called directly by the program.
Consider a class Employee
, from which is derived a class Manager
. Let us
assume that both classes contain properties that are objects. To make a
copy of a Manager
object, its __clone
method is called to do whatever
is necessary to copy the properties for the Manager
class. That method
should, in turn, call the __clone
method of its parent class,
Employee
, so that the properties of that class can also be copied (and
so on, up the derived-class hierarchy).
To clone an object, the clone
operator makes a shallow copy
of the object on which it is called. Then, if the class of the instance being cloned has a method called
__clone
, that method is called to make a deep copy.
Method __clone
cannot be called directly from outside a class; it can
only be called by name from within a derived class, using the notation
parent::__clone()
. This method can return a value; however, if it does
so and control returns directly to the point of invocation via the clone
operator, that value will be ignored. The value returned to a
parent::__clone()
call can, however, be retrieved.
While cloning creates a new object, it does so without using a
constructor, in which case, code may need to be added to the __clone
method to emulate what happens in a corresponding constructor. (See the
Point
example below).
An implementation of __clone
should factor in the possibility of an
instance having dynamic properties.
Examples
class Employee
{
...
public function __clone()
{
// do what it takes here to make a copy of Employee object properties
}
}
class Manager extends Employee
{
...
public function __clone()
{
parent::__clone(); // request cloning of the Employee properties
// do what it takes here to make a copy of Manager object properties
}
...
}
// -----------------------------------------
class Point
{
private static $pointCount = 0;
public function __construct($x = 0, $y = 0)
{
...
++self::$pointCount;
}
public function __clone()
{
++self::$pointCount; // emulate the constructor
}
...
}
$p1 = new Point; // created using the constructor
$p2 = clone $p1; // created by cloning
Method __debugInfo
Syntax
method-modifiers function __debugInfo ( ) compound-statement
Constraints
The method-modifiers must not contain static
and must define public visibility.
The function should return array.
Semantics
This method allows the class to supply debugging information for the object, which can be used as
the source of information for var_dump()
.
Example
class File {
// "Resource(stream)" isn't all that useful
private $fp;
// But all the stream meta data is
public function __debugInfo() {
return $this->fp ? stream_get_meta_data($fp) : [];
}
public function open($filename, $mode = 'r'){
$this->fp = fopen($filename, $mode);
}
}
$f = new File;
var_dump($f); // object(File)#1 { }
$f->open('http://php.net');
var_dump($f);
/*
object(File)#1 {
["wrapper_type"]=>
string(4) "http"
["stream_type"]=>
string(10) "tcp_socket"
etc...
*/
Method __get
Syntax
method-modifiers function &opt __get ( $name ) return-typeopt compound-statement
Constraints
The method-modifiers must not contain static
and must define public visibility.
Semantics
This instance method gets the value of the dynamic property
designated by $name
. It is up to the implementor to define the return value.
Typically, __get
is called implicitly, when the
->
operator
is used in a non-lvalue context and the named property is not visible.
While __get
can be called explicitly, the two scenarios do not
necessarily produce the same result. Consider the expression
$v = $p->m
, where p
is an instance and m
is a property name. If m
is
the name of a visible property, p->m
does not result in __get
’s being
called. Instead, the visible property is used. On the other hand, the
expression p->__get('m')
always gets the value of the named dynamic
property, ignoring the fact that a visible property having the same name
might exist. If m
is not the name of a visible property, the two
expressions are equivalent; that is; when handling p->m
in a non-lvalue
context, if no visible property by that name is found, a dynamic
property is assumed, and __get
is called.
Consider the expression $v = $p->m = 5
, where m
is a dynamic
property. While __set
is called to assign the value 5 to
that property, __get
is not called to retrieve the result after that
assignment is complete.
If the implementation wants the caller to be able to modify the contents
of the returned value (such as returning an array which can be modified by caller,
and the modifications are reflected in the dynamic property), __get
should return byRef.
Examples
class Point
{
private $dynamicProperties = array();
private $x;
private $y;
public function __get($name)
{
if (array_key_exists($name, $this->dynamicProperties))
{
return $this->dynamicProperties[$name];
}
// no-such-property error handling goes here
return NULL;
}
...
}
Implementation Notes
Consider the following class, which does not contain a property
called prop:
class C
{
public function __get($name)
{
return $this->$name; // must not recurse
}
...
}
$c = new C;
$x = $c->prop;
As no property (dynamic or otherwise) by the name prop exists in the
class and a __get
method is defined, this looks look a recursive
situation. However, the implementation must not allow that. The same
applies to seemingly self-referential implementations of __set
, __isset
, and __unset
. Only one iteration of the dynamic resolution is
performed per-property, and the special method is called only once per property name.
While the name source token has a prescribed syntax, there are no
restrictions on the spelling of the dynamic property name designated by
$name
. Any source character is allowed here.
Method __invoke
Syntax
method-modifiers function __invoke ( parameter-declaration-listopt ) return-typeopt compound-statement
Constraints
The method-modifiers must not contain static
and must define public visibility.
Semantics
This instance method allows an instance to be used with function-call
notation. An instance whose class provides this method will also return TRUE
when passed to is_callable
.
When an instance is called as a function, the argument list used is made
available to __invoke
, whose return value becomes the return value of the
initial function call.
Examples
class C
{
public function __invoke($p)
{
...
return ...;
}
...
}
$c = new C;
is_callable($c) // returns TRUE
$r = $c(123); // becomes $r = $c->__invoke(123);
Method __isset
Syntax
method-modifiers function __isset ( $name ) return-typeopt compound-statement
Constraints
The method-modifiers must not contain static
and must define public visibility.
Semantics
If the dynamic property designated by $name
exists, this
instance method returns TRUE
; otherwise, FALSE
is returned. The speficis of
how existence of the dynamic property is determined is left to the implementor of the method.
Typically, __isset
is called implicitly, when the intrinsic isset
or intrinsic empty
is called with an argument that designates
a property that is not visible.
While __isset
can be called explicitly, the two
scenarios do not necessarily produce the same result. Consider the
expression isset($p->m)
, where p
is an instance and m
is a property
name. If m
is the name of a visible property, __isset
is not called.
Instead, the visible property is used. On the other hand, the expression
p->__isset('m')
always tests for the named dynamic property, ignoring
the fact that a visible property having the same name might exist. If m
is not the name of a visible property, the two expressions are
equivalent; that is; when handling p->m
in a non-lvalue context, if no
visible property by that name is found, a dynamic property is assumed.
While the name source token has a prescribed syntax, there are no
restrictions on the spelling of the dynamic property name designated by
$name
. Any source character is allowed here.
Examples
class Point
{
private $dynamicProperties = array();
private $x;
private $y;
public function __isset($name)
{
return isset($this->dynamicProperties[$name]);
}
...
}
Implementation Notes
See the Implementation Notes for __get
.
Method __set
Syntax
method-modifiers function __set ( $name , $value ) return-typeopt compound-statement
Constraints
The method-modifiers must not contain static
and must define public visibility.
Semantics
This instance method sets the value of the dynamic property
designated by $name
to $value
. No value is expected to be returned.
Typically, __set
is called implicitly, when the
->
operator
is used in a modifiable lvalue context and the named property is not
visible.
While __set
can be called explicitly, the two scenarios
do not necessarily produce the same result. Consider the expression
p->m = 5
, where p
is an instance and m
is a property name. If m
is the
name of a visible property, p->m
does not result in __set
’s being
called. Instead, the visible property is used. On the other hand, the
expression p->__set('m',5)
always sets the value of the named dynamic
property, ignoring the fact that a visible property having the same name
might exist. If m
is not the name of a visible property, the two
expressions are equivalent; that is; when handling p->m
, if no visible
property by that name is found, a dynamic property is assumed, and
__set
is called.
While the name source token has a prescribed syntax, there are no
restrictions on the spelling of the dynamic property name designated by
$name
. Any source character is allowed here.
Examples
class Point
{
private $dynamicProperties = array();
private $x;
private $y;
public function __set($name, $value)
{
$this->dynamicProperties[$name] = $value;
}
...
}
// -----------------------------------------
class X
{
public function __destruct() { ... }
}
$p = new Point(5, 9);
$p->thing = new X; // set dynamic property "thing" to instance with destructor
...
// at the end of the program, p->thing's destructor is called
Implementation Notes
See the Implementation Notes for __get
.
Method __set_state
Syntax
method-modifiers function __set_state ( array $properties ) return-typeopt compound-statement
Constraints
The method-modifiers must contain static
and must define public visibility.
Semantics
This function supports the library function var_export
when it is
given an instance of this class type. var_export
takes a variable and
produces a string representation of that variable as valid PHP code
suitable for use with the intrinsic eval
.
For an object, the string returned by var_export
has the following
general format:
classname::__set_state(array('prop1' => value, ..., 'propN' => value , ))
where the property names prop1
through propN
do not include a
leading dollar ($
). This string contains a call to the __set_state
method even if no such method is defined for this class or in any of its
base classes, in which case, a subsequent call to eval
using this string
will produce a fatal error. To allow the string to be used with eval
, the method
__set_state
must be defined, and it must create a new instance of the
class type, initialize its instance properties using the key/value pairs
in $properties
, and it must return that new object.
When extending the class with __set_state
method, one should override
the method, otherwise a call to it will look for such a method in the base class hierarchy,
and that method will return an instance of the associated base class, not of the class
on which it was invoked. Usage of static
allows late static binding to produce
the instance of an appropriate class.
If a derived class defines a __set_state
method, but any
base class has instance properties that are not visible within that
method, that method must invoke parent’s __set_state
as well, but
that can require support from a base class. See the second example
below.
Examples
class Point
{
private $x;
private $y;
static public function __set_state(array $properties)
{
$p = new Point;
$p->x = $properties['x'];
$p->y = $properties['y'];
return $p;
}
...
}
$p = new Point(3, 5);
$v = var_export($p, TRUE); // returns string representation of $p
The string produced looks something like the following:
"Point::__set_state(array(
'x' => 3,
'y' => 5,
))"
eval('$z = ' . $v . ";"); // execute the string putting the result in $z
echo "Point $z is $zn"; // Point $z is (3,5)
// -----------------------------------------
class B // base class of D
{
private $bprop;
public function __construct($p)
{
$this->bprop = $p;
}
static public function __set_state(array $properties)
{
$b = new static($properties['bprop']); // note the static
return $b;
// Because of the "new static", the return statement
// returns a B when called in a B context, and
// returns a D when called in a D context
}
}
class D extends B
{
private $dprop = 123;
public function __construct($bp, $dp = NULL)
{
$this->dprop = $dp;
parent::__construct($bp);
}
static public function __set_state(array $properties)
{
$d = parent::__set_state($properties); // expects back a D, NOT a B
$d->dprop = $properties['dprop'];
return $d;
}
}
$b = new B(10);
$v = var_export($b, TRUE);
eval('$z = ' . $v . ";");
var_dump($z);
$d = new D(20, 30);
$v = var_export($d, TRUE);
eval('$z = ' . $v . ";");
var_dump($z);
Method __sleep
Syntax
method-modifiers function __sleep ( ) return-typeopt compound-statement
Constraints
The method-modifiers must not contain static
and must define public visibility.
Semantics
The instance methods __sleep
and __wakeup
support
serialization.
If a class has a __sleep
method, the library function serialize
calls that method to find out which visible instance properties it
should serialize. (In the absence of a __sleep
or serialize
method,
all instance properties are serialized, including ones defined in runtime).
This information is returned by __sleep
as an array of zero
or more elements, where each element’s value is distinct and is the name
of a visible instance property. These properties’ values are serialized
in the order in which the elements are inserted in the array. If
__sleep
does not return a value explicitly, NULL
is returned, and that
value is serialized.
Besides creating the array of property names, __sleep
can do whatever
else might be needed before serialization occurs.
The alternative to using __sleep
and __wakeup
is implementing the
Serializable interface.
Note that if a class defining __sleep
and __wakeup
is extended, and the
derived class does not override the methods, the serialization and unserialization
will be performed as if those were instances of the base class, e.g. additional
properties may not be serialized or restored.
Examples
Consider a Point
class that not only contains x- and y-coordinates, it
also has an id
property; that is, each distinct Point
created during a
program’s execution has a unique numerical id. However, there is no need
to include this when a Point
is serialized. It can simply be recreated
when that Point
is unserialized. This information is transient and need
not be preserved across program executions. (The same can be true for
other transient properties, such as those that contain temporary results
or run-time caches).
class Point
{
private static $nextId = 1;
private $x;
private $y;
private $id;
public function __construct($x = 0, $y = 0)
{
$this->x = $x;
$this->y = $y;
$this->id = self::$nextId++; // assign the next available id
}
public function __sleep()
{
return array('y', 'x'); // serialize only $y and $x, in that order
}
public function __wakeup()
{
$this->id = self::$nextId++; // assign a new id
}
...
}
$p = new Point(-1, 0);
$s = serialize($p); // serialize Point(-1,0)
$v = unserialize($s); // unserialize Point(-1,0)
Method __toString
Syntax
method-modifiers function __toString ( ) return-typeopt compound-statement
Constraints
The method-modifiers must not contain static
and must define public visibility.
This function must return a string.
This function must not throw any exceptions.
Semantics
This instance method is intended to create a string representation of
the instance on which it is called.
__toString
is called by a number of language and library facilities,
including echo
, when an object-to-string conversion is needed.
__toString
can also be called directly.
An implementation of __toString
should factor in the possibility of an
instance having dynamic properties.
Examples
class Point
{
private $x;
private $y;
public function __construct($x = 0, $y = 0)
{
$this->x = $x;
$this->y = $y;
}
public function __toString()
{
return '(' . $this->x . ',' . $this->y . ')';
}
...
}
$p1 = new Point(20, 30);
echo $p1 . "n"; // implicit call to __toString() returns "(20,30)"
// -----------------------------------------
class MyRangeException extends Exception
{
public function __toString()
{
return parent::__toString()
. string-representation-of-MyRangeException
}
...
}
Method __unset
Syntax
method-modifiers function __unset ( $name ) return-typeopt compound-statement
Constraints
The method-modifiers must not contain static
and must define public visibility.
Semantics
If the dynamic property designated by $name
exists, it is
removed by this instance method; otherwise, the call has no effect. No
value is expected to be returned.
Typically, __unset
is called implicitly, when the unset
statement
is called with an argument that designates a property that
is not visible.
While __unset
can be called explicitly, the two
scenarios do not necessarily produce the same result. Consider the
expression unset($p->m)
, where p
is an instance and m
is a property
name. If m
is the name of a visible property, __unset
is not called.
Instead, the visible property is used. On the other hand, the expression
p->__unset('m'))
always removes the named dynamic property, ignoring
the fact that a visible property having the same name might exist. If m
is not the name of a visible property, the two expressions are
equivalent; that is; when handling p->m
in a non-lvalue context, if no
visible property by that name is found, a dynamic property is assumed.
While the name source token has a prescribed syntax, there are no
restrictions on the spelling of the dynamic property name designated by
$name
. Any source character is allowed here.
Examples
class Point
{
private $dynamicProperties = array();
private $x;
private $y;
public function __unset($name)
{
unset($this->dynamicProperties[$name]);
}
...
}
Implementation Notes
See the Implementation Notes for __get
.
Method __wakeup
Syntax
method-modifiers function __wakeup ( ) return-typeopt compound-statement
Constraints
The method-modifiers must not contain static
and must define public visibility.
Semantics
The instance methods __sleep
and __wakeup
support
serialization.
When the library function unserialize
is called on the string
representation of an object, as created by the library function
serialize
, unserialize
creates an instance of that object’s type
without calling a constructor, and then calls that class’s
__wakeup
method, if any, to initialize the instance. In the absence of
a __wakeup
method, all that is done is that the values of the instance
properties encoded in the serialized string are restored.
__wakeup
is not expected to return a value.
Consider a Point
class that not only contains x- and y-coordinates, it
also has an id
property; that is, each distinct Point
created during a
program’s execution has a unique numerical id. However, there is no need
to include this when a Point
is serialized. It can simply be recreated
by __wakeup
when that Point
is unserialized. This means that
__wakeup
must emulate the constructor, as appropriate.
Examples
See __sleep
.
Serialization
In PHP, variables can be converted into some external form suitable for
use in file storage or inter-program communication. The process of
converting to this form is known as serialization while that of
converting back again is known as unserialization. These facilities
are provided by the library functions serialize
and unserialize
, respectively.
In the case of variables that are objects, on their own, these two
functions serialize and unserialize all the instance properties, which
may be sufficient for some applications. However, if the programmer
wants to customize these processes, they can do so in one of two mutually exclusive ways.
The first approach is to define methods called
__sleep
and __wakeup
, and have them get control before serialization
and after serialization, respectively. For information on this approach,
see __sleep and __wakeup. The second approach involves implementing
the interface Serializable
by defining two methods, serialize
and unserialize
.
Consider a Point
class that not only contains x- and y-coordinates, it
also has an id
property; that is, each distinct Point
created during a
program’s execution has a unique numerical id. However, there is no need
to include this when a Point
is serialized. It can simply be recreated
when that Point
is unserialized. This information is transient and need
not be preserved across program executions. (The same can be true for
other transient properties, such as those that contain temporary results
or run-time caches). Furthermore, consider a class ColoredPoint
that
extends Point
by adding a color
property. The following code shows how
these classes need be defined in order for both Points
and ColoredPoints
to be serialized and unserialized:
class Point implements Serializable // note the interface
{
private static $nextId = 1;
private $x;
private $y;
private $id; // transient property; not serialized
public function __construct($x = 0, $y = 0)
{
$this->x = $x;
$this->y = $y;
$this->id = self::$nextId++;
}
public function __toString()
{
return 'ID:' . $this->id . '(' . $this->x . ',' . $this->y . ')';
}
public function serialize()
{
return serialize(array('y' => $this->y, 'x' => $this->x));
}
The custom method serialize
calls the library function serialize
to
create a string version of the array, whose keys are the names of the
instance properties to be serialized. The insertion order of the array
is the order in which the properties are serialized in the resulting
string. The array is returned.
public function unserialize($data)
{
$data = unserialize($data);
$this->x = $data['x'];
$this->y = $data['y'];
$this->id = self::$nextId++;
}
}
The custom method unserialize
converts the serialized string passed to
it back into an array. Because a new object is being created, but
without any constructor being called, the unserialize
method must
perform the tasks ordinarily done by a constructor. In this case, that
involves assigning the new object a unique id.
$p = new Point(2, 5);
$s = serialize($p);
The call to the library function serialize
calls the custom serialize
method. Afterwards, the variable $s
contains the serialized version of
the Point(2,5)
, and that can be stored in a database or transmitted to a
cooperating program. The program that reads or receives that serialized
string can convert its contents back into the corresponding variable(s),
as follows:
$v = unserialize($s);
The call to the library function unserialize
calls the custom
unserialize
method. Afterwards, the variable $s
contains a new
Point(2,5)
.
class ColoredPoint extends Point implements Serializable
{
const RED = 1;
const BLUE = 2;
private $color; // an instance property
public function __construct($x = 0, $y = 0, $color = RED)
{
parent::__construct($x, $y);
$this->color = $color;
}
public function __toString()
{
return parent::__toString() . $this->color;
}
public function serialize()
{
return serialize(array(
'color' => $this->color,
'baseData' => parent::serialize()
));
}
As with class Point
, this custom method returns an array of the instance
properties that are to be serialized. However, in the case of the second
element, an arbitrary key name is used, and its value is the serialized
version of the base Point within the current ColoredPoint
object. The
order of the elements is up to the programmer.
public function unserialize($data)
{
$data = unserialize($data);
$this->color = $data['color'];
parent::unserialize($data['baseData']);
}
}
As ColoredPoint
has a base class, it unserializes its own instance
properties before calling the base class’s custom method, so it can
unserialize the Point
properties.
$cp = new ColoredPoint(9, 8, ColoredPoint::BLUE);
$s = serialize($cp);
...
$v = unserialize($s);
Function unserialize
takes an optional second argument, which specifies an array of trusted class names as strings. Objects found in the data stream whose type name is not in this trusted name list are converted to objects of type __PHP_Incomplete_Class
.
Any attempt to serialize an object having an anonymous class type results in an instance of type Exception
being thrown.
Predefined Classes
Class Closure
The predefined class Closure
is used
for representing an anonymous function. It
cannot be instantiated except by the Engine, as described below.
Closure objects are immutable and must not permit the creation or modification of properties.
Closures can be bound, unbound or static. If a closure is said to be
bound, then it has an object that $this
will be bound to when called. If a
closure is unbound, then it has no object $this
will be bound to. If a closure
is static, then it cannot be bound.
Closures can be scoped or unscoped. If a closure is said to be scoped, it
has a class scope which determines the visibility of the private and protected
members of objects of the class, including but not limited to such members on
$this
. If a closure is said to be unscoped, it has no class scope set.
Closures have an invariant that scoped closures must be bound or static, and
unbound closures must be unscoped.
class Closure
{
public static bind(Closure $closure, $newthis [, $newscope = "static" ]);
public bindTo($newthis [, $newscope = "static" ]);
public call($newthis [, ...$parameters ]);
}
The class members are defined below:
Name | Purpose |
---|---|
bind |
Duplicates closure $closure with a specific bound object $newthis and class scope $newscope . If $newthis is NULL then the closure is to be unbound if no scope is specified, or static if a scope is specified. $newscope is the scope the closure is to be given (either a string containing the name of a class, or an object whose class will be used), or "static" to keep the current one. Returns a new Closure object or FALSE on failure. This function must not violate the invariant that closures must either be both scoped and bound or static, or otherwise both unscoped and unbound. This function must prevent binding an object to the new closure if the $closure is static, however the new closure may have a different scope. |
bindTo |
Duplicates the closure designated by the current instance with a new-bound object and class scope. This method is an instance version of bind. |
call |
Calls the closure (the current instance) with $this bound to $newthis , the class scope of the class of $newthis , and the parameters specified by $parameters . This function must fail if $newthis is NULL, or if the closure is static. |
When the anonymous function creation operator is evaluated,
the result is an object of type Closure
(or some unspecified class
derived from that type) created by the Engine. This object is referred
to here as “the Closure object”. This instance encapsulates the
anonymous function defined in the corresponding
anonymous-function-creation-expression.
The contents of a Closure
object are determined based on the context in
which an anonymous function is created. Consider the following scenario:
class C
{
public function compute()
{
$count = 0;
$values = array("red" => 3, 10);
$callback = function ($p1, $p2) use (&$count, $values)
{
...
};
...
}
}
A Closure
object may contain the following, optional dynamic properties,
in order: static
, this
, and parameter
.
If an anonymous-function-creation-expression contains an
anonymous-function-use-clause, a dynamic property called static
is
present. This is unrelated to whether a closure is said to be static. This
property is an array having an element for each variable-name in the
use-variable-name-list, inserted in lexical order of their appearance in the
use clause. Each element’s key is the corresponding variable-name, and each
element value is the value of that variable at the time the time the Closure
object is created (not when it is used to call the encapsulated function). In
the scenario above, this leads to the following, shown as pseudo code:
$this->static = array(["count"]=>&0,["values"]=>array(["red"]=>3,[0]=>10));
If an anonymous-function-creation-expression is used inside an
instance method, a dynamic property called this
is present. This
property is a handle that points to the current instance. In the
scenario above, this leads to the following, shown as pseudo code:
$this->this = $this;
If an anonymous-function-creation-expression contains a
parameter-declaration-list, a dynamic property called parameter
is
present. This property is an array of one or more elements, each of
which corresponds to a parameter. The elements are inserted in that
array in lexical order of their declaration. Each element’s key is the
corresponding parameter name, and each element value is some unspecified
value. (These values are overridden by the argument values used when the
anonymous function is called). In the scenario above, this leads to the
following, shown as pseudo code:
$property = array("$p1" => ???, "$p2" => ???)
It is possible for all three dynamic properties to be absent, in which
case, the Closure
object is empty.
Closure objects can not be serialized or unserialized.
Class Generator
This class supports the yield
operator. This class cannot be
instantiated directly. It is defined, as follows:
class Generator implements Iterator
{
public function current();
public function getReturn();
public function key();
public function next();
public function rewind();
public function send($value) ;
public function throw(Exception $exception) ;
public function valid();
}
The class members are defined below:
Name | Purpose |
---|---|
current |
An implementation of the instance method Iterator::current . |
getReturn |
Returns the final expression from a generator, which was produced by a return statement rather than a yield . This function can only be called meaningfully once the generator has finishing yielding values; otherwise, an instance of Exception is thrown. |
key |
An implementation of the instance method Iterator::key . |
next |
An implementation of the instance method Iterator::next . |
rewind |
An implementation of the instance method Iterator::rewind . |
send |
This instance method sends the value designated by $value to the generator as the result of the current yield expression, and resumes execution of the generator. $value is the return value of the yield expression the generator is currently at. If the generator is not at a yield expression when this method is called, it will first be let to advance to the first yield expression before sending the value. This method returns the yielded value. |
throw |
This instance method throws an exception into the generator and resumes execution of the generator. The behavior is as if the current yield expression was replaced with throw $exception . If the generator is already closed when this method is invoked, the exception will be thrown in the caller’s context instead. This method returns the yielded value. |
valid |
An implementation of the instance method Iterator::valid . |
Generator objects can not be serialized or unserialized.
Class __PHP_Incomplete_Class
There are certain circumstances in which a program can generate an
instance of this class, which on its own contains no members. One
involves an attempt to unserialize a string that
encodes an instance of a class for which there is no definition or
if an object’s type is declared untrusted by unserialize
’s filter argument.
Consider the following code:
class Point
{
private $x;
private $y;
...
}
$p = new Point(2, 5);
$s = serialize($p); // properties $x and $y are serialized, in that order
Let us assume that the serialized string is stored in a database from
where it is retrieved by a separate program. That program contains the
following code, but does not contain a definition of the class Point:
$v = unserialize($s);
Instead of returning a point, Point(2, 5
), an instance of
__PHP_Incomplete_Class
results, with the following contents:
__PHP_Incomplete_Class
{
__PHP_Incomplete_Class_Name => "Point"
x:Point:private => 2
y:Point:private => 5
}
Object of this class can be serialized, however, any attempt to call its method or access its property
for any other operation except serialization will result in a fatal error.
Class stdClass
This class contains no members. It can be instantiated and used as a
base class. An instance of this type is automatically created when a
non-object is converted to an object,
or the member selection operator
is applied to NULL
, FALSE
, or an empty string.
Predefined Error Classes
PHP has a number of predefined classes that are used for error reporting. All these classes extend the base Error class.
Class Error
This class is the base class for all internal PHP error exceptions. It is defined, as follows:
class Error implements Throwable
{
protected $message = '';
protected $code = 0;
protected $file;
protected $line;
public function __construct($message = "", $code = 0,
Throwable $previous = NULL);
final private function __clone();
}
For information about the base interface, see Throwable.
Note that the methods from Throwable are implemented as final
in the Error class, which means
the extending class can not override them.
Class ArithmeticError
An instance of this class is thrown when an error occurs during certain mathematical operations. It is defined, as follows:
class ArithmeticError extends Error
{
}
Class AssertionError
An instance of this class is thrown when an assertion made via the intrinsic assert
fails. The class type is defined, as follows:
class AssertionError extends Error
{
}
Class DivisionByZeroError
An instance of this class is thrown when an attempt is made to divide a number by zero, e.g. when using the remainder operators (%
and %=
).
Note that this happens only for integer operations, regular float division (/
) produces a non-fatal error instead.
The class type is defined, as follows:
class DivisionByZeroError extends Error
{
}
Class ParseError
An instance of this class is thrown when an error occurs while parsing PHP code (such as when calling the intrinsic eval
). It is defined, as follows:
class ParseError extends Error
{
}
Class TypeError
An instance of this class is thrown when any of the following occurs:
- The type of an argument being passed to a function does not match its corresponding parameter’s declared type.
- The type of the value being returned from a function does not match the function’s declared return type.
- In strict mode, an invalid number of arguments are passed to a library function.
The class is defined, as follows:
class TypeError extends Error
{
}
See also class Exception
.