たとえば、「Aという商品を1,000点入荷する」という処理を行うとき、メモリなどの関係で一気にレコードを処理することができないので、100点ずつに分割して処理したいとします。
そのため、1,000という数値を100が10個含まれた配列に変換したかったのですが、意外とそういうニーズってないのか、ベストプラクティスを見つけられませんでした。。。これよりいい方法があればぜひ教えてほしいです。。。
分割処理
ProcedureUtil.php
class ProcedureUtil
{
/**
* @param int $quantity 分割したい数値
* @param int $divisor 除数
*
* @return array 分割された配列
*/
public static function divideQuantity($quantity, $divisor)
{
$quantity = (int)$quantity;
$divisor = (int)$divisor;
if ($quantity < 0) {
// 0未満の数値は扱わない
throw new \InvalidArgumentException(
sprintf(
'Argument 1 passed to divideQuantity() must be number and greater than 0, %s is given',
$divisor
)
);
} elseif (0 === $quantity) {
// 0の場合は、そのまま配列に格納して返却
return array(0);
}
if ($divisor <= 0) {
// 除数に0以下の数値は扱わない
throw new \InvalidArgumentException(
sprintf(
'Argument 2 passed to divideQuantity() must be number and greater than 1, %s is given',
$divisor
)
);
}
$quotient = ceil($quantity / $divisor);
$ret = array();
for ($index = 1; $index <= $quotient; $index++) {
if ($quantity - $divisor > 0) {
$ret[] = $divisor;
$quantity -= $divisor;
} else {
$ret[] = $quantity;
}
}
return $ret;
}
単体テスト
ProcedureUtilTest.php
class ProcedureUtilTest extends \PHPUnit_Framework_TestCase
{
public function testDivideQuantity()
{
$result = ProcedureUtil::divideQuantity(1, 1);
$expected = array(1);
$this->assertEquals($expected, $result);
$result = ProcedureUtil::divideQuantity(0, 1);
$expected = array(0);
$this->assertEquals($expected, $result);
$result = ProcedureUtil::divideQuantity(1, 10);
$expected = array(1);
$this->assertEquals($expected, $result);
$result = ProcedureUtil::divideQuantity(0, 10);
$expected = array(0);
$this->assertEquals($expected, $result);
$result = ProcedureUtil::divideQuantity(10, 10);
$expected = array(10);
$this->assertEquals($expected, $result);
$result = ProcedureUtil::divideQuantity(11, 10);
$expected = array(10, 1);
$this->assertEquals($expected, $result);
$result = ProcedureUtil::divideQuantity(20, 10);
$expected = array(10, 10);
$this->assertEquals($expected, $result);
$result = ProcedureUtil::divideQuantity(21, 10);
$expected = array(10, 10, 1);
$this->assertEquals($expected, $result);
}
/**
* @expectedException \InvalidArgumentException
*/
public function testDivideQuantityWithException()
{
ProcedureUtil::divideQuantity(1, 0);
ProcedureUtil::divideQuantity(1, -1);
}
使用例
HogeLogic.php
class HogeLogic
{
public function process()
{
foreach (ProcedureUtil::divideQuantity(1000, 100) as $divided) {
$this->doSomething(divided);
}
}