ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
return と yield の基本動作の違い
// return: 1 回呼んで終わり
function range_return(int $n): array {
$result = [];
for ($i = 0; $i < $n; $i++) {
$result[] = $i;
}
return $result; // ★ ここで終了、全要素を含む配列を返す
}
// yield: 1 回ごとに値を吐き出す
function range_yield(int $n) {
for ($i = 0; $i < $n; $i++) {
yield $i; // ★ 一時停止して値を返す、次回ここから再開
}
}
// 利用は同じ foreach で書ける
foreach (range_return(5) as $v) { echo $v; } // 01234
foreach (range_yield(5) as $v) { echo $v; } // 01234
メモリ効率の決定的な差
// 100 万件で比較
function arr_return(): array {
$a = [];
for ($i = 0; $i < 1_000_000; $i++) {
$a[] = "item_$i";
}
return $a;
}
function arr_yield() {
for ($i = 0; $i < 1_000_000; $i++) {
yield "item_$i";
}
}
// メモリ計測
echo memory_get_usage() . PHP_EOL; // ベース: 約 400 KB
$a = arr_return();
echo memory_get_usage() . PHP_EOL; // 約 60 MB ❌
unset($a);
foreach (arr_yield() as $v) {
// 1 件ずつ処理
}
echo memory_get_usage() . PHP_EOL; // 約 400 KB ✅
yield の構文バリエーション
function basics() {
yield 1; // 値のみ (キーは 0 から自動)
yield 2;
yield 3;
}
function withKey() {
yield 'name' => '太郎'; // ★ キー => 値
yield 'age' => 30;
}
function fromAnother() {
yield 1;
yield from [2, 3, 4]; // ★ 他の iterable を流し込む
yield from basics(); // ジェネレータ from ジェネレータ
yield 5;
}
// 受け取り方
foreach (withKey() as $k => $v) {
echo "$k = $v\n";
}
// name = 太郎
// age = 30
Generator クラスのメソッド
yield を含む関数は Generator オブジェクトを返します。foreach 以外にも直接メソッドを呼べます:
$gen = range_yield(5);
$gen->current(); // 現在の値
$gen->key(); // 現在のキー
$gen->next(); // 次へ進める
$gen->valid(); // まだ要素があるか
$gen->rewind(); // 巻き戻し (※ 一度進めた後は不可)
$gen->send($v); // ジェネレータに値を送る (双方向通信)
$gen->getReturn(); // ジェネレータ終了後の return 値を取得
// 手動でループ
while ($gen->valid()) {
echo $gen->current() . "\n";
$gen->next();
}
ジェネレータ内の return
ジェネレータ関数内でも return が使えます。値はジェネレータ終了後に getReturn() で取得可能:
function counter() {
$i = 0;
while ($i < 3) {
yield $i++;
}
return 'finished'; // ★ 終了時の戻り値
}
$gen = counter();
foreach ($gen as $v) {
echo "$v\n"; // 0, 1, 2
}
echo $gen->getReturn(); // finished
典型ユースケース1: 巨大ファイル処理
// ❌ 全部メモリに読む → OOM 確定
$lines = file('huge.csv');
foreach ($lines as $line) { ... }
// ✅ 行単位でストリーミング
function readLines(string $path) {
$fp = fopen($path, 'r');
while (($line = fgets($fp)) !== false) {
yield trim($line);
}
fclose($fp);
}
foreach (readLines('huge.csv') as $line) {
// 1 行ずつ処理 → メモリ一定
}
典型ユースケース2: 無限ストリーム
// 無限フィボナッチ
function fibonacci() {
[$a, $b] = [0, 1];
while (true) {
yield $a;
[$a, $b] = [$b, $a + $b];
}
}
$count = 0;
foreach (fibonacci() as $n) {
echo "$n ";
if (++$count >= 10) break;
}
// 0 1 1 2 3 5 8 13 21 34
Laravel での lazy / lazyCollection
Laravel 6+ では Eloquent / Collection にジェネレータベースの API が用意されています:
// ❌ get() は全件メモリ展開 → 大量データで OOM
foreach (User::all() as $user) { ... }
// ✅ lazy() は内部 yield で 1000 件ずつ取得
foreach (User::lazy() as $user) {
// メモリ一定で全件処理
}
// ID 順で安全に lazy 取得 (推奨)
foreach (User::lazyById() as $user) { ... }
// Collection の lazy
LazyCollection::make(function () {
$fp = fopen('big.csv', 'r');
while (($line = fgets($fp)) !== false) {
yield $line;
}
})->each(fn($l) => process($l));
return vs yield 使い分け
| 状況 | 推奨 |
|---|---|
| 結果が小さい (数件〜数百件) | return + 配列 |
| 結果が大きい / メモリ気になる | yield |
呼び出し側で count() や添字アクセスが必要 | return + 配列 |
| 呼び出し側は foreach で十分 | yield |
| 無限列 / 終わりのないストリーム | yield 一択 |
| JSON にエンコードして返す API | return (Generator は json_encode 不可) |
テスト方法
use PHPUnit\Framework\TestCase;
class GeneratorTest extends TestCase {
public function test_range_yield(): void {
$result = iterator_to_array(range_yield(3));
$this->assertSame([0, 1, 2], $result);
}
public function test_yields_3_items(): void {
$gen = range_yield(3);
$this->assertCount(3, iterator_to_array($gen));
}
}
FAQ
Q: ジェネレータは何度も foreach できる?
A: できません。1 度走り切ると終了。再度回すには関数を呼び直す必要があります ($gen = range_yield(5) を再実行)。
Q: ジェネレータを array にしたい
A: iterator_to_array($gen)。ただし全件メモリ展開されるので yield の利点が消えます。
Q: PHP のどのバージョンから使える?
A: PHP 5.5+ で yield、PHP 7.0+ で yield from、PHP 7.0+ でジェネレータの return 値サポート。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページ
子ページはありません
同階層のページ
- インストール方法
- 文法
- Composerのインストール
- 内部関数
- フレームワーク
- エラー一覧
- 改行出力
- printとechoの違い
- シングルクォートとダブルクォートの違い
- returnとyieldの違い
- var_dumpをログ出力
- CSV読み込み
- 待機・処理の遅延
- ログファイルにエラーを出力する方法
- エラーログ出力関数
- URLパラメータの配列化
- empty, is_null. issetの判定比較表
- httpステータスコードの付与
- バージョンの確認
- php.ini
- APIを呼び出す方法
- 外部ファイルを呼び出す方法
- カンマ区切りの文字列を配列に変換
- 配列からランダムに値を取り出す方法
- Webスクレイピング
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?