【PHP】関数

この記事は[一人PHP総復習 Advent Calendar 2016](http://qiita.com/advent-calendar/2016/php_beginner)5日目の記事です！

型について書こうと思っていたのですが、既に丁寧に解説している方がいらっしゃいました！
-> [PHPの型と型安全について(PHP7からのPHPプログラミング)](http://qiita.com/bokotomo/items/1ead446ef689dc45b487)

型ってどんなときに意識するの〜ってことで、関数について書きます！
[ユーザ定義関数まとめ](http://qiita.com/tokutoku393/private/7b3a2500f4d4c6c2463a#%E3%83%A6%E3%83%BC%E3%82%B6%E5%AE%9A%E7%BE%A9%E9%96%A2%E6%95%B0%E3%81%BE%E3%81%A8%E3%82%81)の項がさっと読める方は読まなくて大丈夫です！笑

## 関数とは
変数は値を入れておく箱でしたが、関数は幾つかの処理をまとめて入れておくものです。
最初から用意されている「組み込み関数」と、自分で定義する「ユーザ定義関数」があります。

## 関数の読み方・書き方
### 組み込み関数
例えば`isset()`という関数の場合。[PHPマニュアル](http://php.net/manual/ja/function.isset.php)

```php
$result = isset($name);
```

`$name`がセットされているかどうかを調べて、boolean型の`true`か`false`を返す関数です。

関数に渡す値（ここでは`$name`）を「引数」、返ってくる値を「返り値（または戻り値）」と言います。
上記のような書き方をすることで、返り値が`$result`に格納されます。

ここで返り値がboolean型だとわかっているので、次の処理で

```php
// もしtrueだったら
if ($result) {
	・・・
}
```

という処理を続けることが出来るわけですね。

組み込み関数は`isset()`や`substr()`、`explode()`などなど、覚えきれないほどあります。
覚えるのではなく、使う前にPHPマニュアルなどで引数と返り値（後述）の型をチェックします。

### ユーザー定義関数
自分で作る関数も「引数」、「返り値」の考え方は同様です。幾つかの処理をして、結果を返します。

#### 基本の書き方
```php
<?php

// greetingという名前をつけた関数
function greeting($name) {
	$message = 'Hello, '. $name. '!'; // 処理

	return $message; // 結果を返す
}

$message = greeting('Tom');
echo $message; // 'Hello, Tom!'
```

  
  
returnで結果を返すと、そこで処理は終了します。

```
<?php

function greeting($name) {
	$message = 'Hello, '. $name. '!';
	return $message;
	
	$message .= 'Nice to meet you.'; // この部分は実行されない
}

$message = greeting('Tom'); 
echo $message; // 'Hello, Tom!'
```


ちなみに初心者の頃理解しがたかったのですが、関数内の`$message`と返り値を格納している`$message`は別物です。
関数内での変数はローカルスコープ（関数内でのみ参照できる）です。

```php
<?php

function greeting($name) {
	$message = 'Hello, '. $name. '!';
	
	return $message;
}

$greeting = greeting('Tom');

echo $greeting; // 'Hello, Tom!'
echo $message; // 宣言されていないのでエラーになる
```

よく分からない方は、[変数](http://qiita.com/tokutoku393/items/72d2f3f8986c97c36a27)のスコープの部分を参照してみてください！

#### 引数を複数渡す
引数をいくつか渡す場合は左から順に第一引数、第二引数・・と呼びます。関数を呼ぶときも左から順番に渡すので注意しましょう

```php
<?php

function greeting($time, $name) {
	$message = 'Good '. $time. ', ' $name;
	
	return $message;
}

$message = greeting('morning', 'Tom');

echo $message; // 'Good morning, Tom';
```
ここでは`$time`が第一引数、`$name`が第二引数です。

#### 配列を返す関数
配列を使って複数の値を返すこともできます。その際、返り値は`list()`か配列で受け取ります。

```php
<?php

function children() {
    return ['Tom', 'Bob', 'Emily'];
}

$children = children();
list($elder, $younger, $sister) = children();

echo $children[0]; // 'Tom'
echo $elder; // 'Tom'
```

#### 返り値のない関数
また返り値がない場合もあります。

```php
<?php

function greeting($name) {
	$message = 'hello, '. $name. '!';
	
	echo $message;
}

greeting('Tom'); // 'hello, Tom!'と表示される
```

関数内で`$message`をechoしているので、返り値を受け取らなくても出力されます。

#### 型をコメントに明記する
ユーザー定義関数も、返ってくる値が何かわからないと困るので、型をコメントに明記するのがよいです。(PHPDocと言います)

```php
<?php

/**
 * @param string $name
 * @return string
 */
function greeting($name) {
	$message = 'Hello, '. $name. '!';
	
	return $message;
}

$message = greeting('Tom');
echo $message; // 'Hello, Tom!'
```
`@param`は引数、`@return`は返り値を示します。[PHPマニュアル](http://php.net/manual/ja/language.pseudo-types.php)
※コメントについては後日まとめたいと思います！


#### 型宣言
さらに、引数の型宣言（タイプヒンティング）ができます。（※PHPの古いバージョンではできない/挙動が違うので注意）

```php
<?php

function greeting(string $name) :string {
	$message = 'Hello, '. $name. '!';
	
	return $message;
}
```
この場合、`$name`にstring以外の型が渡ってくるとエラーになります。

#### 引数にデフォルト値をセットする
引数にデフォルト値をセットしておくことができます。引数が渡ってこなくてもエラーにならない処理を作る時などに有用です。

```php
<?php

function greeting($name = 'guest user') {
	$message = 'Hello, '. $name. '!';
	
	return $message;
}

echo greeting('Tom'); // 'Hello, Tom!'
echo greeting(); // 'Hello, guest user!'
```




予期せぬエラーを防止するために、型を意識することが重要です！

#### ユーザ定義関数まとめ

```php
<?php

/**
 * @param string $name
 * @param array $date
 * @return string
 */
function greeting(string $name = 'guest user', array $date) :string {
	$message = 'Hello, '. $name. '!';
	$message .= 'It's '. $date[0]. ' '. $date[1];
	
	return $message;
}

$user = 'Tom';
$today = ['December', '5th'];

echo greeting($user, $today); // 'Hello, Tom!It's December 5th'
```

ここまで理解できると気持ちいいですね！

## ユーザー定義関数の書き方いろいろ
### 関数宣言
ここまで紹介してきた呼び出して使う関数の書き方です。

```php
<?php

function FUNCTION_NAME() {
	// 処理
	
	return VALUE;
}

FUNCTION_NAME();
```

*関数名は大文字と小文字を区別しません。*

### 無名関数
PHP5.3からは無名関数が使えるようになりました。文字通り名前をつけない関数です。

```php
<?php

$greeting = function($name) {
	$message = 'hello, '. $name. '!';
	
	return $message;
}

echo $greeting('Tom');
```

また無名関数に変数を引き継ぐこともできます。

```php
<?php

$time = 'morning';

$greeting = function($name) use ($time) {
	$message = 'Good '. $time. ', '. $name;
	
	return $message;
}

echo $greeting('Tom'); // 'Good morning, Tom'
```

一度しか使わないことがわかっている関数などは、無名関数で書いてあげるとコードの冗長化が防げると思います！
実際にはDBのトランザクション処理などでよく使います。

プログラミングを始めたばかりの頃、型を理解していなくて何となく書いてよく分からないエラーが起きる、ということが多かったので、しっかり理解しておくとよいです！
最近は型宣言が出来るので気持ちよいですね( 厂˙ω˙ )厂