PHP Conference Nagoya 2025

PharData::buildFromIterator

(PHP 5 >= 5.3.0, PHP 7, PHP 8, PECL phar >= 2.0.0)

PharData::buildFromIteratorイテレータから tar あるいは zip アーカイブを作成する

説明

public PharData::buildFromIterator(Traversable $iterator, ?string $baseDirectory = null): array

tar あるいは zip アーカイブをイテレータから作成します。 サポートするイテレータは二種類で、 tar/zip 内のファイル名とディスク上の実際のファイル名を対応させたものか、あるいは DirectoryIterator のように SplFileInfo オブジェクトを返すものです。 SplFileInfo オブジェクトを返すイテレータの場合は、2 番目のパラメータが必要となります。

パラメータ

iterator

phar ファイルと実際の場所の関連を返すイテレータ、 あるいは SplFileInfo オブジェクトを返すイテレータ。

baseDirectory

SplFileInfo オブジェクトを返すイテレータを指定した際、 tar/zip アーカイブへの追加時にフルパスから取り除く部分。

戻り値

PharData::buildFromIterator() は連想配列を返します。 これは、ファイルの内部パスとファイルシステム上のフルパスを対応させたものです。

エラー / 例外

このメソッドは、イテレータが間違った値 (たとえば文字列キーではなく整数キーなど) を返した場合に UnexpectedValueException を返します。また、SplFileInfo 型のイテレータを渡したときに baseDirectory を指定しなかった場合は BadMethodCallException を、 phar アーカイブの保存時にエラーが発生した場合は PharException を返します。

変更履歴

バージョン 説明
8.1.0 PharData::buildFromIterator() は、 false を返さなくなりました。
8.0.0 baseDirectory は、nullable になりました。

例1 SplFileInfo を使用した PharData::buildFromIterator() の例

ほとんどの tar/zip アーカイブは、実際のディレクトリ構造を反映した形式になっています。 このような場合は 2 番目の方式が最適です。 たとえば、次のようなディレクトリ構成のファイルを含む tar/zip アーカイブを作成してみることにしましょう。

/path/to/project/
                 config/
                        dist.xml
                        debug.xml
                 lib/
                     file1.php
                     file2.php
                 src/
                     processthing.php
                 www/
                     index.php
                 cli/
                     index.php

次のコードを使用すると、これらのファイルを tar アーカイブ "project.tar" に追加します。

<?php
$phar
= new PharData('project.tar');
$phar->buildFromIterator(
new
RecursiveIteratorIterator(
new
RecursiveDirectoryIterator('/path/to/project')),
'/path/to/project');
?>

これで、ファイル project.tar はすぐに使えるようになります。 PharData::buildFromIterator() は圧縮やメタデータの設定を行いません。 これらは tar/zip アーカイブを作成した後で行うことができます。

興味深いことに、PharData::buildFromIterator() を使用して既存の phar や tar、あるいは zip アーカイブの中身をコピーすることもできます。 というのも PharData オブジェクトは DirectoryIterator を継承しているからです。

<?php
$phar
= new PharData('project.tar');
$phar->buildFromIterator(
new
RecursiveIteratorIterator(
new
Phar('/path/to/anotherphar.phar')),
'phar:///path/to/anotherphar.phar/path/to/project');
$phar->setStub($phar->createDefaultStub('cli/index.php', 'www/index.php'));
?>

例2 その他のイテレータを使用した PharData::buildFromIterator() の例

それ以外の形式のイテレータでは、 key => value の対応を返すものを使用できます。たとえば ArrayIterator などです。

<?php
$phar
= new PharData('project.tar');
$phar->buildFromIterator(
new
ArrayIterator(
array(
'internal/file.php' => dirname(__FILE__) . '/somefile.php',
'another/file.jpg' => fopen('/path/to/bigfile.jpg', 'rb'),
)));
?>

参考

add a note

User Contributed Notes 1 note

up
1
cbonnissent
10 years ago
The code in the first exemple doesn't work properly without the flag FilesystemIterator::SKIP_DOTS in the RecursiveDirectoryIterator (on a linux filesystem).

So, to build a tar with a phar, I do (with two level of iteration here) :

$pharTar = new \PharData($contentTar.".tar");
$firstLevelIterator = new \DirectoryIterator($this->inputPath);
foreach ($firstLevelIterator as $fileInfo) {
/* @var \SplFileInfo $fileInfo */
if (in_array($fileInfo->getFilename(), $allowedDirectory)) {
$recursiveDirectoryIterator = new \RecursiveDirectoryIterator(
$this->inputPath . DIRECTORY_SEPARATOR . $fileInfo->getFilename(), \FilesystemIterator::SKIP_DOTS);
$pharTar->buildFromIterator(new \RecursiveIteratorIterator($recursiveDirectoryIterator), $this->inputPath);
}
}
To Top