1
0
mirror of https://github.com/php/doc-ja.git synced 2026-03-23 22:52:11 +01:00
Files
archived-doc-ja/reference/phar/using.xml
Yoshinari Takaoka 7a512f8031 s/静的メソッド/staticメソッド/
find . -name '*.xml' | xargs sed -i "s/静的メソッド/staticメソッド/g"
2022-05-03 02:15:42 +09:00

407 lines
18 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: e9f972da6918eabb189ba377822a1d6ad982c96d Maintainer: takagi Status: ready -->
<!-- Credits: mumumu -->
<chapter xml:id="phar.using" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Phar アーカイブの使用法</title>
<section xml:id="phar.using.intro" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Phar アーカイブの使用法: 導入</title>
<para>
Phar アーカイブは Java の JAR アーカイブと似た概念のものですが、
PHP アプリケーションで使用する際に必要な機能をより柔軟に使用できるよう改良しています。
Phar アーカイブを使用すると、PHP アプリケーションやライブラリを
ひとつのファイルにまとめて配布できるようになります。
Phar アーカイブ形式のアプリケーションは、その他の PHP
アプリケーションとまったく同様に扱えます。
</para>
<screen>
<![CDATA[
php coolapplication.phar
]]>
</screen>
<para>
Phar アーカイブ形式のライブラリを使用する方法も、
その他の通常の PHP ライブラリとまったく同じです。
</para>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
include 'coollibrary.phar';
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
<literal>phar</literal> ストリームラッパーは phar 拡張モジュールの要となるものです。
詳細については <link linkend="phar.using.stream">こちら</link>
で説明します。このストリームラッパーを使用すると、
phar 内の個々のファイルに対して
<function>fopen</function><function>opendir</function>
といった標準のファイル操作関数を使用でき、
まるで通常のファイルシステム上にあるのと同じような感覚でアクセスできます。
<literal>phar</literal> ストリームラッパーは、
ファイルやディレクトリに対する読み書き操作をすべてサポートしています。
</para>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
include 'phar://coollibrary.phar/internal/file.php';
header('Content-type: image/jpeg');
// phar にアクセスするには、フルパスあるいはエイリアスを使用します
echo file_get_contents('phar:///fullpath/to/coollibrary.phar/images/wow.jpg');
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
<classname>Phar</classname> クラスでは、
ファイルへのアクセスや phar アーカイブ作成用により高度な機能も実装しています。
Phar クラスについての説明は
<link linkend="phar.using.object">こちら</link> をご覧ください。
</para>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
try {
// 既存の phar をオープンします
$p = new Phar('coollibrary.phar', 0);
// Phar は SPL の DirectoryIterator クラスを継承しています
foreach (new RecursiveIteratorIterator($p) as $file) {
// $file は PharFileInfo クラスで、これは SplFileInfo を継承しています
echo $file->getFileName() . "\n";
echo file_get_contents($file->getPathName()) . "\n"; // 内容を表示します
}
if (isset($p['internal/file.php'])) {
var_dump($p['internal/file.php']->getMetadata());
}
// 新しい phar の作成 - php.ini で phar.readonly を 0 にしておく必要があります。
// phar.readonly は、セキュリティ上の理由によってデフォルトで有効になっています。
// 実際の運用サーバーでは、決して Phar を作成する必要はないはずで、
// 単に実行できるだけでよいはずです。
if (Phar::canWrite()) {
$p = new Phar('newphar.tar.phar', 0, 'newphar.tar.phar');
// tar 形式の phar アーカイブを作成し、gzip で圧縮します (.tar.gz)
$p = $p->convertToExecutable(Phar::TAR, Phar::GZ);
// トランザクションの作成 - newphar.phar には、
// stopBuffering() がコールされるまで (一時的なストレージが必要となっても) なにも書き込まれません
$p->startBuffering();
// すべてのファイルを /path/to/project に追加し、プレフィックス "project" で phar に保存します
$p->buildFromIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator('/path/to/project')), '/path/to/');
// 配列形式の API で新しいファイルを追加します
$p['file1.txt'] = 'Information';
$fp = fopen('hugefile.dat', 'rb');
// すべてのデータをストリームからコピーします
$p['data/hugefile.dat'] = $fp;
if (Phar::canCompress(Phar::GZ)) {
$p['data/hugefile.dat']->compress(Phar::GZ);
}
$p['images/wow.jpg'] = file_get_contents('images/wow.jpg');
// ファイルのメタデータには任意の値を保存できます
$p['images/wow.jpg']->setMetadata(array('mime-type' => 'image/jpeg'));
$p['index.php'] = file_get_contents('index.php');
$p->setMetadata(array('bootstrap' => 'index.php'));
// phar アーカイブをディスクに保存します
$p->stopBuffering();
}
} catch (Exception $e) {
echo 'Phar をオープンできません: ', $e;
}
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
さらに、phar ファイルの中身の検証を行うこともできます。対称型ハッシュアルゴリズム
(MD5、SHA1、SHA256、そしてもし ext/hash が有効ならさらに SHA512) のいずれか、
あるいは OpenSSL を使用した非対称公開鍵/秘密鍵ペアによる署名のいずれかを使用します。
OpenSSL による署名を使用するには、
まず公開鍵/秘密鍵のペアを作成し、秘密鍵を使用して
<function>Phar::setSignatureAlgorithm</function> で署名を行います。
公開キーによる展開はこのようなコードで行います。
<programlisting role="php">
<![CDATA[
<?php
$public = openssl_get_publickey(file_get_contents('private.pem'));
$pkey = '';
openssl_pkey_export($public, $pkey);
?>
]]>
</programlisting>
公開鍵は phar アーカイブと同じ場所、名前でなければなりません。つまり、phar アーカイブの保存先が
<literal>/path/to/my.phar</literal> の場合は公開鍵を
<literal>/path/to/my.phar.pubkey</literal> としなければなりません。
そうしないと、OpenSSL 署名の検証ができなくなります。
</para>
<para>
<classname>Phar</classname> には 3 つのstaticメソッド
<function>Phar::webPhar</function>
<function>Phar::mungServer</function> そして <function>Phar::interceptFileFuncs</function>
が追加されました。これは、通常のファイルシステム用あるいはウェブアプリケーション用の
PHP アプリケーションのパッケージを作成する際に重要となります。
<function>Phar::webPhar</function> は、HTTP のコールを phar
アーカイブ内の特定の場所に転送するフロントコントローラを実装します。
<function>Phar::mungServer</function>
<varname>$_SERVER</varname> 配列の中身をうまく変更して
アプリケーションでその値を使えるようにします。
<function>Phar::interceptFileFuncs</function> は、
<function>fopen</function><function>file_get_contents</function><function>opendir</function>
そしてすべての stat 系関数 (<function>file_exists</function><function>is_readable</function> など)
のコールを Phar が横取りして、相対パスを phar アーカイブ内の適切な位置に変換するようにします。
</para>
<para>
たとえば、あの有名な phpMyAdmin を phar アーカイブにすることを考えてみましょう。
必要なのは、こんな単純なスクリプトだけです。あとは、
ユーザー名とパスワードを変更してウェブサーバー上から
<literal>phpMyAdmin.phar.tar.php</literal> にアクセスするだけで利用できます。
</para>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
@unlink('phpMyAdmin.phar.tar.php');
copy('phpMyAdmin-2.11.3-english.tar.gz', 'phpMyAdmin.phar.tar.php');
$a = new Phar('phpMyAdmin.phar.tar.php');
$a->startBuffering();
$a["phpMyAdmin-2.11.3-english/config.inc.php"] = '<?php
/* サーバーの設定 */
$i = 0;
/* Server localhost (config:root) [1] */
$i++;
$cfg[\'Servers\'][$i][\'host\'] = \'localhost\';
$cfg[\'Servers\'][$i][\'extension\'] = \'mysqli\';
$cfg[\'Servers\'][$i][\'connect_type\'] = \'tcp\';
$cfg[\'Servers\'][$i][\'compress\'] = false;
$cfg[\'Servers\'][$i][\'auth_type\'] = \'config\';
$cfg[\'Servers\'][$i][\'user\'] = \'root\';
$cfg[\'Servers\'][$i][\'password\'] = \'\';
/* サーバーの設定はここまで */
if (strpos(PHP_OS, \'WIN\') !== false) {
$cfg[\'UploadDir\'] = getcwd();
} else {
$cfg[\'UploadDir\'] = \'/tmp/pharphpmyadmin\';
@mkdir(\'/tmp/pharphpmyadmin\');
@chmod(\'/tmp/pharphpmyadmin\', 0777);
}';
$a->setStub('<?php
Phar::interceptFileFuncs();
Phar::webPhar("phpMyAdmin.phar", "phpMyAdmin-2.11.3-english/index.php");
echo "phpMyAdmin is intended to be executed from a web browser\n";
exit -1;
__HALT_COMPILER();
');
$a->stopBuffering();
?>
]]>
</programlisting>
</informalexample>
</para>
</section>
<section xml:id="phar.using.stream" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Phar アーカイブの使用法: phar ストリームラッパー</title>
<para>
Phar ストリームラッパーは、<function>fopen</function> による読み込みや
書き込み (追記は除く)、<function>unlink</function><function>stat</function>
<function>fstat</function><function>fseek</function><function>rename</function>
そしてディレクトリに対する <function>opendir</function><function>rmdir</function>
<function>mkdir</function> といった機能に完全に対応しています。
</para>
<para>
Phar アーカイブ内の各ファイルの圧縮やファイル単位のメタデータの操作も、
ストリーム上で可能です。
</para>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$context = stream_context_create(array('phar' =>
array('compress' => Phar::GZ)),
array('metadata' => array('user' => 'cellog')));
file_put_contents('phar://my.phar/somefile.php', 0, $context);
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
<literal>phar</literal> ストリームラッパーは、
リモートファイルを操作することはできません。つまり、INI 設定
<link linkend="ini.allow-url-fopen">allow_url_fopen</link> および
<link linkend="ini.allow-url-include">allow_url_include</link>
が無効になっている場合でも使用できます。
</para>
<para>
ストリーム操作だけで新しい phar アーカイブをゼロから作成することも可能ですが、
そんな場合は Phar クラスの組み込み機能を使用するほうが便利です。
ストリームラッパーが有用なのは、読み込み専用の操作を行う場合です。
</para>
</section>
<section xml:id="phar.using.object" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Phar アーカイブの使用法: Phar クラスおよび PharData クラス</title>
<para>
<classname>Phar</classname> クラスは Phar アーカイブの読み込みや操作をサポートしています。
また <classname>RecursiveDirectoryIterator</classname>
クラスを継承しているため、順次処理も可能です。
<interfacename>ArrayAccess</interfacename> インターフェイスをサポートしているので、
Phar アーカイブ内のファイルに対して、
それがまるで連想配列であるかのようにアクセスすることができます。
</para>
<para>
<classname>PharData</classname> クラスは <classname>Phar</classname>
を継承したもので、実行可能でない (データ) tar アーカイブおよび
zip アーカイブなら php.ini で
<literal>phar.readonly</literal>=1 であっても作成/変更できるようになります。
このクラスでは
<function>PharData::setAlias</function><function>PharData::setStub</function>
は使用不可能になっています。というのもエイリアスやスタブというのは
実行可能な phar アーカイブに独特の概念だからです。
</para>
<para>
注意すべき点は、Phar アーカイブを作成する際には
<classname>Phar</classname> のコンストラクタに
フルパスを渡さなければならないということです。
相対パスでは初期化に失敗します。
</para>
<para>
<literal>$p</literal> が、次のように作成した Phar オブジェクトであるとしましょう。
</para>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$p = new Phar('/path/to/myphar.phar', 0, 'myphar.phar');
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
空の Phar アーカイブが <literal>/path/to/myphar.phar</literal>
に作成されます。もし <literal>/path/to/myphar.phar</literal>
が既に存在する場合は、それを再度オープンします。
リテラル <literal>myphar.phar</literal> は、エイリアスを表します。
これを用いると、URL で <literal>/path/to/myphar.phar</literal>
を参照する際に次のようにできます。
</para>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
// これらのふたつの file_get_contents() コールが同等となるのは、
// /path/to/myphar.phar のマニフェストでエイリアス "myphar.phar"
// が明示的に指定されている場合か、先ほどの例のように
// Phar オブジェクトを初期化した場合です。
$f = file_get_contents('phar:///path/to/myphar.phar/whatever.txt');
$f = file_get_contents('phar://myphar.phar/whatever.txt');
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
新しく作成した <classname>Phar</classname> オブジェクト
<literal>$p</literal> に対して、次のような処理が可能となります。
<itemizedlist>
<listitem>
<simpara>
<literal>$a = $p['file.php']</literal> とすると、
<literal>phar://myphar.phar/file.php</literal> の中身を参照する
<classname>PharFileInfo</classname> クラスが作成されます。
</simpara>
</listitem>
<listitem>
<simpara>
<literal>$p['file.php'] = $v</literal> とすると、
<literal>myphar.phar</literal> の中に新しいファイル
(<literal>phar://myphar.phar/file.php</literal>)
を作成するか、あるいは同名のファイルを上書きします。
<literal>$v</literal> には、文字列あるいはファイルポインタのいずれかを指定できます。
ファイルポインタを指定した場合は、その中身全体をもとにして新しいファイルを作成します。
<literal>$p-&gt;addFromString('file.php', $v)</literal> は、
機能的に上と同じであることに注意しましょう。また、ファイルの中身を
<literal>$p-&gt;addFile('/path/to/file.php', 'file.php')</literal>
で追加することもできます。最後に、空のディレクトリを作成するには
<literal>$p-&gt;addEmptyDir('empty')</literal> とします。
</simpara>
</listitem>
<listitem>
<simpara>
<literal>isset($p['file.php'])</literal>
とすると、<literal>phar://myphar.phar/file.php</literal>
<literal>myphar.phar</literal> の中に存在するかどうかがわかります。
</simpara>
</listitem>
<listitem>
<simpara>
<literal>unset($p['file.php'])</literal> とすると、
<literal>phar://myphar.phar/file.php</literal>
<literal>myphar.phar</literal> から削除します。
</simpara>
</listitem>
</itemizedlist>
</para>
<para>
さらに、Phar 固有のメタデータにアクセスするためには
<classname>Phar</classname> オブジェクトを使用することが唯一の方法となります。そのためには
<function>Phar::getMetadata</function>
を使用します。また、Phar アーカイブの PHP ローダスタブを設定したり取得したりするための唯一の方法が
<function>Phar::getStub</function> および
<function>Phar::setStub</function> です。
また、Phar アーカイブ全体の圧縮を行うには
<classname>Phar</classname> クラスが必要となります。
</para>
<para>
<classname>Phar</classname> オブジェクトの全機能の一覧については、以下で説明します。
</para>
<para>
<classname>PharFileInfo</classname> クラスは
<classname>SplFileInfo</classname>
クラスを継承しており、Phar 内のファイルについての Phar
固有の情報 (圧縮情報やメタデータなど) を扱うためのメソッドが追加されています。
</para>
</section>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->