mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-15 16:38:54 +00:00
368 lines
12 KiB
XML
368 lines
12 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<sect1 xml:id="language.oop5.decon" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Constructors and Destructors</title>
|
|
|
|
<sect2 xml:id="language.oop5.decon.constructor">
|
|
<title>Constructor</title>
|
|
<methodsynopsis xml:id="object.construct">
|
|
<type>void</type><methodname>__construct</methodname>
|
|
<methodparam rep="repeat"><type>mixed</type><parameter>values</parameter><initializer>""</initializer></methodparam>
|
|
</methodsynopsis>
|
|
<para>
|
|
PHP allows developers to declare constructor methods for classes.
|
|
Classes which have a constructor method call this method on each
|
|
newly-created object, so it is suitable for any initialization that the
|
|
object may need before it is used.
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
Parent constructors are not called implicitly if the child class defines
|
|
a constructor. In order to run a parent constructor, a call to
|
|
<function>parent::__construct</function> within the child constructor is
|
|
required. If the child does not define a constructor then it may be inherited
|
|
from the parent class just like a normal class method (if it was not declared
|
|
as private).
|
|
</simpara>
|
|
</note>
|
|
<example>
|
|
<title>Constructors in inheritance</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class BaseClass {
|
|
function __construct() {
|
|
print "In BaseClass constructor\n";
|
|
}
|
|
}
|
|
|
|
class SubClass extends BaseClass {
|
|
function __construct() {
|
|
parent::__construct();
|
|
print "In SubClass constructor\n";
|
|
}
|
|
}
|
|
|
|
class OtherSubClass extends BaseClass {
|
|
// inherits BaseClass's constructor
|
|
}
|
|
|
|
// In BaseClass constructor
|
|
$obj = new BaseClass();
|
|
|
|
// In BaseClass constructor
|
|
// In SubClass constructor
|
|
$obj = new SubClass();
|
|
|
|
// In BaseClass constructor
|
|
$obj = new OtherSubClass();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Unlike other methods, <link linkend="object.construct">__construct()</link>
|
|
is exempt from the usual
|
|
<link linkend="language.oop.lsp">signature compatibility rules</link>
|
|
when being extended.
|
|
</para>
|
|
<para>
|
|
Constructors are ordinary methods which are called during the instantiation of their
|
|
corresponding object. As such, they may define an arbitrary number of arguments, which
|
|
may be required, may have a type, and may have a default value. Constructor arguments
|
|
are called by placing the arguments in parentheses after the class name.
|
|
</para>
|
|
<example>
|
|
<title>Using constructor arguments</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Point {
|
|
protected int $x;
|
|
protected int $y;
|
|
|
|
public function __construct(int $x, int $y = 0) {
|
|
$this->x = $x;
|
|
$this->y = $y;
|
|
}
|
|
}
|
|
|
|
// Pass both parameters.
|
|
$p1 = new Point(4, 5);
|
|
// Pass only the required parameter. $y will take its default value of 0.
|
|
$p2 = new Point(4);
|
|
// With named parameters (as of PHP 8.0):
|
|
$p3 = new Point(y: 5, x: 4);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
If a class has no constructor, or the constructor has no required arguments, the parentheses
|
|
may be omitted.
|
|
</para>
|
|
<sect3>
|
|
<title>Old-style constructors</title>
|
|
<para>
|
|
Prior to PHP 8.0.0, classes in the global namespace will interpret a method named
|
|
the same as the class as an old-style constructor. That syntax is deprecated,
|
|
and will result in an <constant>E_DEPRECATED</constant> error but still call that function as a constructor.
|
|
If both <link linkend="object.construct">__construct()</link> and a same-name method are
|
|
defined, <link linkend="object.construct">__construct()</link> will be called.
|
|
</para>
|
|
<para>
|
|
In namespaced classes, or any class as of PHP 8.0.0, a method named
|
|
the same as the class never has any special meaning.
|
|
</para>
|
|
<para>Always use <link linkend="object.construct">__construct()</link> in new code.
|
|
</para>
|
|
</sect3>
|
|
<sect3 xml:id="language.oop5.decon.constructor.promotion">
|
|
<title>Constructor Promotion</title>
|
|
<para>
|
|
As of PHP 8.0.0, constructor parameters may also be promoted to correspond to an
|
|
object property. It is very common for constructor parameters to be assigned to
|
|
a property in the constructor but otherwise not operated upon. Constructor promotion
|
|
provides a short-hand for that use case. The example above could be rewritten as the following.
|
|
</para>
|
|
<example>
|
|
<title>Using constructor property promotion</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Point {
|
|
public function __construct(protected int $x, protected int $y = 0) {
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
When a constructor argument includes a visibility modifier, PHP will interpret it as
|
|
both an object property and a constructor argument, and assign the argument value to
|
|
the property. The constructor body may then be empty or may contain other statements.
|
|
Any additional statements will be executed after the argument values have been assigned
|
|
to the corresponding properties.
|
|
</para>
|
|
<para>
|
|
Not all arguments need to be promoted. It is possible to mix and match promoted and not-promoted
|
|
arguments, in any order. Promoted arguments have no impact on code calling the constructor.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Object properties may not be typed <type>callable</type> due to engine ambiguity that would
|
|
introduce. Promoted arguments, therefore, may not be typed <type>callable</type> either. Any
|
|
other <link linkend="language.types.declarations">type declaration</link> is permitted, however.
|
|
</para>
|
|
</note>
|
|
<note>
|
|
<para>
|
|
<link linkend="language.attributes">Attributes</link> placed on a
|
|
promoted constructor argument will be replicated to both the property
|
|
and argument.
|
|
</para>
|
|
</note>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="language.oop5.decon.constructor.new">
|
|
<title>New in initializers</title>
|
|
<para>
|
|
As of PHP 8.1.0, objects can be used as default parameter values,
|
|
static variables, and global constants, as well as in attribute arguments.
|
|
Objects can also be passed to <function>define</function> now.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
The use of a dynamic or non-string class name or an anonymous class is not allowed.
|
|
The use of argument unpacking is not allowed.
|
|
The use of unsupported expressions as arguments is not allowed.
|
|
</para>
|
|
</note>
|
|
<example>
|
|
<title>Using new in initializers</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// All allowed:
|
|
static $x = new Foo;
|
|
|
|
const C = new Foo;
|
|
|
|
function test($param = new Foo) {}
|
|
|
|
#[AnAttribute(new Foo)]
|
|
class Test {
|
|
public function __construct(
|
|
public $prop = new Foo,
|
|
) {}
|
|
}
|
|
|
|
// All not allowed (compile-time error):
|
|
function test(
|
|
$a = new (CLASS_NAME_CONSTANT)(), // dynamic class name
|
|
$b = new class {}, // anonymous class
|
|
$c = new A(...[]), // argument unpacking
|
|
$d = new B($abc), // unsupported constant expression
|
|
) {}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="language.oop5.decon.constructor.static">
|
|
<title>Static creation methods</title>
|
|
<para>
|
|
PHP only supports a single constructor per class. In some cases, however, it may be
|
|
desirable to allow an object to be constructed in different ways with different inputs.
|
|
The recommended way to do so is by using static methods as constructor wrappers.
|
|
</para>
|
|
<example>
|
|
<title>Using static creation methods</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Product {
|
|
|
|
private ?int $id;
|
|
private ?string $name;
|
|
|
|
private function __construct(?int $id = null, ?string $name = null) {
|
|
$this->id = $id;
|
|
$this->name = $name;
|
|
}
|
|
|
|
public static function fromBasicData(int $id, string $name): static {
|
|
$new = new static($id, $name);
|
|
return $new;
|
|
}
|
|
|
|
public static function fromJson(string $json): static {
|
|
$data = json_decode($json);
|
|
return new static($data['id'], $data['name']);
|
|
}
|
|
|
|
public static function fromXml(string $xml): static {
|
|
// Custom logic here.
|
|
$data = convert_xml_to_array($xml);
|
|
$new = new static();
|
|
$new->id = $data['id'];
|
|
$new->name = $data['name'];
|
|
return $new;
|
|
}
|
|
}
|
|
|
|
$p1 = Product::fromBasicData(5, 'Widget');
|
|
$p2 = Product::fromJson($some_json_string);
|
|
$p3 = Product::fromXml($some_xml_string);
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
The constructor may be made private or protected to prevent it from being called externally.
|
|
If so, only a static method will be able to instantiate the class. Because they are in the
|
|
same class definition they have access to private methods, even if not of the same object
|
|
instance. The private constructor is optional and may or may not make sense depending on
|
|
the use case.
|
|
</para>
|
|
<para>
|
|
The three public static methods then demonstrate different ways of instantiating the object.
|
|
</para>
|
|
<simplelist>
|
|
<member><code>fromBasicData()</code> takes the exact parameters that are needed, then creates the
|
|
object by calling the constructor and returning the result.</member>
|
|
<member><code>fromJson()</code> accepts a JSON string and does some pre-processing on it itself
|
|
to convert it into the format desired by the constructor. It then returns the new object.</member>
|
|
<member><code>fromXml()</code> accepts an XML string, preprocesses it, and then creates a bare
|
|
object. The constructor is still called, but as all of the parameters are optional the method
|
|
skips them. It then assigns values to the object properties directly before returning the result.</member>
|
|
</simplelist>
|
|
<para>
|
|
In all three cases, the <code>static</code> keyword is translated into the name of the class the code is in.
|
|
In this case, <code>Product</code>.
|
|
</para>
|
|
</sect3>
|
|
</sect2>
|
|
<sect2 xml:id="language.oop5.decon.destructor">
|
|
<title>Destructor</title>
|
|
<methodsynopsis xml:id="object.destruct">
|
|
<type>void</type><methodname>__destruct</methodname>
|
|
<void />
|
|
</methodsynopsis>
|
|
<para>
|
|
PHP possesses a destructor concept similar to that of other
|
|
object-oriented languages, such as C++. The destructor method will be
|
|
called as soon as there are no other references to a particular object,
|
|
or in any order during the shutdown sequence.
|
|
</para>
|
|
<example>
|
|
<title>Destructor Example</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class MyDestructableClass
|
|
{
|
|
function __construct() {
|
|
print "In constructor\n";
|
|
}
|
|
|
|
function __destruct() {
|
|
print "Destroying " . __CLASS__ . "\n";
|
|
}
|
|
}
|
|
|
|
$obj = new MyDestructableClass();
|
|
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Like constructors, parent destructors will not be called implicitly by
|
|
the engine. In order to run a parent destructor, one would have to
|
|
explicitly call <function>parent::__destruct</function> in the destructor
|
|
body. Also like constructors, a child class may inherit the parent's
|
|
destructor if it does not implement one itself.
|
|
</para>
|
|
<para>
|
|
The destructor will be called even if script execution is stopped using
|
|
<function>exit</function>. Calling <function>exit</function> in a destructor
|
|
will prevent the remaining shutdown routines from executing.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Destructors called during the script shutdown have HTTP headers already
|
|
sent. The working directory in the script shutdown phase can be different
|
|
with some SAPIs (e.g. Apache).
|
|
</para>
|
|
</note>
|
|
<note>
|
|
<para>
|
|
Attempting to throw an exception from a destructor (called in the time of
|
|
script termination) causes a fatal error.
|
|
</para>
|
|
</note>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|