PHPの文脈でいうストリームは、ファイル、ネットワーク、データ圧縮などでデータ総量が確定していないものを少しづつ処理して操作を行うこと。

fgetやfread、stream_get_contensなどはストリーム関数で、file_get_contentsなどはストリーム関数ではない。
file_get_contentsは大きいファイルの場合は、PHPのメモリが足りなくなってエラーが発生する可能性がある(ただしfile_get_contents関数は内部的にはストリーム処理を行っているため、第3引数に後述するストリームコンテキストを渡すことができる)。

ストリームを使う場合、下記の3つの概念を抑えておく必要がある。

ストリームフィルター

ストリームで入出力するデータに対して、フィルターを適用することで特定の操作を行うことができる。

以下、フィルターの挙動を示す良い例があったので、引用させていただく。

fgetcsvは内部で次の処理をしている。

1. ファイルから文字列をN文字読み込む
2. 読み込んだ文字をパースして、CSVの行の配列にする

ストリームフィルターはこの1と2の間に割って入ることができる。
したがって、次のような処理ができる。

1. ファイルから文字列をN文字読み込む
2. その文字列をUTF-8に変換する (ストリームフィルタ)
3. 読み込んだ文字をパースして、CSVの行の配列にする

https://qiita.com/suin/items/3edfb9cb15e26bffba11

ストリームコンテキスト

ストリームの挙動を変更したり拡張できるオプション機能。

ストリームラッパー

どのように特定のプロトコル・エンコーディングを扱うかを指示する付加的なコードのこと。
ストリームラッパーは「php://〜」といったURL風のプロトコルである。
ファイルなどのリソースに実際にアクセスする方法は、ファイルが保管されている場所とファイルを保管する方法によって決まり、ローカルにあるファイルにアクセスする方法と、リモート・サーバー上にあるファイルに HTTP や FTP によってアクセスする方法は、まったく異なる。
ストリームラッパーを使用することで、その場所と保管方法にあった呼び出し方法を見つけ出してくれる。

参考:https://qiita.com/desho/items/14361eb8594faf661210

よく使われるのは、「php://memory」「php:temp」で両者の違いは下記となる。

php://memory および php://temp は読み書き可能なストリームで、一時データをファイルのように保存できるラッパーです。
両者の唯一の違いは、php://memory が常にデータをメモリに格納するのに対して php://temp は定義済みの上限 (デフォルトは 2 MB) に達するとテンポラリファイルを使うという点です。

https://www.php.net/manual/ja/wrappers.php.php

さらには、ジェネレーターを使うことで、さらにメモリを節約できそう。

// yieldの使い方の引用
// https://qiita.com/zaburo/items/437a4ff14c13018a4812
<?php

    function readRows($filename)
    {
        //対象ファイルオープン
        $fp = fopen($filename,'r');

        //最初の1行を読む
        $row = fgets($fp);

        //最後のlineまでループ
        while($row !== false)
        {   
            //値を戻す
            yield $row;
            //次の行を読む
            $row = fgets($fp);
        }

        //ファイルクローズ
        fclose($fp);
    }

    //
    $rows = readRows('input.txt');

    foreach($rows as $row)
    {
        echo $row."<br>";
    }

ちなみにMySQLで大きなデータを取得する際には、
PHP5.4まではmysql_unbuffered_query()を使用してクエリを発行し、結果は逐次的にmysql_free_result()を使用して、必要な部分を少しずつ読み込んでは結果セットを削除するといったやりかたがいい。
新しいPHPでは、MySQLi あるいは PDO_MySQL を使うべきである。

mysql_unbuffered_query() は SQL クエリ query を MySQL に送信します。その際、 mysql_query() が行っているような自動バッファリングを 行いません。一方、この挙動により SQL クエリが消費するメモリの量を おさえられます。また、最初の 1 行目が取得されたらすぐに処理を はじめることができます。SQL の処理が完全に終わるまで待つ必要がありません。 複数の DB 接続を利用する場合には、オプションのパラメータ link_identifier を指定する必要があります。

〜中略〜

注意
mysql_unbuffered_query() の利点には、以下のような 代償があります: mysql_unbuffered_query() から返される結果セットには、 すべての行をフェッチするまでは mysql_num_rows() や mysql_data_seek() を使用できません。また、結果の行をすべてフェッチするまで、 同じ link_identifier を使って MySQL に新しいクエリを送信することができません。

https://www.php.net/manual/ja/function.mysql-unbuffered-query.php

この内容には、バッファクエリと非バッファクエリの知識が必要である。

クエリは、デフォルトではバッファモードで実行されます。 つまり、クエリの結果がすぐに MySQL サーバーから PHP に転送され、 PHP プロセスのメモリ内に結果を保持し続けるということです。 これで、その後で行数を数えたり結果ポインタを移動 (シーク) したりといった操作ができるようになります。 また、同じ接続上でさらに別のクエリを発行しつつ、 現在の結果セットを使った作業をすることもできます。 バッファモードの弱点は、結果セットが大きくなると大量にメモリを消費するということです。 結果セットへの参照がなくなるか、結果セットを明示的に解放する (リクエストを終了すると、自動的に解放されます) まではメモリ上に残り続けます。 バッファモードは「結果を格納する」クエリとも呼ばれます。 ここでは、結果セット全体が一度に格納されます。

注意:
ライブラリとして libmysqlclient を使っている場合は、結果セットのデータを PHP の変数に代入するまで結果セットのメモリ利用量が PHP のメモリ制限にカウントされません。 mysqlnd の場合は、結果セットのメモリがすべて PHP のメモリ制限にもカウントされます。

非バッファクエリは、クエリを実行してリソースを返しますが、 その時点ではまだデータが MySQL サーバー上にあって取得待ちになっています。 PHP 側でのメモリ消費が少なくなりますが、サーバーへの負荷は高くなります。 サーバー上の結果セットからすべての結果を取得するまで、 同じ接続上で別のクエリを実行することはできません。 非バッファクエリは「結果を使う」クエリとも呼ばれます。

こういった特性を考慮すると、バッファクエリを使うのは、 結果セットの量が限られている場合や事前に結果の行数を知りたい場合だけにとどめるべきでしょう。 結果が大量に返ってくることが想定できる場合は、非バッファモードを使わないといけません。

https://www.php.net/manual/ja/mysqlinfo.concepts.buffering.php

長く引用させていただいたが、バッファクエリはすべてのパケットが受信完了するまで待たなければならないため、BLOBカラムなどで大きなデータを取り扱う場合で最初の数行のみ必要なときでもすべての行を受信しなければいけなくなる。

だから、そのようなときには非バッファクエリを使うか、LIMIT句で取得行数を指定するのが望ましい。