試してみてください:
$sql = "INSERT INTO persist (user_id, hash, expire)
VALUES (:user_id, :hash, :expire)
ON DUPLICATE KEY UPDATE hash=:hash2";
および
$stm->execute(
array(":user_id" => $user_id,
":hash" => $hash,
":expire" => $future,
":hash2" => $hash)
);
ドキュメントからの抜粋( http://php.net/manual/en/pdo prepare.php ):
PDOStatement ::execute()を呼び出すときに、ステートメントに渡す値ごとに一意のパラメーターマーカーを含める必要があります。プリペアドステートメントで同じ名前の名前付きパラメータマーカーを2回使用することはできません。たとえば、SQLステートメントのIN()句で、複数の値を単一の名前付きパラメーターにバインドすることはできません。