PHPの基礎 - 関数
概要
関数とは、いくつかの処理をまとめて名前を付けて定義したものである。
関数には、組み込み関数とユーザー定義関数の2種類がある。
使い方は同じであるが、組み込み関数はPHPで予め用意された関数であり、ユーザ定義関数は自身が定義した関数である。
ここでは、ユーザ定義関数について記載する。
関数の使用方法
関数の具体的な使用方法を記載する前に、関数を使用する場面について記載する。
以下の例では、数値を判定して出力する部分を関数にして、必要な時に呼び出している。
繰り返し使用する処理を関数にして、必要な時に呼び出す。
function check($kamoku, $Num)
{
print $kamoku.'の結果:';
if($Num >= 80)
{
print '80以上';
}
else
{
print '80未満';
}
}
$Math = 84;
$Eng = 62;
$Jp = 78;
check('数学', $Math);
check('英語', $En);
check('国語', $Jp);
関数の定義と実行
関数の定義
まず、関数の定義を記載する。
基本的な書式は、以下の通りである。
function 関数名(引数1, 引数2, ...) { 実行される処理; }
関数名として使用できる文字は、先頭がアンダーバーかアルファベットで始まり、その後にアンダーバー、数字、アルファベットが続く。
変数名とは異なり、大文字・小文字の区別は無いので注意すること。
引数は、関数に値を渡す場合に使用するものであり、パラメータとも呼ばれる。
関数の実行
関数を実行する時の書式は、以下の通りである。
関数名(); または 関数名(引数1, 引数2, ...);
また、関数を実行すると戻り値として計算結果を返す場合がある。
その場合、以下のように記述することにより、関数からの戻り値を変数に代入することができる。
変数名 = 関数名(引数1, 引数2, ...);
※注意
PHPにおいて、以下のように、関数の定義は関数の実行よりも後で定義してもよい。
hello();
function hello()
{
print 'hello';
}
引数
関数を呼び出す時に関数に渡す値を引数と呼ぶ。
引数を使用することにより、関数を実行するたびに一部の値を変化させて実行することができる。
以下の例では、最初に関数を実行する時、引数として"田中"を渡している。
関数側では、変数nameに"田中"という値が格納されて、関数内の処理が実行される。
次に、変数nameに"鈴木"という値が格納されて、関数内の処理が実行される。
function greeting($name)
{
print 'こんにちは。'.$name.'さん。';
print 'お元気ですか?';
}
greeting('田中');
greeting('鈴木');
複数の引数
引数は、必要な数だけ指定することができる。
複数の引数を指定する場合は、カンマ(,)で区切り記述する。
書式は以下の通りである。
呼び出し元で指定した順に、引数に値を格納する。値1は引数1、値2は引数2に格納されて関数内の処理が実行される。
function 関数名(引数1, 引数2, ...) { // ... } 関数名(値1, 値2, ...);
以下の例では、2つの値の平均値を出力している。
function heikin($num1, $num2)
{
$result = ($num1 + $num2) / 2;
print '平均は'.$result.'です';
}
heikin(10, 8);
heikin(3, 23);
戻り値
関数では、return
文を使用して、数値、文字列、配列等の演算結果を呼び出し元に返すことができる。
戻り値を返す場合、関数名(引数1, 引数2, ...)
の評価が戻り値となる。
戻り値は、変数 = 関数名(引数1, 引数2, ...)
のように変数に対して格納する。
以下の例では、変数に戻り値を格納する場合と関数の実行を直接記述している。
function plus($num1, $num2)
{
$sum = $num1 + $num2;
return $sum;
}
$sum = plus(10, 8);
print '加算の結果は'.$sum.'です';
print '加算の結果は'.plus(7, 14).'です';
なお、引数とは異なり、戻り値として指定できる値は1つのみである。
ただし、戻り値として配列も指定できるため、配列を返すことで実質的に複数の値を返すことも可能である。
可変長引数
可変長引数を持つ関数を定義することができる。
可変長引数は配列として関数内で扱われる。
通常の引数と組み合わせる場合、可変長引数は必ず最後に定義する必要がある。
これには、主に2つの方法がある。
...
(スプラット演算子 / 可変引数演算子) を使用する方法 (PHP 5.6以降)- ...演算子を使用する方法が推奨される。
func_get_args
関数を使用する方法 (従来の方法)
また、型宣言も使用可能である。
// 型宣言の例
function sum(int ...$numbers)
- ...演算子を使用する場合
function sum(...$numbers)
{
$total = 0;
foreach ($numbers as $number) {
$total += $number;
}
return $total;
}
// 使用例
echo sum(1, 2, 3, 4, 5); // 出力: 15
echo sum(10, 20); // 出力: 30
- func_get_args関数を使用する場合
function multiply()
{
$numbers = func_get_args();
$result = 1;
foreach ($numbers as $number) {
$result *= $number;
}
return $result;
}
// 使用例
echo multiply(2, 3, 4); // 出力: 24
echo multiply(5, 10); // 出力: 50
また、通常の引数と可変長引数を組み合わせることもできる。
function greet($greeting, ...$names)
{
foreach ($names as $name) {
echo "$greeting, $name!\n";
}
}
// 使用例
greet("Hello", "Alice", "Bob", "Charlie");
// 出力
Hello, Alice!
Hello, Bob!
Hello, Charlie!
グローバル変数の使用
PHPのスコープルールにおいて、グローバルスコープで定義された変数は、関数の内部からは自動的にはアクセスできない。
これはPHPの変数スコープの分離という特徴によるものである。
関数内でグローバル変数を使用する場合は、以下に示すいずれかの方法を使用する必要がある。
- globalキーワードを使用する方法
$hoge = 1;
function func1()
{
global $hoge; // グローバル変数を関数内で使用することを宣言
echo "$hoge";
}
- $GLOBALS配列を使用する方法
$hoge = 1;
function func1()
{
echo "$GLOBALS['hoge']";
}
※注意
グローバル変数の使用は避け、代わりに引数として値を渡すことが推奨される。
これにより、関数の依存関係が明確になり、テストや保守が容易になる。
ソースコードの予測可能性と再利用性も向上する。
参照渡し
参照渡しとは、変数のメモリアドレスを直接渡すことにより、関数内で値を変更すると呼び出し元の変数の値も変更される仕組みである。
関数の引数の前に&を付加することにより参照渡しになる。
- 特に大きな配列やオブジェクトを扱う場合、メモリ使用量を節約できる場合がある。
- 複数の値を同時に変更する場合に便利である。
// 参照渡し
function addFiveByRef(&$num)
{
$num += 5;
}
$value = 10;
addFiveByRef($value);
echo $value; // 15 (元の値が変更される)
// 配列の要素を全て2倍にする関数
function doubleArrayValues(&$arr)
{
foreach ($arr as &$value) {
$value *= 2;
}
}
$numbers = [1, 2, 3, 4, 5];
doubleArrayValues($numbers);
print_r($numbers); // [2, 4, 6, 8, 10]
参照渡しは、以下に示すような場合に使用することを推奨する。
- 大きなデータ構造を扱う時のパフォーマンス最適化
- 複数の値を同時に変更する必要がある時
- オブジェクトのメソッドチェーンを実装する時
別のPHPファイルの関数を呼び出す (関数のライブラリ化)
関数をユーティリティ化 / ライブラリ化して、外部のPHPファイルに記述する方法として、require
、require_once
、include
、include_once
関数がある。
外部のPHPファイルの関数を呼び出す前に、上記の関数を使用して外部ファイルを読み込むことにより、外部のPHPファイルの関数を呼び出すことができる。
// index.phpファイル
<?php
require_once 'utils.php'; //関数呼び出しより手前に記述する
echo('sum: '.utl_sum(12,5).'<br/>');
echo('mul: '.utl_mul(12,5).'<br/>');
echo('div: '.utl_div(12,5).'<br/>');
echo('sub: '.utl_sub(12,5).'<br/>');
?>
// utils.phpファイル
<?php
function utl_sum($a,$b)
{
return $a + $b;
}
function utl_sub($a,$b)
{
return $a - $b;
}
function utl_mul($a,$b)
{
return $a * $b;
}
function utl_div($a,$b)
{
return $a / $b;
}
?>
コールバック関数
コールバック関数の定義を以下に示す。
- 関数の引数としてcallable型を指定。
- 文字列で関数名を渡す。
- 既存の関数を参照として渡す。
コールバック関数のメリットを以下に示す。
- コードの再利用性が高まる。
- 柔軟な処理の実装が可能
- コードの可読性が向上する。
使用場面を以下に示す。
- 配列操作
- array_map関数、array_filter関数、array_reduce関数
- イベントハンドラ
- コールバックベースのAPI
- データの変換や加工
function processNumbers(array $numbers, callable $callback)
{
$result = [];
foreach ($numbers as $number) {
$result[] = $callback($number);
}
return $result;
}
// コールバック関数の定義
function double($n)
{
return $n * 2;
}
// コールバック関数の使用例
$numbers = [1, 2, 3, 4, 5];
$doubled = processNumbers($numbers, 'double');
print_r($doubled); // [2, 4, 6, 8, 10]
ラムダ式 (無名関数)
ラムダ式 (無名関数) の特徴を以下に示す。
- function() {}構文を使用する。
- 変数に代入可能である。
- その場で定義して使用できる。
use
キーワードで外部のスコープの変数を取り込める。
// コールバック関数
function processNumbers(array $numbers, callable $callback)
{
$result = [];
foreach ($numbers as $number) {
$result[] = $callback($number);
}
return $result;
}
// ラムダ式 (無名関数) の例
$triple = function($n) {
return $n * 3;
};
// 一般的なラムダ式の使用
$tripled = processNumbers($numbers, $triple);
print_r($tripled); // 出力 : [3, 6, 9, 12, 15]
// インラインでのラムダ式の使用
$squared = processNumbers($numbers, function($n) {
return $n * $n;
});
print_r($squared); // [1, 4, 9, 16, 25]
以下の例では、useキーワードを使用したクロージャを定義している。
// コールバック関数
function processNumbers(array $numbers, callable $callback)
{
$result = [];
foreach ($numbers as $number) {
$result[] = $callback($number);
}
return $result;
}
$multiplier = 4;
$multiplied = processNumbers($numbers, function($n) use ($multiplier) {
return $n * $multiplier;
});
print_r($multiplied); // 出力 : [4, 8, 12, 16, 20]
以下の例では、array_map関数の引数としてラムダ式を使用している。
ラムダ式の部分をコールバック関数として使用することもできる。
// 配列操作の実践的な例
$users = [
['name' => 'Tanaka', 'age' => 25],
['name' => 'Suzuki', 'age' => 30],
['name' => 'Sato', 'age' => 20]
];
// array_map関数でラムダ式を使用
$names = array_map(function($user) {
return $user['name'];
}, $users);
print_r($names); // 出力 : ['Tanaka', 'Suzuki', 'Sato']
// array_filter関数でコールバックを使用
$adults = array_filter($users, function($user) {
return $user['age'] >= 25;
});
print_r($adults); // 25歳以上のみ出力