シェア
//PHPジェネレーター

PHPジェネレーター

こんな状況に直面したことはありませんか?
これは、実行中のプロセスが許可されたRAMメモリ制限を超えてメモリを消費する場合に、PHP開発者が遭遇する可能性のあるエラーです。

具体的な例を見てみましょう:

private function range() {
    $a = [];
 
    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        $a[] = $i;
    }
 
    return $a;
}
 
foreach ($this->range() as $value) {
    echo $value;
}

上記のコードは、0からPHP_INT_MAX(現在のPHPバージョンが提供する最大の整数値)までの配列を作成し、その値を画面に出力します。コードを実行すると、先に述べたエラーが発生します。

このエラーに対処する方法はどうすれば良いのでしょうか?一つの方法は、“memory_limit”の設定をphp.iniファイルで増加させることです。

; スクリプトが消費する最大メモリ量
; https://php.net/memory-limit
 memory_limit = 128M

しかし、これは最適な解決策ではありません。小さなコードでメモリ制限オーバーエラーが発生しているのは問題があります。そこで、メモリ制限を増加させる代わりに、PHPジェネレーターを使用して、どのようにメモリ使用量を削減できるか試してみましょう。

PHPジェネレーターとは?

PHPジェネレーターは、PHP 5.5で導入された強力な機能です。この機能により、ジェネレーター関数を作成することができ、ジェネレーター関数はすべての値を一度に返すのではなく、必要に応じて1つずつ値を生成して返します。これによりメモリを大幅に節約でき、データセット全体をメモリに保持せずにデータを処理することができます。

PHPジェネレーターの使用方法

上記のコードで、“range()”関数を変更して、配列(文字列)を作成してすべての値を返すのではなく、yieldキーワードを使って値を順番に返すようにします。簡単に言うと、yieldは値を返しますが、すべての値をメモリに保存することなく、その時点で呼び出すときにのみ値を返します。このようにすると、関数はジェネレーター関数になります。

private function range() {
    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        yield $i;
    }
}
 
foreach ($this->range() as $value) {
    echo $value;
}

PHPジェネレーターのメソッド

public current(): mixed
public getReturn(): mixed
public key(): mixed
public next(): void
public rewind(): void
public send(mixed $value): mixed
public throw(Throwable $exception): mixed
public valid(): bool
public __wakeup(): void

動作の例

別の例を試してみましょう:

function myGeneratorFunction()
{
      echo 'One' . "<br>";
      yield 'first return value' . "<br>";
 
      echo 'Two' . "<br>";
      yield 'second return value' . "<br>";
 
      echo 'my return value' ;
}
 
$iterator = myGeneratorFunction();
 
$firstValue = $iterator->current();
echo $firstValue;
 
$iterator->next();
$secondValue = $iterator->current();
echo $secondValue;
 
$iterator->next();
echo $iterator->getReturn();

Output

One
first return value
Two
second return value
my return value

呼び出すと、$iterator->current()関数が実行され、“One”という値が表示され、最初のyieldキーワードで停止します。最初のyieldの値が返され、$firstValueに格納されます。

次に、$iterator->next();を呼び出すと、ジェネレーター関数は、最初のyieldで停止した位置から実行を再開します。この時、“Two”が表示され、2番目のyieldキーワードの値が返され、$secondValueに格納されます。次に、$iterator->next();を再度呼び出し、$iterator->getReturn();を使用して返された値を取得します。

この例から、yieldキーワードは関数を一時停止するように働き、yieldを呼び出すたびに関数は停止し、$iterator->next()を呼び出すことで続行されます。

キーの返却

yieldを使用してkey⇒valueを返す

private function range()
{
    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        yield "key {$i}" => "value {$i}";
    }
}
 
foreach ($this->rangeKeyValue() as $key => $value) {
  echo "{$key} -> {$value} <br>";
}

Output

key 0 -> value 0
key 1 -> value 1
key 2 -> value 2
key 3 -> value 3
key 4 -> value 4
key 5 -> value 5
…

ジェネレーターへの引数の渡し方

引数をジェネレーターに渡して、関数を停止するようにすることもできます。方法は以下の通りです:

private function range()
{
    for ($i = 0; $i < PHP_INT_MAX; $i++) {
         $value = yield $i;
 
         if ($value === 'stop') {
            return;
         }
    }
}
 
$generator = $this->range();
 
foreach ($generator as $value) {
    if ($value === 5) {
        $generator->send('stop');
    }
 
    echo "current value is {$value} <br>";
}

Output

current value is 0
current value is 1
current value is 2
current value is 3
current value is 4
current value is 5

PHPジェネレーターの利点

アプリケーションが数ギガバイトのログファイルをデータベースに保存する必要がある場合、そのすべてを一度に読み込んで処理することはメモリオーバーフローを引き起こします。PHPジェネレーターを使用して、ログファイルの各行を逐次的に読み込んで処理することで、メモリの使用量を最小限に抑え、システムリソースを無駄に消費することなく、効率的に処理できます。

結論

大量のデータを処理する必要があるシステムでは、安全で最適な方法を選択することが非常に重要です。PHPジェネレーターは、メモリを節約し、サーバーの安定性とパフォーマンスを向上させる強力な解決策を提供します。システムの過負荷によるエラーを回避し、ユーザー体験の中断を防ぐためにも、PHPジェネレーターの使用を検討することが望ましいです。

Huỳnh Hữu Phát
Web Developer

今すぐ応募







    福利厚生

    給料・ボーナス制度

    社員の感情・願望を理解しているので、リバークレーンベトナムは特に年2回の定期昇給制度を設けています。毎年6月と12月に評価を行い、毎年1月と7月に給与が変更されます。また、社員は月次と年次の優秀な個人には定期的な業績賞与が別で支給されます。

    日本研修制度

    世界中の新しい技術分野に触れるために、社員を日本にオンサイトさせる方針があります。さらに、技術分野か管理分野かのキャリアパスは社員の決定次第です。

    毎年社員旅行

    リバークレイン・ベトナムは、スタッフに挑戦の機会を提供するだけでなく、年に一度の魅力的な旅行で彼らを楽しませています。エキサイティングなガラディナーやチームビルディングゲームは、リバークレインのメンバー同士の絆をさらに深める手助けをします。

    リバークレイン イベント

    チームビルディング・ファミリーデー・お夏休み・中秋節などのイベントはチーム内のメンバーが接続出来るしお互いに自分のことを共有出来る機会です。ご家族員に連携する際にはそれも誇りに言われています。

    社会保険制度

    リバークレーンベトナムは従業員に社会保険、医療保険、失業手当などの社会保険制度があります。当社は、これらの保険に関するあらゆる手続きをスタッフに必ずサポートしています。さらに、他の保険契約も考慮され、検討されています。

    他福利

    社員向けの活動をサポートすることもあります。 ・文化・芸術・スポーツクラブの運営費用 ・技術研究の教科書を購入する金額 ・エンジニア試験・言語能力試験を受験料 ・ソフトスキルのセミナー・コースの参加費 ・等 また会社政策通り、他のベネフィットもあります。

    © 2012 RiverCrane Vietnam. All rights reserved.

    Close