PHP: 関数

PHP: 関数

September 24, 2020
PHP
PHP

基本形 #

<?php
function my_func($arg_1, $arg_2, /* ... */ $arg_n)
{
  echo "hello! my func";
  return $retval;
}

引数の参照渡し #

仮引数に & を付与すると参照渡しになる。

<?php
function increment_one(&$n)
{
  $n += 1;
}

$a = 1;
increment_one($a);
echo $a; //=> 2

引数のデフォルト値 #

<?php
function greet($word = 'hello')
{
  echo $word . "\n";
}

greet("hi"); //=> hi
greet();     //=> hello

仮引数への型宣言 #

仮引数にデータ型を宣言できる。宣言した型と一致しない場合は型変換が発生し、それができない場合は TypeError 例外がスローされる。

<?php
function double(int $val)
{
  return $val * 2;
}

echo double(1), "\n";
echo double("2"), "\n";
echo double([]), "\n";
2
4

Fatal error: Uncaught TypeError: Argument 1 passed to double() must be of the type int, array given, called in /usr/src/myapp/a.php on line 9 and defined in /usr/src/myapp/a.php:2
Stack trace:
#0 /usr/src/myapp/a.php(9): double(Array)
#1 {main}
  thrown in /usr/src/myapp/a.php on line 2

declare(strict_types=1); を宣言することでファイル単位で型の厳密化ができる。

<?php
declare(strict_types=1);

function double(int $val)
{
  return $val * 2;
}

echo double("2"); //=> TypeError

NULL を許容する型宣言 #

デフォルト値に NULL を指定すると NULL を許容する引数となる。

<?php
function nullable_greet(string $name = null)
{
  echo "hello $name\n";
}

function greet(string $name)
{
  echo "hello $name\n";
}

nullable_greet(null); //=> hello
greet(null);          //=> TypeError

可変長引数 #

仮引数の前に ... で可変長引数となる。

<?php
function sum(...$vals)
{
  $acc = 0;
  foreach ($vals as $val) {
    $acc += $val;
  }
  return $acc;
}

echo sum(1, 2, 3, 4); //=> 10

実引数の展開 #

実引数に ... を付与することで展開(配列の各要素を引数に指定したのと同義)できる。

<?php
function sum($a, $b)
{
  return $a + $b;
}

$ary = [1, 2];
echo sum(...$ary); //=> 3

可変長引数に型宣言 #

<?php
declare(strict_types=1);

function sum(int ...$vals)
{
  $acc = 0;
  foreach ($vals as $val) {
    $acc += $val;
  }
  return $acc;
}

echo sum(1, "2", 3, 4); //=> TypeError

参照を返す関数 #

関数名の前に & を付与で参照を返す関数となり、戻り値を =& で代入すれば参照として扱える。

<?php
function &ret_ref()
{
  static $val = 1;
  return $val;
}

$a =& ret_ref();
$b =& ret_ref();
$b = 2;
echo $a . "\n"; //=> 2
echo $b . "\n"; //=> 2

戻り値の型宣言 #

仮引数の括弧の後に : type で戻り値の型を宣言できる。

<?php
function add($a, $b): int {
  return $a + $b;
}

echo add(1, 2) . "\n"; //=> 3

NULL を許容する戻り値の型宣言 #

: ?type と宣言する。

<?php
function nullable_greet($name = null): ?string {
  if ($name == NULL) {
    return null;
  } else {
    return "hello $name";
  }
}

function greet($name = null): string {
  if ($name == NULL) {
    return null;
  } else {
    return "hello $name";
  }
}

echo nullable_greet("john") . "\n"; //=> hello john
echo nullable_greet() . "\n";       //=> NULL
echo greet("john") . "\n";          //=> hello john
echo greet() . "\n";                //=> TypeError

無名関数 #

コールバック引数へ直接指定したり、変数に格納するなどで使える。

<?php
$ary = array_map(function($val) {
  return $val * 2;
}, [1,2,3,4,5]);

var_dump($ary); //=> [2,4,6,8,10]
<?php
$add = function($a, $b) { return $a + $b; };

echo $add(1,2); //=> 3

無名関数の外のスコープにある変数を使う (use) #

function() use ($a, $b, ..., $z) { ... } という形で、 use の後に外のスコープの変数を列挙すると利用できる。

<?php
$a = 1;
$b = 2;

$no_use_func = function($c) { return $a + $b + $c; };
$use_func = function($c) use ($a, $b) { return $a + $b + $c; };

echo $no_use_func(3); //=> 3
echo $use_func(3);    //=> 6

アロー関数 #

無名関数のより短い記法。

fn($a, $b, ..., $z) => expr

<?php
$ary = array_map(fn($val) => $val * 2, [1,2,3,4,5]);

var_dump($ary); //=> [2,4,6,8,10]

無名関数との違いは、

  • 文が書けず式だけ、その式の評価した値が戻り値となる
  • use キーワード使わなくても外のスコープの変数が利用可能
<?php
$a = 1;

$ary = array_map(fn($v) => $v + $a, [1,2,3,4,5]);

var_dump($ary); //=> [2,3,4,5,6]

上記以外、型宣言、可変長引数、参照渡し、参照戻しなど無名関数と同様に記述可能(参照戻しは fn&($x) => $x のように記述する)