closureを使ったLazyLoad(PHP)

Devshedで紹介されていたclosureの使い方が面白かったので紹介する。

3ページに渡る記事だけど、最後のサンプルを見るだけでも十分。

テンプレート

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Using closures in PHP</title>
</head>
<body>
<header>
<h1>Header section</h1>
<h2>Welcome! You're accessing this page from : <?php echo $this->clientIp;?></h2>
<p><?php echo $this->header;?></p>
</header>
<section>
<h2>Main section</h2>
<p><?php echo $this->content;?></p>
</section>
<footer>
<h2>Footer section</h2>
<p><?php echo $this->footer;?></p>
</footer>
</body>
</html>

PHP

<?php

use MyApplication\View,
MyApplication\Serializer,
MyApplication\FileHandler;

// include the autoloader and create an instance of it
require_once __DIR__ . '/Autoloader.php';
$autoloader = new Autoloader;

// create a view object
$view = new View;
$view->header = 'This is the content of the header section';
$view->footer = 'This is the content of the footer section';
$view->clientIp = $_SERVER['REMOTE_ADDR'];

// lazy load contents from a remote file and assign them to the 'content' field
$view->content = function() {
$fileHandler = new FileHandler(new Serializer);
return $fileHandler->read();
};

// render the view template
echo $view->render();

コレのポイントはテンプレートの

<p><?php echo $this->content;?></p>

PHP

$view->content = function() {
$fileHandler = new FileHandler(new Serializer);
return $fileHandler->read();
}

上記部分、

closureがなかった頃は一度ファイルを読み込んで、それを変数に入れるという2度手間が必要だったけど、

closureによりそれを1箇所にまとめ、かつ「ファイルの読み込み」というコストのかかる処理をそれが必要なタイミングギリギリまで遅らせている。

勿論、上記処理はクラスを使うことによって同等の事が行えるけど、

テンプレートエンジンによってはメソッドの扱いが面倒だったりするし、「クラスの宣言が不要」と言うのも有難い。

今のところ、closureはarray_walk/set-error-handlerなど、callable引数に使うことが多いけど

こういう使い方も直ぐに思い出して使えるようにしたい。