mb_ereg()の第三引数に未定義変数を入れて失敗した場合の動作 オマケ:preg_matchの場合

# <i class="fa fa-cubes"></i> 概要

[mb_ereg]は第三引数に`array`を入れた場合は、
一致した部分文字列が格納されます。
ここに`array`以外を入れてみました。

きっかけは

* 未定義の変数が指定されていたコードが元気に動いているのを見つけた(IDEが警告してくる)
* [mb_ereg]の第三引数が参照渡しになっていない
* [mb_ereg]に失敗時の第三引数の結果が書いていない


# <i class="fa fa-check-circle-o"></i> 結論

[mb_ereg]の第三引数は配列以外でも動作し、失敗時は引き渡したままの値が残る。
ただし、未定義変数を渡した場合は`NULL`に設定される。

これが[mb_ereg]のリファレンスに`&`がついていない理由かは不明。
(`&`がついている[preg_match]とは失敗時の動作が異なる)

未定義の変数を渡すこと自体は、褒められた書き方ではないと思われるが、
`null`に上書きされるため、危険は無いと思われる。
現状存在するコードが意図的に行っているとは言えないのがリスクだが…


# <i class="fa fa-smile-o text-success"></i> [mb_ereg] 成功パターン

すべて`array`の正常な結果に上書きされる。

## <i class="fa fa-code text-success"></i> コード

```php:succsess_mb_ereg.php

// 成功系
$pattern = 'test';
$string  = 'test';

test($pattern, $string, array());                 // array(1) {[0]=> string(4) "test"}
test($pattern, $string, array('hoge' => 'huga')); // array(1) {[0]=> string(4) "test"}
test($pattern, $string, null);                    // array(1) {[0]=> string(4) "test"}
test($pattern, $string, 'string');               // array(1) {[0]=> string(4) "test"}
test($pattern, $string, 100);                    // array(1) {[0]=> string(4) "test"}
test($pattern, $string, true);                   // array(1) {[0]=> string(4) "test"}
test($pattern, $string, false);                  // array(1) {[0]=> string(4) "test"}
test($pattern, $string, new stdClass());         // array(1) {[0]=> string(4) "test"}
test($pattern, $string, $regs);                  // array(1) {[0]=> string(4) "test"}

function test($pattern, $string, $regs) {
    mb_ereg($pattern, $string, $regs);
    var_dump($regs);
    echo "\n\n";
}


```

# <i class="fa fa-frown-o text-danger"></i> [mb_ereg] 失敗パターン

引数の値が保持される。
ただし、未定義の変数の場合はNULLが定義される。

## <i class="fa fa-code text-danger"></i> コード

```php:failure_mb_ereg.php

// 失敗系
$pattern = 'test';
$string  = 'bad';

test($pattern, $string, array());                 // array(0) {}
test($pattern, $string, array('hoge' => 'huga')); // array(1) {["hoge"] => string(4) "huga"}
test($pattern, $string, null);                   // NULL
test($pattern, $string, 'string');               // string(6) "string"
test($pattern, $string, 100);                    // int(100)
test($pattern, $string, true);                   // bool(true)
test($pattern, $string, false);                  // bool(false)
test($pattern, $string, new stdClass());         // object(stdClass)#1 (0) {}
test($pattern, $string, $regs);                  // NULL
var_dump($undefined);                            // NULL ただし PHP Notice:  Undefined variable: undefined

function test($pattern, $string, $regs) {
    mb_ereg($pattern, $string, $regs);
    var_dump($regs);
    echo "\n\n";
}


```

## 失敗パターンのつかいどころ？

引数の値が保存されるので、デフォルト値として使える？
成功時は一致結果配列、失敗時はその他の値を返したいとき、
[mb_ereg]の実行結果は不要になる。

```php:普通に使う.php

$regs = array()
if (mb_ereg($pattern, $string, $regs)) {
    return $regs;
} else {
    return '失敗しました';
}

```

```php:横着.php

$regs = '失敗しました';
mb_ereg($pattern, $string, $regs)
return $regs

```

失敗時にNULLを返すなら初期化も不要

```php:NULLを返す.php

mb_ereg($pattern, $string, $regs)
return $regs

```

また、

```php

null[0]         // null
(string)null[0] // string(0) ""

```

で、エラーも出ないので、

```php:一致文字列の追加.php

mb_ereg($pattern, $string, $regs)
return 'test' . $regs[0]; // もし$patternがあれば追加

```

とかもできる。


***

ついでに似たような関数[preg_match]ではどうなるか調べました。

# <i class="fa fa-smile-o text-success"></i> [preg_match] 成功パターン

同じく`array`の結果に上書きされる。

## <i class="fa fa-code text-success"></i> コード


```php:succsess_preg_match.php


// 成功系
$pattern = 'test';
$string  = 'test';

test($pattern, $string, array());                 // array(1) {[0]=> string(4) "test"}
test($pattern, $string, array('hoge' => 'huga')); // array(1) {[0]=> string(4) "test"}
test($pattern, $string, null);                    // array(1) {[0]=> string(4) "test"}
test($pattern, $string, 'string');               // array(1) {[0]=> string(4) "test"}
test($pattern, $string, 100);                    // array(1) {[0]=> string(4) "test"}
test($pattern, $string, true);                   // array(1) {[0]=> string(4) "test"}
test($pattern, $string, false);                  // array(1) {[0]=> string(4) "test"}
test($pattern, $string, new stdClass());         // array(1) {[0]=> string(4) "test"}
test($pattern, $string, $regs);                  // array(1) {[0]=> string(4) "test"}

function test($pattern, $string, $regs) {
    preg_match($pattern, $string, $regs);
    var_dump($regs);
    echo "\n\n";
}


```

# <i class="fa fa-frown-o text-danger"></i> [preg_match] 失敗パターン

すべて空配列で上書きされる。

## <i class="fa fa-code text-danger"></i> コード

```php:failure_preg_match.php

// 失敗系
$pattern = '/test/';
$string  = 'bad';

test($pattern, $string, array());                 // array(0) {}
test($pattern, $string, array('hoge' => 'huga')); // array(0) {}
test($pattern, $string, null);                   // array(0) {}
test($pattern, $string, 'string');               // array(0) {}
test($pattern, $string, 100);                    // array(0) {}
test($pattern, $string, true);                   // array(0) {}
test($pattern, $string, false);                  // array(0) {}
test($pattern, $string, new stdClass());         // array(0) {}
test($pattern, $string, $regs);                  // array(0) {}


function test($pattern, $string, $regs) {
    preg_match($pattern, $string, $regs);
    var_dump($regs);
    echo "\n\n";
}

```

直感では[preg_match]のほうが普通かなぁ。


[mb_ereg]:http://php.net/manual/ja/function.mb-ereg.php
[preg_match]:http://php.net/manual/ja/function.preg-match.php