「PHP/入門/関数とは」の版間の差分

削除された内容 追加された内容
→‎型指定の新機能: PHPの新旧によって、異なる型の加減乗除では型の扱いが異なるので、事前にテストして確認しておきましょう。
Ef3 (トーク | 投稿記録)
→‎無名関数: 関数の中で関数を定義してもクロージャーにはなりませんが、無名関数でクロージャーを実現できます。 PHPには、無名関数を定義する方法に、アロー関数と関数式の2つがあります。
タグ: 2017年版ソースエディター
8 行
 
 
;ユーザー定義関数の例:<syntaxhighlight lang=php>
<syntaxhighlight lang="PHP">
<?php
f();
33 ⟶ 32行目:
関数をユーザーが定義するには、function 宣言を使い、波カッコ { } の中に処理をかく。
 
:書式:<syntaxhighlight lang=php>
つまり
<syntaxhighlight lang="PHP">
function 関数名(引数) {
// させたい処理をカッコ内に書く
}
</syntaxhighlight>
という書式である。(※ 余談だが、JavaScript でも関数の定義には function 宣言が必要になる。)
 
 
PHPで関数を実行させたい場合には、phpタグ内で関数の名前(上記コードでは「f」が名前)を書くだけで、{ }カッコ内の処理を行ってくれる。
60 ⟶ 56行目:
例えば、下記のコードは、単純に関数fが1を返す関数である。
 
:<syntaxhighlight lang="PHP"php>
<?php
$a = f();
 
printecho $a;
 
function f(){
83 ⟶ 79行目:
 
;参考
:<syntaxhighlight lang="PHP"php>
<?php
$num = pi();
102 ⟶ 98行目:
関数には引数(ひきすう)を持たせることもできる。引数とは、関数の呼び出し時に値を渡して処理させるために、渡す値のこと。引数は複数個でも単数個でも0個でも構わない。PHPに限らず一般にプログラミング言語は関数に引数を持たせることができる。
 
;例:<syntaxhighlight lang=php>
例:
<syntaxhighlight lang="PHP">
<?php
 
print add(20, 99);
 
function add($i, $j) : {
return $i + $j;
}
 
?>
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
 
119
出力結果
119
 
引数は、括弧のなかへ記述する。
 
==== 型指定の新機能 ====
2021年現在、最近のPHP7以降では、関数の引数で型を指定することができます。
 
現在のところ、単に変数を宣言する場合には、型宣言は不可能です。
 
型宣言をするには、下記のように関数の引数の中での宣言など、一部の機能でのみ、型宣言が可能です。
 
<syntaxhighlight lang="PHP">
<?php
 
print add(10020, 99);
 
function add(int $i, int $j){
return $i + $j;
}
 
?>
</syntaxhighlight>
:引数は、括弧のなかへ記述します。
 
==== 型宣言 ====
結果
型宣言は、関数の引数や返り値、そして PHP 7.4.0 以降ではクラスのプロパティに追加することができます。これらは、呼び出し時に指定した型の値であることを保証し、 そうでない場合は TypeError がスローされます。
10199
strict_types を 1 にセットすると、型宣言漏れをエラーにできます。
 
:<syntaxhighlight lang=php line highlight=6>
 
<code>int</code>とは、整数型を意味する予約語です。PHPにかぎらずC言語でも整数型の予約語は <code>int</code> です。
 
 
古いバージョンのPHPでは、上記コードのadd のカッコ()の中を整数ではなく小数などにすると、上記の型指定したコードでは、その引数はむりやり整数に変換される仕様でした。
 
 
<syntaxhighlight lang="PHP">
<?php
declare(strict_types=1);
 
$y = 7;
print add(5000.1234, 99);
$fn1 = fn(int $x) : int => $x + $y;
 
$fn2 = function add(int $i,x) use ($jy) : int {
return $ix + $jy;
};
echo '$fn1(3) --> ', $fn1(3), PHP_EOL;
 
echo '$fn2(3) --> ', $fn2(3), PHP_EOL;
$y = 1;
echo '$fn1(3) --> ', $fn1(3), PHP_EOL;
echo '$fn2(3) --> ', $fn2(3), PHP_EOL;
?>
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
10119
</syntaxhighlight>
 
==== 有効な型 ====
結果
プリミティブ型のほか、クラスやインターフェースの名前は、型名として認識されます。
:※ 古いバージョンのPHPの場合
:{| class="wikitable"
5099
|+ PHPの関数の引数や戻値の型
 
!型
※ PHP8.1およびPHP8.2αでテストしたところ、
!説明
5099.1234
!バージョン
になった。
|-
 
| classまたはinterfacd の名前
このように、PHPの新旧によって、異なる型の加減乗除では型の扱いが異なるので、事前にテストして確認しておきましょう。
| 値は与えられたクラスまたはインターフェースのインスタンスでなければならない。
 
|
 
|-
入門的な型としては、
|self
:整数型の '''int''' 、
| 値は型宣言が使用されているクラスと同じクラスのインスタンスでなければならない。クラス内でのみ使用可能。
:浮動小数点型の '''float''' 、
|
:文字列型の '''string''' 、
|-
などがあります。
|parent
|型宣言が使われているクラスの親のインスタンスでなければならない。クラス内でのみ使用可能。
|
|-
|array
|値は配列でなければならない。
|
|-
|callable
|値は有効な callable である必要があります。クラスのプロパティの型宣言としては使用できません。
|
|-
|bool
|値はブール値でなければならない。
|
|-
|float
|値は浮動小数点数でなければならない。
|
|-
|int
|値は整数値でなければならない。
|
|-
|string
|値は文字列でなければならない。
|
|-
|iterable
|値は、配列か Traversable のインスタンスでなければなりません。
|PHP 7.1.0
|-
|object
|値はオブジェクトでなければなりません。
|PHP 7.2.0
|-
|mixed
|値は任意の値であることができます。
|PHP 8.0.0
|}
 
=== 変数のスコープ ===
190 ⟶ 206行目:
このような、変数の使える範囲のことを、スコープ(Scope) と呼ぶ。
 
:<syntaxhighlight lang="PHP"php>
<?php
$i = 10;
220 ⟶ 236行目:
 
;コード例
:<syntaxhighlight lang="PHP"php>
<?php
$i = 10;
249 ⟶ 265行目:
 
;その他
:<syntaxhighlight lang="PHP"php>
<?php
$s = 99;
265 ⟶ 281行目:
sの二乗は9801です。
 
{{コラム|関数内で関数を定義しても関数スコープにはならない|2=
 
関数の中で別の関数を定義することは可能ですが意味はありません。
== 発展的な話題 ==
;例:<syntaxhighlight lang=php>
=== 関数内の関数 ===
PHPでは、ユーザ定義関数の中に別のユーザ定義関数の定義を書き、またその別関数を呼び出して利用する事もできます。
 
一般に、このような機能をプログラミング用語で「内部関数」と言いますが、PHPでは別の意味で「内部関数」という用語がすでに使われているので、本wikiページでは「関数内関数」と呼ぶことにします。
 
この機能は、あまり市販の書籍に書かれてはいないですが、普通にwebブラウザでも動きます。
 
 
;例
<syntaxhighlight lang="PHP">
<?php
declare(strict_types=1);
function soto()
{
function uti()
{
print "abc<br>";
}
 
function outer() {
uti();
uti()$y = 10;
function inner() {
}
global $y;
 
echo __FUNCTION__, "\$y = $y", PHP_EOL;
soto();
?>
</syntaxhighlight>
:※(動作確認: 2020年6月24日に Fedora32上の Firefox で動作を確認ずみ。)
 
;実行結果
<pre>
abc
abc
</pre>
 
 
 
なお、PHPでは、関数内関数は定義さえすれば、どこからでも自由に関数内関数を呼び出せます。比喩的に言うなら、関数内関数は「グローバル関数」です。
 
 
下記コードのように書いても、動作して、
<syntaxhighlight lang="PHP">
<?php
function soto()
{
function uti()
{
print "abc<br>";
}
inner();
 
utiinner();
uti();
}
 
sotoouter();
utiinner();
?>
</syntaxhighlight>
 
$y = 0;
実行結果は
<pre>
abc
abc
abc
</pre>
 
となります。
 
=== アロー関数 ===
===== 数値計算 =====
PHP7.4以降、アロー関数という機能が追加されており、下記のような1個の命令の内容の関数を定義できます。
 
書式は
:<code>$値を格納する変数 = fn($引数) => 関数の内容の式</code>
です。
 
<code>fn</code>は予約語ですので、変更できません(変更してもエラーになるので実行不可能です)。
 
また、<code> => </code>は(不等号ではなく、)アロー演算子という演算子ですので、混同しないように。
 
<syntaxhighlight lang="PHP">
<?php
// 定義方法
$atai = fn($hiki) => $hiki * 7;
 
// outer(); PHP Fatal error: Cannot redeclare inner() (previously declared in /workspace/Main.php:7) in /workspace/Main.php on line 6
// 出力
inner();
print($atai(2)); // 14 なぜなら 2×7=14 なので
print("\n"); // 改行
print($atai(5)); // 35 なぜなら 5×7=35 なので
?>
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
inner$y =
inner$y =
inner$y =
inner$y = 0
</syntaxhighlight>
: 関数の中で別の関数を定義することは可能ですが意味はありません。
: 定義した関数の中で inner() を呼び出すことは複数回できます。
: 定義した関数を抜けたあとも、定義した関数を呼び出すことはできます。
: ですが、関数内で定義された関数から「外側の」ローカル変数は参照できません。
: global 宣言した変数は、「外側の」ローカル変数ではなくトップレベルの変数です。
: あまつさえ、関数を定義する関数を二回呼び出すと、<code>PHP Fatal error: Cannot redeclare</code> と致命的エラーです。
; これは、関数内で別の関数を定義しても関数スコープにはならず'''クロージャではない'''ことを表しています。
}}
 
=== 無名関数 ===
実行結果
関数の中で関数を定義してもクロージャーにはなりませんが、無名関数でクロージャーを実現できます。
<pre>
PHPには、無名関数を定義する方法に、アロー関数と関数式の2つがあります。
14
;[https://paiza.io/projects/B3_gFsPL2r0L3mL4XRuLtQ?language=php 例]:<syntaxhighlight lang=php line highlight=9>
35
</pre>
 
となります。
 
アロー関数の定義の命令自体は1個の命令だけで構成される必要がありますが、アロー関数自体は1回以上でも何度でも呼び出せて使えます。
 
===== 数値計算以外 =====
数値計算でなくても、関数の命令内容が1個なら、アロー関数が定義および利用できる場合もあります。
 
また、引数を用いない場合、下記コード例のように、アロー関数の宣言文から引数を省略できます。
 
コード例
<syntaxhighlight lang="PHP">
<?php
$y = 7;
 
$ataifn1 = fn($x) => print("test$x ")+ $y;
$fn2 = function ($x) use ($y) {
 
//return 使い方$x + $y;
};
$atai();
echo '$fn1(3) --> ', $ataifn1(3), PHP_EOL;
echo '$fn2(3) --> ', $fn2(3), PHP_EOL;
$y = 1;
echo '$fn1(3) --> ', $fn1(3), PHP_EOL;
echo '$fn2(3) --> ', $fn2(3), PHP_EOL;
?>
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
 
$fn1(3) --> 10
実行例
$fn2(3) --> 10
<pre>
$fn1(3) --> 10
test test
$fn2(3) --> 10
</pre>
</syntaxhighlight>
:<code>fn($x) => $x + $y;</code>の<code>=></code>が矢印っぽいのでアロー関数と呼ばれます。
::この記号は <code>{ 'a' => 1 }</code> (連想配列)でも使われます。
:<code>function ($x) use ($y) { return $x + $y;};</code>は、関数式です。
::関数定義とよく似ていますが名前がありません。
::use でキャプチャーする環境を指定します。
:;キャプチャー
::上の実行結果をよく見ると9行目 <code>$y = 1;</code>のあとも答えが変わっていません。
::このようにアロー関数や関数式(まとめて無名関数)は、定義されたときの環境をキャプチャーします。
::このようキャプチャーを行う性質から、無名関数は、しばしまクロージャーと呼ばれます。
::: 無名関数の中で __FUNCTION__ を参照すると、<code>{closure}</code> となります。
 
[[Category:PHP|にゆうもん かんすうとは]]