[PHP]多次元配列の次元の深さ(階層)を調べる

多次元配列の内、最も深い階層の次元数をカウントする関数を作ってみました。
「123」などの配列でないものは 0 を返し、「array(1,2,3)」等の場合は 1 を返します。
「$arr[0][0][0][0][0] = 123」だと 5 になります。
「array(1, array(2), 3)」のように混在している場合は最も深いものを返すので 2 になります。

function array_depth($arr, $blank=false, $depth=0){
	if( !is_array($arr)){
		return $depth;
	} else {
		$depth++;
		$tmp = ($blank) ? array($depth) : array(0);
		foreach($arr as $value){
			$tmp[] = array_depth($value, $blank, $depth);
		}
		return max($tmp);
	}
}

「array( array() )」など、配列の内容が空の場合、デフォルトでは 0 になりますが、
$blank を true にすることで 2 としてカウントすることもできます。

[PHP]PDO bindParamで同じ変数名を使うと内容も同じになる

プレースホルダに bindParam() を使って値をセットする時、
同じ変数名を使うと参照渡しが行われてしまい、最後にセットした値が
全てのプレースホルダにセットされてしまいます。

<?php
$host = 'localhost';
$name = 'test';
$user = 'user';
$pass = 'password';

try {
	$dsn = "mysql:host={$host};dbname={$name};charset=utf-8";
	$db = new PDO($dsn, $user, $pass);
} catch (PDOExceprion $e){
	echo $e->getMessage();
}

$sql = "SELECT * FROM sample WHERE (name = ? OR name = ?)";

$stmt = $db->prepare($sql);

$value = "foo";
$stmt->bindParam(1, $value);

$value = "bar";
$stmt->bindParam(2, $value);

$stmt->execute();

上の例では、
「SELECT * FROM sample WHERE (name = ? OR name = ?)」
という SQL 文の疑問符部分に対してそれぞれ「foo」と「bar」をバインドしています。

「name = ‘foo’ OR name = ‘bar’」となるつもりが、実際の結果は
「name = ‘bar’ OR name = ‘bar’」となってしまいました。

どちらも value と言う変数名を使っているため、後から代入した値によって
他の値が上書きされています。
$value1, $value2 のように名前を分ければこれは発生しません。
あるいは一度使った $value を unset() しておけば同じ名前であっても大丈夫です。

$value = "foo";
$stmt->bindParam(1, $value);

unset($value);

$value = "bar";
$stmt->bindParam(2, $value);

execute() を行うまでは $value に代入した時点で上書きが行われるので、
bindParam() を使ったかどうかは実際には関係ありません。
次のようにすると全てのパラメータは「hello」に上書きされます。

$value = "foo";
$stmt->bindParam(1, $value);

$value = "bar";
$stmt->bindParam(2, $value);

$value = "hello";

【結果】

SELECT * FROM sample WHERE (name = 'hello' OR name = 'hello')

ループ内で使う場合は、参照渡し「&$value」を使って bindParam() を行います。
後から問題を起こさないように使った変数は unset() で片付けておきます。

$i=1;foreach($arr as &$value){
  $stmt->bindParam($i, $value);
  $i++;
}
unset($value);

参照渡しをしない bindValue() を使えばこの問題が発生しないので、bindParam にこだわりがなければ
for や foreach などのループ内では bindValue() を使ったほうが無駄な混乱が起こりにくくなると思います。

[PHP]最小公倍数・最大公約数を求める(ユークリッドの互除法)

最小公倍数・最大公約数を求めるにはユークリッドの互除法に基づくアルゴリズムを利用します。
なぜこの式で計算できるのかについては数学に詳しい人に聞いて下さい。

//最大公約数
function gcd($m, $n){
	if($n > $m) list($m, $n) = array($n, $m);
	
	while($n !== 0){
		$tmp_n = $n;
		$n = $m % $n;
		$m = $tmp_n;
	}
	return $m;
}

//最小公倍数
function lcm($m, $n){
	return $m * $n / gcd($m, $n);
}

参考