mirror of
https://github.com/php/doc-en.git
synced 2026-03-23 23:32:18 +01:00
The bottom type can't be used in a composite type for the same (rather, dual) reason the top type can't.
799 lines
19 KiB
XML
799 lines
19 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<sect1 xml:id="language.types.declarations">
|
|
<title>Type declarations</title>
|
|
|
|
<para>
|
|
Type declarations can be added to function arguments, return values,
|
|
as of PHP 7.4.0, class properties, and as of PHP 8.3.0, class constants.
|
|
They ensure that the value is of the specified type at call time,
|
|
otherwise a <classname>TypeError</classname> is thrown.
|
|
</para>
|
|
|
|
<para>
|
|
Every single type that PHP supports, with the exception of
|
|
<type>resource</type> can be used within a user-land type declaration.
|
|
This page contains a changelog of availability of the different types
|
|
and documentation about usage of them in type declarations.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
When a class implements an interface method or reimplements a method which
|
|
has already been defined by a parent class, it has to be compatible with the
|
|
aforementioned definition.
|
|
A method is compatible if it follows the
|
|
<link linkend="language.oop5.variance">variance</link> rules.
|
|
</para>
|
|
</note>
|
|
|
|
<sect2 role="changelog">
|
|
&reftitle.changelog;
|
|
<informaltable>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>&Version;</entry>
|
|
<entry>&Description;</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>8.3.0</entry>
|
|
<entry>
|
|
Support for class, interface, trait, and enum constant typing has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8.2.0</entry>
|
|
<entry>
|
|
Support for <acronym>DNF</acronym> types has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8.2.0</entry>
|
|
<entry>
|
|
Support for the literal type <type>true</type> has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8.2.0</entry>
|
|
<entry>
|
|
The types <type>null</type> and <type>false</type> can now be used standalone.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8.1.0</entry>
|
|
<entry>
|
|
Support for intersection types has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8.1.0</entry>
|
|
<entry>
|
|
Returning by reference from a <type>void</type> function is now deprecated.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8.1.0</entry>
|
|
<entry>
|
|
Support for the return only type <type>never</type> has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8.0.0</entry>
|
|
<entry>
|
|
Support for <type>mixed</type> has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8.0.0</entry>
|
|
<entry>
|
|
Support for the return only type <type>static</type> has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8.0.0</entry>
|
|
<entry>
|
|
Support for union types has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>7.4.0</entry>
|
|
<entry>
|
|
Support for class properties typing has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>7.2.0</entry>
|
|
<entry>
|
|
Support for <type>object</type> has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>7.1.0</entry>
|
|
<entry>
|
|
Support for <type>iterable</type> has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>7.1.0</entry>
|
|
<entry>
|
|
Support for <type>void</type> has been added.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>7.1.0</entry>
|
|
<entry>
|
|
Support for nullable types has been added.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.types.declarations.base">
|
|
<title>Atomic Types Usage Notes</title>
|
|
|
|
<simpara>
|
|
Atomic types have straight forward behaviour with some minor caveats which
|
|
are described in this section.
|
|
</simpara>
|
|
|
|
<sect3 xml:id="language.types.declarations.base.scalar">
|
|
<title>Scalar types</title>
|
|
<warning>
|
|
<para>
|
|
Name aliases for scalar types (<type>bool</type>, <type>int</type>,
|
|
<type>float</type>, <type>string</type>) are not supported.
|
|
Instead, they are treated as class or interface names.
|
|
For example, using <literal>boolean</literal> as a type declaration
|
|
will require the value to be an &instanceof; the class or interface
|
|
<literal>boolean</literal>, rather than of type <type>bool</type>:
|
|
</para>
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function test(boolean $param) {}
|
|
test(true);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.8;
|
|
<screen>
|
|
<![CDATA[
|
|
Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in /in/9YrUX on line 2
|
|
|
|
Fatal error: Uncaught TypeError: test(): Argument #1 ($param) must be of type boolean, bool given, called in - on line 3 and defined in -:2
|
|
Stack trace:
|
|
#0 -(3): test(true)
|
|
#1 {main}
|
|
thrown in - on line 2
|
|
]]>
|
|
</screen>
|
|
</informalexample>
|
|
</warning>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="language.types.declarations.void">
|
|
<title>void</title>
|
|
<note>
|
|
<para>
|
|
Returning by reference from a <type>void</type> function is deprecated as of PHP 8.1.0,
|
|
because such a function is contradictory.
|
|
Previously, it already emitted the following
|
|
<constant>E_NOTICE</constant> when called:
|
|
<computeroutput>Only variable references should be returned by reference</computeroutput>.
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function &test(): void {}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
</note>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="language.types.declarations.base.function">
|
|
<title>Callable types</title>
|
|
<para>
|
|
This type cannot be used as a class property type declaration.
|
|
</para>
|
|
|
|
<note>
|
|
<simpara>
|
|
It is not possible to specify the signature of the function.
|
|
</simpara>
|
|
</note>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="language.types.declarations.references">
|
|
<title>Type declarations on pass-by-reference Parameters</title>
|
|
|
|
<simpara>
|
|
If a pass-by-reference parameter has a type declaration, the type of the
|
|
variable is <emphasis>only</emphasis> checked on function entry, at the
|
|
beginning of the call, but not when the function returns.
|
|
This means that a function can change the type of variable reference.
|
|
</simpara>
|
|
<example>
|
|
<title>Typed pass-by-reference Parameters</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function array_baz(array &$param)
|
|
{
|
|
$param = 1;
|
|
}
|
|
$var = [];
|
|
array_baz($var);
|
|
var_dump($var);
|
|
array_baz($var);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
int(1)
|
|
|
|
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type array, int given, called in - on line 9 and defined in -:2
|
|
Stack trace:
|
|
#0 -(9): array_baz(1)
|
|
#1 {main}
|
|
thrown in - on line 2
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.types.declarations.composite">
|
|
<title>Composite Types Usage Notes</title>
|
|
<para>
|
|
Composite type declarations are subject to a couple of restrictions and
|
|
will perform a redundancy check at compile time to prevent simple bugs.
|
|
</para>
|
|
|
|
<caution>
|
|
<simpara>
|
|
Prior to PHP 8.2.0, and the introduction of <acronym>DNF</acronym> types,
|
|
it was not possible to combine intersection types with union types.
|
|
</simpara>
|
|
</caution>
|
|
|
|
<sect3 xml:id="language.types.declarations.composite.union">
|
|
<title>Union types</title>
|
|
<warning>
|
|
<simpara>
|
|
It is not possible to combine the two singleton types <type>false</type>
|
|
and <type>true</type> together in a union type.
|
|
Use <type>bool</type> instead.
|
|
</simpara>
|
|
</warning>
|
|
|
|
<caution>
|
|
<simpara>
|
|
Prior to PHP 8.2.0, as <type>false</type> and <type>null</type>
|
|
could not be used as standalone types, a union type comprised of only
|
|
these types was not permitted. This comprises the following types:
|
|
<type>false</type>, <literal>false|null</literal>,
|
|
and <literal>?false</literal>.
|
|
</simpara>
|
|
</caution>
|
|
|
|
<sect4 xml:id="language.types.declarations.nullable">
|
|
<title>Nullable type syntactic sugar</title>
|
|
|
|
<para>
|
|
A single base type declaration can be marked nullable by prefixing the
|
|
type with a question mark (<literal>?</literal>).
|
|
Thus <literal>?T</literal> and <literal>T|null</literal> are identical.
|
|
</para>
|
|
|
|
<note>
|
|
<simpara>
|
|
This syntax is supported as of PHP 7.1.0, and predates generalized union
|
|
types support.
|
|
</simpara>
|
|
</note>
|
|
|
|
<note>
|
|
<para>
|
|
It is also possible to achieve nullable arguments by making
|
|
<literal>null</literal> the default value.
|
|
This is not recommended as if the default value is changed in a child
|
|
class a type compatibility violation will be raised as the
|
|
<type>null</type> type will need to be added to the type declaration.
|
|
This behavior is also deprecated since PHP 8.4.
|
|
</para>
|
|
<example>
|
|
<title>Old way to make arguments nullable</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class C {}
|
|
|
|
function f(C $c = null) {
|
|
var_dump($c);
|
|
}
|
|
|
|
f(new C);
|
|
f(null);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
object(C)#1 (0) {
|
|
}
|
|
NULL
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</note>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="language.types.declarations.composite.redundant">
|
|
<title>Duplicate and redundant types</title>
|
|
<para>
|
|
To catch simple bugs in composite type declarations, redundant types that
|
|
can be detected without performing class loading will result in a
|
|
compile-time error. This includes:
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Each name-resolved type may only occur once. Types such as
|
|
<literal>int|string|INT</literal> or
|
|
<literal>Countable&Traversable&COUNTABLE</literal>
|
|
result in an error.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Using <type>mixed</type> or <type>never</type> results in an error.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>For union types:</simpara>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
If <type>bool</type> is used, <type>false</type> or <type>true</type>
|
|
cannot be used additionally.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
If <type>object</type> is used, class types cannot be used additionally.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
If <type>iterable</type> is used, <type>array</type>
|
|
and <classname>Traversable</classname> cannot be used additionally.
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>For intersection types:</simpara>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Using a type which is not a class-type results in an error.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Using either <type>self</type>, <type>parent</type>, or
|
|
<type>static</type> results in an error.
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>For <acronym>DNF</acronym> types:</simpara>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
If a more generic type is used, the more restrictive one is redundant.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Using two identical intersection types.
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
|
|
<note>
|
|
<simpara>
|
|
This does not guarantee that the type is “minimal”, because doing so would
|
|
require loading all used class types.
|
|
</simpara>
|
|
</note>
|
|
|
|
<para>
|
|
For example, if <literal>A</literal> and <literal>B</literal> are class
|
|
aliases, then <literal>A|B</literal> remains a legal union type, even
|
|
though it could be reduced to either <literal>A</literal> or
|
|
<literal>B</literal>.
|
|
Similarly, if class <code>B extends A {}</code>, then <literal>A|B</literal>
|
|
is also a legal union type, even though it could be reduced to just
|
|
<literal>A</literal>.
|
|
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo(): int|INT {} // Disallowed
|
|
function foo(): bool|false {} // Disallowed
|
|
function foo(): int&Traversable {} // Disallowed
|
|
function foo(): self&Traversable {} // Disallowed
|
|
|
|
use A as B;
|
|
function foo(): A|B {} // Disallowed ("use" is part of name resolution)
|
|
function foo(): A&B {} // Disallowed ("use" is part of name resolution)
|
|
|
|
class_alias('X', 'Y');
|
|
function foo(): X|Y {} // Allowed (redundancy is only known at runtime)
|
|
function foo(): X&Y {} // Allowed (redundancy is only known at runtime)
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.types.declarations.examples">
|
|
&reftitle.examples;
|
|
<example>
|
|
<title>Basic class type declaration</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class C {}
|
|
class D extends C {}
|
|
|
|
// This doesn't extend C.
|
|
class E {}
|
|
|
|
function f(C $c) {
|
|
echo get_class($c)."\n";
|
|
}
|
|
|
|
f(new C);
|
|
f(new D);
|
|
f(new E);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.8;
|
|
<screen>
|
|
<![CDATA[
|
|
C
|
|
D
|
|
|
|
Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8
|
|
Stack trace:
|
|
#0 -(14): f(Object(E))
|
|
#1 {main}
|
|
thrown in - on line 8
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Basic interface type declaration</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
interface I { public function f(); }
|
|
class C implements I { public function f() {} }
|
|
|
|
// This doesn't implement I.
|
|
class E {}
|
|
|
|
function f(I $i) {
|
|
echo get_class($i)."\n";
|
|
}
|
|
|
|
f(new C);
|
|
f(new E);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.8;
|
|
<screen>
|
|
<![CDATA[
|
|
C
|
|
|
|
Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8
|
|
Stack trace:
|
|
#0 -(13): f(Object(E))
|
|
#1 {main}
|
|
thrown in - on line 8
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Basic return type declaration</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function sum($a, $b): float {
|
|
return $a + $b;
|
|
}
|
|
|
|
// Note that a float will be returned.
|
|
var_dump(sum(1, 2));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
float(3)
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Returning an object</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class C {}
|
|
|
|
function getC(): C {
|
|
return new C;
|
|
}
|
|
|
|
var_dump(getC());
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
object(C)#1 (0) {
|
|
}
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Nullable argument type declaration</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class C {}
|
|
|
|
function f(?C $c) {
|
|
var_dump($c);
|
|
}
|
|
|
|
f(new C);
|
|
f(null);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
object(C)#1 (0) {
|
|
}
|
|
NULL
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Nullable return type declaration</title>
|
|
<programlisting role="php" annotations="non-interactive">
|
|
<![CDATA[
|
|
<?php
|
|
function get_item(): ?string {
|
|
if (isset($_GET['item'])) {
|
|
return $_GET['item'];
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Class property type declaration</title>
|
|
<programlisting role="php" annotations="non-interactive">
|
|
<![CDATA[
|
|
<?php
|
|
class User {
|
|
public static string $foo = 'foo';
|
|
|
|
public int $id;
|
|
public string $username;
|
|
|
|
public function __construct(int $id, string $username) {
|
|
$this->id = $id;
|
|
$this->username = $username;
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect2>
|
|
|
|
<!-- TODO Move this into its own declare page -->
|
|
<sect2 xml:id="language.types.declarations.strict">
|
|
<title>Strict typing</title>
|
|
|
|
<para>
|
|
By default, PHP will coerce values of the wrong type into the expected
|
|
scalar type declaration if possible. For example, a function that is given
|
|
an <type>int</type> for a parameter that expects a <type>string</type>
|
|
will get a variable of type <type>string</type>.
|
|
</para>
|
|
|
|
<para>
|
|
It is possible to enable strict mode on a per-file basis. In strict
|
|
mode, only a value corresponding exactly to the type declaration will be
|
|
accepted, otherwise a <classname>TypeError</classname> will be thrown.
|
|
The only exception to this rule is that an <type>int</type> value will
|
|
pass a <type>float</type> type declaration.
|
|
</para>
|
|
|
|
<warning>
|
|
<simpara>
|
|
Function calls from within internal functions will not be affected by
|
|
the <literal>strict_types</literal> declaration.
|
|
</simpara>
|
|
</warning>
|
|
|
|
<para>
|
|
To enable strict mode, the &declare; statement is used with the
|
|
<literal>strict_types</literal> declaration:
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Strict typing applies to function calls made from
|
|
<emphasis>within</emphasis> the file with strict typing enabled, not to
|
|
the functions declared within that file. If a file without strict
|
|
typing enabled makes a call to a function that was defined in a file
|
|
with strict typing, the caller's preference (coercive typing) will be
|
|
respected, and the value will be coerced.
|
|
</para>
|
|
</note>
|
|
|
|
<note>
|
|
<para>
|
|
Strict typing is only defined for scalar type declarations.
|
|
</para>
|
|
</note>
|
|
|
|
<example>
|
|
<title>Strict typing for arguments values</title>
|
|
<programlisting role="php" annotations="non-interactive">
|
|
<![CDATA[
|
|
<?php
|
|
declare(strict_types=1);
|
|
|
|
function sum(int $a, int $b) {
|
|
return $a + $b;
|
|
}
|
|
|
|
var_dump(sum(1, 2));
|
|
var_dump(sum(1.5, 2.5));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.8;
|
|
<screen>
|
|
<![CDATA[
|
|
int(3)
|
|
|
|
Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 9 and defined in -:4
|
|
Stack trace:
|
|
#0 -(9): sum(1.5, 2.5)
|
|
#1 {main}
|
|
thrown in - on line 4
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Coercive typing for argument values</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function sum(int $a, int $b) {
|
|
return $a + $b;
|
|
}
|
|
|
|
var_dump(sum(1, 2));
|
|
|
|
// These will be coerced to integers: note the output below!
|
|
var_dump(sum(1.5, 2.5));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
int(3)
|
|
int(3)
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Strict typing for return values</title>
|
|
<programlisting role="php" annotations="non-interactive">
|
|
<![CDATA[
|
|
<?php
|
|
declare(strict_types=1);
|
|
|
|
function sum($a, $b): int {
|
|
return $a + $b;
|
|
}
|
|
|
|
var_dump(sum(1, 2));
|
|
var_dump(sum(1, 2.5));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
int(3)
|
|
|
|
Fatal error: Uncaught TypeError: sum(): Return value must be of type int, float returned in -:5
|
|
Stack trace:
|
|
#0 -(9): sum(1, 2.5)
|
|
#1 {main}
|
|
thrown in - on line 5
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</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
|
|
-->
|