Skip to content

Commit e31c870

Browse files
committed
Optional parameter changes in 8.1, and description improvements
オプションの引数の後に必須を続けることは、PHP 8.0.0 以降 deprecated であったが、UPGRADING ファイルへの予告なしに 8.1.0 から ArgumentCountError が発生するようになった。 予告がなかったのは、UPGRADING への反映漏れが原因で、事故ではある。が、PHP クオリティと言われないためにも再発しないように願いたい... * Document change in behaviour of misplaced optional parameters in 8.1 (see php/php-src@afc4d67c) * Expand and update documentation of default/optional parameters * Fix example labels to use correctly formatted entities * Style improvements, and a couple of extra notes. php/doc-en@0bafd54
1 parent 3afa3ac commit e31c870

File tree

3 files changed

+193
-53
lines changed

3 files changed

+193
-53
lines changed

appendices/migration81/incompatible.xml

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<!-- $Revision$ -->
3-
<!-- EN-Revision: 9c21d93b4c2659081f995fcf63b7b7133b753f84 Maintainer: mumumu Status: ready -->
3+
<!-- EN-Revision: 0bafd5454e7c54de5b9e455f997bec3ecf89cfdb Maintainer: mumumu Status: ready -->
44
<sect1 xml:id="migration81.incompatible" xmlns:xlink="http://www.w3.org/1999/xlink">
55
<title>下位互換性のない変更点</title>
66

@@ -61,6 +61,69 @@ var_dump(B::counter()); // int(4), 以前のバージョンでは int(2)
6161
</para>
6262
</sect3>
6363

64+
<sect3 xml:id="migration81.incompatible.core.optional-before-required">
65+
<title>必須の引数の前に、デフォルト値を持つ引数を指定した場合</title>
66+
67+
<para>
68+
必須の引数の前に、
69+
<link linkend="functions.arguments.default">デフォルト値を持つ引数</link>
70+
を指定した場合、
71+
デフォルト値を持つ引数は常に必須の引数として扱われるようになりました。
72+
これは、
73+
<link linkend="functions.named-arguments">名前付き引数</link>
74+
を使って関数を呼び出した場合でも同様です。
75+
PHP 8.0.0 以降、かつ 8.1.0 より前のバージョンでは、
76+
以下のコードは推奨されない警告を発生させていましたが、
77+
呼び出しは成功していました。
78+
PHP 8.1.0 以降では、
79+
<classname>ArgumentCountError</classname>
80+
がスローされるようになっています。
81+
位置を指定して呼び出した場合でも、同じエラーがスローされます。
82+
<informalexample>
83+
<programlisting role="php">
84+
<![CDATA[
85+
<?php
86+
function makeyogurt($container = "bowl", $flavour)
87+
{
88+
return "Making a $container of $flavour yogurt.\n";
89+
}
90+
try
91+
{
92+
echo makeyogurt(flavour: "raspberry");
93+
}
94+
catch (Error $e)
95+
{
96+
echo get_class($e), ' - ', $e->getMessage(), "\n";
97+
}
98+
?>
99+
]]>
100+
</programlisting>
101+
&example.outputs.80;
102+
<screen>
103+
<![CDATA[
104+
Deprecated: Required parameter container
105+
in example.php on line 3
106+
Making a bowl of raspberry yogurt.
107+
]]>
108+
</screen>
109+
&example.outputs.81;
110+
<screen>
111+
<![CDATA[
112+
Deprecated: Optional parameter $container declared before required parameter
113+
$flavour is implicitly treated as a required parameter in example.php on line 3
114+
ArgumentCountError - makeyogurt(): Argument #1 ($container) not passed
115+
]]>
116+
</screen>
117+
</informalexample>
118+
</para>
119+
<para>
120+
但し、必須の引数の前であっても、
121+
<link linkend="language.types.declarations.nullable">Null を許容する型</link> を指定するために、
122+
引数にデフォルト値 &null; を指定できることに注意して下さい。
123+
その場合でも、その引数は必須であることには変わりありません。
124+
</para>
125+
</sect3>
126+
64127
<sect3 xml:id="migration81.incompatible.core.type-compatibility-internal">
65128
<title>内部クラスと戻り値の型の互換性</title>
66129

language-snippets.ent

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<!-- $Revision$ -->
3-
<!-- EN-Revision: 04210d535db52aed64b82572817f059059ddfebc Maintainer: takagi Status: working -->
3+
<!-- EN-Revision: 0bafd5454e7c54de5b9e455f997bec3ecf89cfdb Maintainer: takagi Status: working -->
44
<!-- Credits: hirokawa,haruki,shimooka,mumumu -->
55

66
<!ENTITY installation.enabled.disable 'この拡張モジュールはデフォルトで有効になっています。無効にしたい場合は、次のオプションを指定してコンパイルします。'>
@@ -539,6 +539,8 @@ PHP では、<literal>https://</literal> ラッパーでストリームをオー
539539

540540
<!ENTITY example.outputs.80 '<para xmlns="http://docbook.org/ns/docbook">上の例の PHP 8.0 での出力は、このようになります。:</para>'>
541541

542+
<!ENTITY example.outputs.81 '<para xmlns="http://docbook.org/ns/docbook">上の例の PHP 8.1 での出力は、このようになります。:</para>'>
543+
542544
<!ENTITY example.outputs.32bit '<para xmlns="http://docbook.org/ns/docbook">上の例の 32 ビットマシンでの出力は、このようになります。</para>'>
543545

544546
<!ENTITY example.outputs.64bit '<para xmlns="http://docbook.org/ns/docbook">上の例の 64 ビットマシンでの出力は、このようになります。</para>'>

language/functions.xml

Lines changed: 126 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<!-- $Revision$ -->
3-
<!-- EN-Revision: 5c2678e02f0eb135946799eed02d884de1bcf4ad Maintainer: takagi Status: ready -->
3+
<!-- EN-Revision: 0bafd5454e7c54de5b9e455f997bec3ecf89cfdb Maintainer: takagi Status: ready -->
44
<!-- CREDITS: hirokawa,mumumu -->
55
<chapter xml:id="language.functions" xmlns="http://docbook.org/ns/docbook">
66
<title>関数</title>
@@ -229,29 +229,6 @@ function takes_many_args(
229229
// ...
230230
}
231231
?>
232-
]]>
233-
</programlisting>
234-
</example>
235-
<para>
236-
PHP 8.0.0 以降では、オプションの引数の後に、
237-
必須の引数を続けて宣言することは、
238-
推奨されなくなります。
239-
一般的には、デフォルト値を削除することで解決できます。
240-
このルールの唯一の例外は、<code>Type $param = null</code> と書かれた引数です。
241-
null をデフォルトにすることは、型が暗黙のうちに nullable であることを示しています。
242-
この書き方はまだ許可されていますが、明示的に nullable 型を使うことを推奨します。
243-
</para>
244-
<example>
245-
<title>オプションの引数の後に、必須の引数を続けて宣言する</title>
246-
<programlisting role="php">
247-
<![CDATA[
248-
<?php
249-
function foo($a = [], $b) {} // PHP 8.0.0 より前
250-
function foo($a, $b) {} // PHP 8.0.0 以後
251-
252-
function bar(A $a = null, $b) {} // PHP 8.0.0 でもまだ許可されています
253-
function bar(?A $a, $b) {} // お勧めの書き方
254-
?>
255232
]]>
256233
</programlisting>
257234
</example>
@@ -296,12 +273,15 @@ echo $str; // 出力は 'This is a string, and something extra.' となりま
296273
<title>デフォルト引数値</title>
297274

298275
<para>
299-
関数は、スカラー引数に関して次のように C++ スタイルのデフォルト値を
300-
定義することができます。
276+
関数は、変数に代入する記法に似たやり方で、
277+
デフォルト値を引数に定義することができます。
278+
デフォルト値は引数が指定されなかった場合に使われますが、
279+
&null; を渡した場合はデフォルト値を代入
280+
<emphasis>しない</emphasis> ことに特に注意して下さい。
301281
</para>
302282
<para>
303283
<example>
304-
<title>関数におけるデフォルトパラメータの使用法</title>
284+
<title>関数におけるデフォルト引数の使用法</title>
305285
<programlisting role="php">
306286
<![CDATA[
307287
<?php
@@ -326,8 +306,11 @@ Making a cup of espresso.
326306
</example>
327307
</para>
328308
<para>
329-
PHPでは、配列および特殊な型 &null; をデフォルト値とすることも可能です。
330-
例えば、
309+
デフォルト引数の値には、スカラー値、
310+
配列、および特殊な型 &null; を指定できます。
311+
PHP 8.1.0 以降では、
312+
<link linkend="language.oop5.basic.new">new ClassName()</link>
313+
記法を使ってオブジェクトも指定できます。
331314
</para>
332315
<para>
333316
<example>
@@ -341,44 +324,69 @@ function makecoffee($types = array("cappuccino"), $coffeeMaker = NULL)
341324
return "Making a cup of ".join(", ", $types)." with $device.\n";
342325
}
343326
echo makecoffee();
344-
echo makecoffee(array("cappuccino", "lavazza"), "teapot");
327+
echo makecoffee(array("cappuccino", "lavazza"), "teapot");?>
328+
]]>
329+
</programlisting>
330+
</example>
331+
</para>
332+
<para>
333+
<example>
334+
<title>オブジェクトをデフォルト値として使用する(PHP 8.1.0 以降)</title>
335+
<programlisting role="php">
336+
<![CDATA[
337+
<?php
338+
class DefaultCoffeeMaker {
339+
public function brew() {
340+
return 'Making coffee.';
341+
}
342+
}
343+
class FancyCoffeeMaker {
344+
public function brew() {
345+
return 'Crafting a beautiful coffee just for you.';
346+
}
347+
}
348+
function makecoffee($coffeeMaker = new DefaultCoffeeMaker)
349+
{
350+
return $coffeeMaker->brew();
351+
}
352+
echo makecoffee();
353+
echo makecoffee(new FancyCoffeeMaker);
345354
?>
346355
]]>
347356
</programlisting>
348357
</example>
349-
350358
</para>
351359
<simpara>
352360
デフォルト値は、定数式である必要があり、
353361
(例えば) 変数やクラスのメンバーであってはなりません。
354362
</simpara>
355363
<para>
356-
引数のデフォルト値を使用する際には、デフォルト値を有する引数はデ
357-
フォルト値がない引数の右側に全てある必要があることに注意して下さ
358-
い。そうでない場合、意図したような動作が行われません。次の簡単な
359-
コードを見てみましょう。
364+
デフォルト値を有する引数は、
365+
デフォルト値がない引数の右側に全てある必要があることに注意して下さい。
366+
そうでない場合、デフォルト値を指定していても、
367+
呼び出し時に省略できません。
368+
次の簡単なコードを見てみましょう。
360369
</para>
361370
<para>
362371
<example>
363372
<title>関数の引数のデフォルト値の 間違った使用法</title>
364373
<programlisting role="php">
365374
<![CDATA[
366375
<?php
367-
function makeyogurt($type = "acidophilus", $flavour)
376+
function makeyogurt($container = "bowl", $flavour)
368377
{
369-
return "Making a bowl of $type $flavour.\n";
378+
return "Making a $container of $flavour yogurt.\n";
370379
}
371380
372-
echo makeyogurt("raspberry"); // 期待通りには動作しません
381+
echo makeyogurt("raspberry"); // $container に "raspberry" を指定します。$flavour ではありません
373382
?>
374383
]]>
375384
</programlisting>
376385
&example.outputs;
377386
<screen>
378387
<![CDATA[
379-
Warning: Missing argument 2 in call to makeyogurt() in
380-
/usr/local/etc/httpd/htdocs/phptest/functest.html on line 41
381-
Making a bowl of raspberry .
388+
Fatal error: Uncaught ArgumentCountError: Too few arguments
389+
to function makeyogurt(), 1 passed in example.php on line 42
382390
]]>
383391
</screen>
384392
</example>
@@ -392,23 +400,90 @@ Making a bowl of raspberry .
392400
<programlisting role="php">
393401
<![CDATA[
394402
<?php
395-
function makeyogurt($flavour, $type = "acidophilus")
403+
function makeyogurt($flavour, $container = "bowl")
396404
{
397-
return "Making a bowl of $type $flavour.\n";
405+
return "Making a $container of $flavour yogurt.\n";
398406
}
399407
400-
echo makeyogurt("raspberry"); // 期待通り動作します
408+
echo makeyogurt("raspberry"); // $flavour に "raspberry" を指定します。
401409
?>
402410
]]>
403411
</programlisting>
404412
&example.outputs;
405413
<screen>
406414
<![CDATA[
407-
Making a bowl of acidophilus raspberry.
415+
Making a bowl of raspberry yogurt.
408416
]]>
409417
</screen>
410418
</example>
411419
</para>
420+
<para>
421+
PHP 8.0.0 以降では、
422+
デフォルト値を指定した引数を複数スキップするために、
423+
<link linkend="functions.named-arguments">名前付き引数</link>
424+
が使えます。
425+
</para>
426+
<para>
427+
<example>
428+
<title>関数の引数のデフォルト値の 正しい使用法</title>
429+
<programlisting role="php">
430+
<![CDATA[
431+
<?php
432+
function makeyogurt($container = "bowl", $flavour = "raspberry", $style = "Greek")
433+
{
434+
return "Making a $container of $flavour $style yogurt.\n";
435+
}
436+
437+
echo makeyogurt(style: "natural");
438+
?>
439+
]]>
440+
</programlisting>
441+
&example.outputs;
442+
<screen>
443+
<![CDATA[
444+
Making a bowl of raspberry natural yogurt.
445+
]]>
446+
</screen>
447+
</example>
448+
</para>
449+
<para>
450+
PHP 8.0.0 以降では、
451+
デフォルト値を指定した引数の後に、
452+
必須の引数を宣言することは <emphasis>推奨されません</emphasis>。
453+
なぜなら、そのデフォルト値は絶対に使われないからです。
454+
これは、デフォルト値を削除することで解決できます。
455+
このルールの唯一の例外は、
456+
<code>Type $param = null</code> と書かれた引数です。
457+
&null; をデフォルトにすることは、
458+
型が暗黙のうちに nullable であることを示しています。
459+
この書き方はまだ許可されていますが、
460+
以下のようにして 明示的に
461+
<link linkend="language.types.declarations.nullable">nullable 型</link>
462+
を使うことを推奨します:
463+
<example>
464+
<title>デフォルト値を指定した引数は、必須の引数の後に宣言する</title>
465+
<programlisting role="php">
466+
<![CDATA[
467+
<?php
468+
function foo($a = [], $b) {} // デフォルト値が使われないため、PHP 8.0.0 以降は推奨されません
469+
function foo($a, $b) {} // 上のコードと機能的には同じですが、推奨されない警告は発生しません。
470+
471+
function bar(A $a = null, $b) {} // まだ許可されています。$a は必須ですが、nullable です。
472+
function bar(?A $a, $b) {} // 推奨される書き方です。
473+
?>
474+
]]>
475+
</programlisting>
476+
</example>
477+
</para>
478+
<note>
479+
<simpara>
480+
PHP 7.1.0 以降では、
481+
デフォルト値を指定しないで引数を省略すると、
482+
<classname>ArgumentCountError</classname>
483+
がスローされるようになりました。
484+
これより前のバージョンでは、警告が発生していました。
485+
</simpara>
486+
</note>
412487
<note>
413488
<simpara>
414489
リファレンス渡しの引数にもデフォルト値を指定できます。
@@ -604,7 +679,7 @@ echo sum(1, 2, 3, 4);
604679
<example>
605680
<title>名前付き引数の文法</title>
606681
<programlisting role="php">
607-
<![CDATA[
682+
<![CDATA[
608683
<?php
609684
myFunction(paramName: $value);
610685
array_foobar(array: $value);
@@ -619,7 +694,7 @@ function_name($variableStoringParamName: $value);
619694
<example>
620695
<title>位置を指定した引数と、名前付き引数</title>
621696
<programlisting role="php">
622-
<![CDATA[
697+
<![CDATA[
623698
<?php
624699
// 位置を指定した引数の場合:
625700
array_fill(0, 100, 50);
@@ -638,7 +713,7 @@ array_fill(start_index: 0, count: 100, value: 50);
638713
<example>
639714
<title>上と同じ例を、引数の順番を変えて渡す</title>
640715
<programlisting role="php">
641-
<![CDATA[
716+
<![CDATA[
642717
<?php
643718
array_fill(value: 50, count: 100, start_index: 0);
644719
?>
@@ -656,7 +731,7 @@ array_fill(value: 50, count: 100, start_index: 0);
656731
<example>
657732
<title>位置を指定した引数と、名前付き引数を組み合わせる</title>
658733
<programlisting role="php">
659-
<![CDATA[
734+
<![CDATA[
660735
<?php
661736
htmlspecialchars($string, double_encode: false);
662737
// 上記は、以下と同等です。
@@ -671,9 +746,9 @@ htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', fa
671746
</para>
672747

673748
<example>
674-
<title>同じ引数を複数回渡すと、Error 例外が発生する</title>
749+
<title>同じ引数を複数回渡すと、Error がスローされる</title>
675750
<programlisting role="php">
676-
<![CDATA[
751+
<![CDATA[
677752
<?php
678753
function foo($param) { ... }
679754

0 commit comments

Comments
 (0)