前回
- 副作用をもつ関数
- 関数表記方法・変数との表記方法の違い
- スコープ
- スタティック
- 上記2つの複合応用問題
※今まで受けてきた中で関数だと、複合応用問題、関数と変数表記方法が主に出題されてると思う
関数後編
入れ子
- 関数の中に別の関数を定義すること
- 入れ子にした関数を呼び出すには先にそれを含む関数を呼び出す
下記の出力はどうなるか。
//(1)
function x(){
function y(){
echo 'ご機嫌';
}
}
x();
y();
//(2)
function x(){
function y(){
echo 'ご機嫌';
}
}
y();
//(3)
function x(){
function y(){
echo 'ご機嫌';
}
}
x();
(1)ご機嫌が出力
(2)エラー終了
(3)エラーはないが、ご機嫌も出力されない
→つまり、x()だけでもy()だけでもだめで、まず先にx()を呼び出し、つぎにy()を呼び出さないといけない
値渡しと参照渡し
- 値渡しはコピー、参照渡しはそっくりそのまま渡すイメージ
- デフォルトはもちろん値渡し
- マクロで言う、byVal,byRef
- 値渡しはデフォルトそのまま、参照渡しはパラメータの前に&(アンパサンド)をつける
いつものどおり下記の出力を答えてください
//(1)値渡し
function test($arr) {
$arr++;
}
$x = 20;
test($x);
echo $x;
//(2)参照渡し
function test2(&$arr) {
$arr++;
}
$x = 20;
test2($x);
echo $x;
上記では、仮引数のほうで(1)のほうは$arrで、値渡し、(2)は&$arrと、参照渡し。
値渡しはコピーを渡しただけなので、外側にある$xは20のまま。
参照渡しはまるごと渡すので、関数内で1こふえてるので21に。
結果、「2021」となる。(改行してないので)
パラメータのデフォルト値
- パラメータのデフォルト値を決めておいて省略されたときにそれを渡せる
- マクロで言うOptional
いつものどおり下記の出力を答えてください
//(1)
function test($x=1,$y=200,$z=300) {
echo '$x='.$x.'<br>';
echo '$y='.$y.'<br>';
echo '$z='.$z.'<br>';
}
test(1,2,3);
test(1,2);
test(1);
//(2)
function test($x=1,$y=200,$z=300) {
echo '$x='.$x.'<br>';
echo '$y='.$y.'<br>';
echo '$z='.$z.'<br>';
}
test(,2);
test(3,,2);
(1) ここはまあ簡単でしょう
$x=1
$y=2
$z=3
$x=1
$y=2
$z=300
$x=1
$y=200
$z=300
(2)
エラー終了。
このように、頭部分を省略するという書き方はできない。
デフォルト値を持つパラメータに対する引数の指定を省略した場合は、それ以降の引数の指定もすべて省略しないといけない。
つまり、(2)のように、1番目を省略したら続く引数も省略しないといけないってこと。
パラメータと引数の関係
- 関数のパラメータの数 > 引数 → 指定されなかったパラメータは未設定のまま処理続行(警告あり)
- 関数のパラメータの数 < 引数 → あまった引数は無視(警告はなし)
いつものどおり下記の出力を答えてください
//(1)
function test($x,$y) {
echo '$x='.$x.'<br>';
echo '$y='.$y.'<br>';
echo '$z='.$z.'<br>';
}
test(1,2,3);
test(1);
test();
エラー終了しなかったが、ログを見ると警告が2つ発生
そして、出力はtest(1,2,3)のみだった。それが下記。
$x=1
$y=2
$z=
可変パラメータ
- 関数が不特定の数のパラメータを必要とするときに利用
- 「func_num_args()」「func_get_arg()」「func_get_args()」の3つを使う
- func_num_args()は関数にはいってる引数の数を取得
- func_get_arg($arg_num)は指定した番号の引数の値を取得。引数は○番目かを指定。Forと一緒に
- func_get_args()は引数リストを配列化。foreachと一緒に使うことが多いハズ
上記の関数を使って下記コードを書いた
function test()
{
$args_num = func_num_args();
echo "引数の数: $args_num<br>";
$args_2num = func_get_arg(1); //2番めの引数を指定
echo "2番めの引数:$args_2num<br>";
$args = func_get_args();
foreach ($args as $s){
echo $s.",<br>";
}
}
test(1, 2);
echo "<br>";
test(1,2,3,4,5);
echo "<br>";
こちらの出力は
引数の数: 2
1番めの引数:2
1,
2,
引数の数: 5
1番めの引数:2
1,
2,
3,
4,
5,
となる
その他
return
- 英語のとおり、返り値を渡せる
- 返り値が不要でも、このreturn;だけで、その関数を終了させることができる
- 関数末尾の場合returnがなくてもOK
- 複数の値を帰す場合はarray()で。カンマ区切りのはない
- デフォルトで関数からの値はコピー。
- 参照渡しにしたいなら、先程の通り、関数名の前に&(アンパサンド)をつける。
- 関数呼び出し側でも関数名の前に&(アンパサンド)をつける。
function &test(&$x){
return $x;
}
$x = 1;
$result = &test($x);
$x = 2;
echo $result;
$resultに&test()という関数が格納されているので、
最後の行ではtest()が参照渡しの状態で実行される
したがってこの出力は2になる
可変関数
- 関数の名前を変数に代入したもの
- 指定した関数名に対応する関数がないとエラーになる
- 関数があるかどうかを調べるのはfunction_exists(function_name)でいける
- また言語構造であるecho()やisset()はこれで呼び出せない
※言語構造とは言語を構成する要素のこと。トークンと言い換えてもいいかも。
例としてifとかforとかある。
紛らわしい例として、echo/isset以外に、print/unset/dieなど。動詞っぽいから紛らわしい。
覚えるしかないが、よく使うのは上のようなものぐらいだと思う。一応下で確認しておこう。
これらは関数ではないので、カッコでくくってもくくらなくてもよい、とされている。
参考→キーワードリスト
ここにあるのは全部言語構造だそう。
//(1)
function test()
{
$test_name = 'print';
$test_name('ご機嫌');
}
//(2)
$test_name = 'print';
if (function_exists($test_name){
$test_name('ご機嫌');
} else {
$test_name,'は未定義です';
}
//(3)
$test_name = 'echo';
$test_name('ご機嫌');
(1)が基本。もちろんご機嫌が出力。
(2)も同じくご機嫌が出力。関数があるか確かめてから実行してる点に注目。
(3)エラー。echoやissetはだめ。
### 匿名関数
- 他の関数と重複しないランダムな名前が割り振られる
- create_fucntion()で作成
- パラメータリストで指定されたパラメータと、コードで作成
- create_fucntion(string $args,string $code);
- array_filter()などの関数の引数として使用
$Myfunc = create_function('$x'.'echo $x;);
$Myfunc('hello');
$Myfunc2 = create_function('x', 'return $x >= 80);
$a = array(78,79,80.81,82);
$b = array_filter($a,$Myfunc2);
printf($b);
出力は
Hello,2=>80, 3=>81, 4=82となる
# 今後
上級Ⅱ3章関数前編
- 副作用をもつ関数
- 関数表記方法・変数との表記方法の違い
- スコープ
- スタティック
- 上記2つの複合応用問題
上級ⅡⅣ関数後編は下記の通り
- 入れ子
- ご機嫌
- 値渡しと参照渡し
- パラメータのデフォルト値
- パラメータと引数の関係
- 可変パラメータ
- return
- 可変関数
- 匿名関数
長かったけど、これで3章終わり。
引っかかりやすいなーというところは、
可変パラメータ、可変関数だと思います。
頑張って覚えましょう!