(PHP) ob_start()で、標準出力をバッファリングする

(PHP) ob_start()で、標準出力をバッファリングする

 

phpの、ob_start()から始まるob_なんちゃら系の関数を先日初めて実務で使用した。
結構とっかかりの理解が難しかったので、学んだことをメモ。

 

ob_start():標準出力のバッファリングを開始する

ob_start()関数は、標準出力のバッファリングを開始する関数だ。
マニュアルには「バッファリングをオンにする」見たいなニュアンスで書いてある。

まずは普通の標準出力

PHPの出力関数である echoを実行すると、echoを記述したタイミングで HTMLに標準出力する。

echo "Hellow World";

なので、HTMLのソースの中にPHPの「echo」の記述を書くと、その書いてあるところで処理され、標準出力の内容がそのまま HTMLに出力される。

<!DOCTYPE html>
<html lang="ja">
<head>
 :
</head>
<body>
 :
<div id="contents">
<?php echo "Hello World!!"; ?>        # HTMLにそのまま出力される
</div>
 :
</body>
</html>

要は、上記のように、
echoしたタイミングでphpソースに結果が反映されるのが標準出力の特徴と言って良いだろう。

 

ob_start()で標準出力をバッファリングすると

しかし、今回紹介する「ob_start()関数」は、この標準出力を即座に出力せずに、
「バッファリング」する機能を提供してくれる関数だ。

バッファリングとは、簡単に言うと、
標準出力の結果を即座に反映するのではなく、出力内容を保持しておく事ができる仕組みのことだ。

バッファリングした値は、「ob_get_contents()関数」を使って値を取得して変数に代入したり、「ob_end_flush()関数」を使って値を出力するといったことが可能だ(※この辺の使い分けは、後述する)。要は、任意のタイミングで出力内容を決定できると言う点が最大のメリットと言うことになる。

「ob_start()関数」を使ってバッファリングを開始を宣言したら、「ob_end_clean()関数」などを使って終了を宣言する必要がある。

 

ob_start()関数とは
  • 準出力を即座に出力せずに、「バッファリング」する機能を提供してくれる関数
  • 任意のタイミングで出力内容を決定できると言う点が最大のメリット
  • バッファリング開始したら、終了もしてあげる必要がある

 

ob_start()関数の使い方

次にob_start()関数の使い方を説明していく。
まずは以下のソースを見て欲しい。

echo "1";
ob_start();                    # バッファリング開始
echo "2";
$buffer = ob_get_contents();   # この時点でのバッファを変数に代入
echo "3";
$buffer2 = ob_get_contents();  # この時点でのバッファを変数に代入
echo "4";
ob_end_clean();                # バッファリング終了
echo "5";
echo $buffer;
echo $buffer2;

上記のプログラムを実行すると、結果は「15223」となる。

まずは「1」と「5」が通常のechoによって出力される。この時、間にある「ob_start();」~「ob_end_clean();」の間のechoに関しては、バッファリングされるため出力されない。

最後の「echo $buffer」と「echo $buffer2」のタイミングで、それぞれ「ob_get_contents()」したタイミングでのバッファリング内容が出力される(「2」と「23」)。

上記から分かるように、「任意のタイミングで出力内容を決定できると言う点」がob_start()関数の最大の特徴と言えることが理解できるだろう。

バッファの内容を取得する「ob_get_contents();」を使うことでバッファリングした内容を任意のタイミングで変数などに保存をすることが可能だ。また、変数に代入するため、その値を置換したりやさらに値に代入したりすることも可能になる。

 

ob_start()関数の使い方【incrude()編】

「出力内容をバッファリングできる」と言うことが理解できたところで、
実際にどのような場面で使用することでob_start()関数が役立つかを実例をもとに理解していく。

 

外部ファイルの読み込み:incrude()

例として、外部ファイルを読み込む処理について考えていく。

PHPの外部ファイル「sample.php」というファイルがあったとして、これを読み込む場合は、下記のように include()関数で読み込む(include_once()、require()などでも同様)。

# 外部ファイルを読み込み

include("sample.php")

だが、include()関数の場合は、先ほどの echoと同じく、読み込んだところで処理されてしまう
そこで登場するのが、「ob_start()関数」だ。

ob_start();                     # バッファリング開始
include("sample.php");          # sample.phpをバッファリング
$buffer = ob_get_contents();    # バッファリングの内容を取得
ob_end_clean();                 # バッファリング終了

上記のように、include()関数で読み込んだ情報もバッファリング可能となる。変数「$buffer」に入ったsample.phpの内容は、必要に応じて出力をすることが可能だ。

上記を応用することで、下記のように条件分岐させて include()した情報を必要に応じて出力させることが可能となる。

# 条件分岐した結果でob_startを使い分ける
ob_start();

if ( $flg = 1 ) {
include("sample.php");
} else {
include("sample2.php");
}

$buffer = ob_get_contents();
ob_end_clean();

また変数に代入しているため、複数個所に出力する場合にも利用することが可能だ。

 

ob_start()関数の使い方【callback関数編】

ob_start()関数は、callback関数を引数として与えることが可能だ。

「コールバック関数って何?」と言う方は、以下の記事にて詳しく説明しているので、参考にして欲しい。

 

ob_start()関数に、callback関数を指定してみる

下記の例は、ob_start()の引数に、str_replace()関数で文字列を置換するコールバック関数を指定している例だ。

<?php

# callback関数
function callback ( $buffer ) {
# baseball を tennis に置換する
return (str_replace("baseball", "tennis", $buffer));
}

ob_start("callback");      # 引数にコールバック関数を渡す(まだ実行はされない)
?>

<html>
<body>
<p>I love baseball .</p>
</body>
</html>

<?php
ob_end_flush();      # バッファリングに対し、コールバック関数を実行した結果を出力

上記を実行すると、下記のように「baseball」が「tennis」に置換されて出力される。

<html>
<body>
<p>I love tennis.</p>
</body>
</html>

 

上記を利用することで、例えば、テンプレートとして用意しておいたファイルの特定部分だけを、ログインユーザの情報に置換して出力すると言ったことが可能ではないだろうか(変更予定部分を「###」としてテンプレートを作成しておいて、出力の際に「###」をログインユーザの情報に置換する、と言った具合)。

 

バッファの記録の開始・取得・終了

ここからは筆者も何となくの理解しているレベルの話になるのだが、
最後にバッファの記録の開始・取得・終了について少しメモを取っておこうかと思う。

と言うのも、ob_何ちゃら系の関数って実はいっぱいあって、どれを使えば良いのか迷っちゃうことが多かったので、「コレっ!」て言うものをメモしておく意味でも紹介する。

バッファは階層的に使用可能

まず第一に理解しておきたいポイントとして、
バッファは階層的に使用できることを押さえておこう。

どう言うことかと言うと、ob_start()でバッファの記録を開始することは上述したが、これを複数回繰り返すと、繰り返した分、バッファの階層が増えていく。

ob_start()でバッファを階層的に使用する画像

そして、現在の階層でバッファの記録を行うため、この機能を利用してバッファの内容を上手くコントロールすると言うことが可能となる。

ちなみに、現在のバッファの階層がどの階層かを確認する関数として、ob_get_level()関数が存在する。

# 現在のバッファの階層を取得
ob_get_level();

 

バッファの記録の取得

バッファの内容の取得はob_get_contents()関数を使用するのがベター。
ob_get_contents()関数を呼んだ時点でのバッファの内容を取得する。

# 呼んだ時点でのバッファの内容を取得する
$buffer = ob_get_contents();

ベターと言ったのは、後述するob_*_flush()系の関数でも、バッファの内容の出力が実行されるため、使い分けに迷ったと言う経緯があるからだ。単にバッファ記録中のある時点の値を取るだけなら、ob_get_contents()関数を使うと覚えておけばとりあえず大丈夫だと覚えている(間違っていたらすいません)。

 

バッファの記録の終了

バッファの記録の終了は、ob_end_clean()、またはob_end_flush()を用いると良いだろう。

  • ob_end_clean()の場合、現在のバッファの記録を単純に終了する。
  • ob_end_flush()の場合、現在のバッファの記録の終了とともに、バッファの内容を一個下の階層に送信する。最下層のバッファだった場合は画面に出力する。ob_start()にコールバック関数を引数として渡していた場合、コールバック関数を実行して出力を送信する。

 

 

記事が気に入った方はシェアをお願いします!

コメントを残す

メールアドレスが公開されることはありません。