LDIF ファイル

LDIF ファイル -- Net_LDAP_Entries と LDIF ファイルとの相互変換

利用可能なバージョン

LDIF のサポートは Net_LDAP リリース 1.1.0a1 以降で追加されました。

LDIF ファイルとは?

LDIF ファイルの詳細については RFC 2849 に説明されています。簡単に言うと、これはディレクトリのデータを可読形式のテキストにしたものです。 データベースにおける SQL ファイルのようなものです。 しかし、SQL がアクションベースであるのに対して LDIF ファイルはデータが主になっている点が異なります。 LDIF ファイルの中身にはコンテンツファイルとチェンジファイルの二種類の形式があり、 これらを混ぜて使うことができます。 もっともよく使われる形式である LDIF コンテンツファイルをまず紹介します。

LDIF ファイルに記述できるのはエントリのデータだけではありません。 エントリ自体への変更についても記述することができます。 そのような LDIF ファイルを LDAP サーバに渡すと、 データをインポートするのではなくその変更をサーバに適用します。 以下の例でお気づきのように、LDIF の中にはコンテンツとチェンジを両方含めることができます。 ただしこれらは別のエントリという扱いになります。 ひとつのエントリはコンテンツあるいはチェンジのいずれかを表すものであり、 その両方を指定することはできません。

Net_LDAP_LDIF でのエラー処理

Net_LDAP_LDIF を使い始める前に、まずエラー処理の方法について説明しておきましょう。 Net_LDAP_LDIF の API の大半は、お手本となった Perl の Net::LDAP::LDIF と同じです。ということは、Net_LDAP_LDIF のメソッドは Net_LDAP_Error オブジェクトを返さないということです。 代わりに error() メソッドを使う必要があります。 このメソッドは、エラー時には Net_LDAP_Error オブジェクトを返し、 すべてうまくいっている場合には true を返します。LDIF 読み込みモードでは、 さらに error_lines() を使うこともできます。 これは、入力ファイルのどこでエラーが発生したのかを取得するためのものです。

オブジェクトの作成とそのオプション

LDIF ファイルの読み書きどちらを行うかにかかわらず、LDIF ファイルを使用するには Net_LDAP_LDIF のコンストラクタを用いてそのインスタンスを作成しなければなりません。 Net_LDAP_LDIF() には、少なくとも使用するファイルへのパスを渡す必要があります。 2 番目のパラメータとして、オープン時のモードを指定することもできます。 使用できるオープンモードは "r" (読み込み)、"w" (書き込み、最初にファイルをクリアする) そして "a" (追記) のいずれかです。省略した場合は読み込みモードとみなします。 オプションの 3 番目のパラメータには、以下のようなオプションを含む連想配列を指定することができます。

表 54-1使用できる設定オプション

名前説明デフォルト
encode LDIF の DN の値の中には、そのままでは書き込めず何らかのエンコードを要するものもあります。 "none"、"canonical" あるいは "base64" (RFC のデフォルト) のいずれかを指定します。 base64
onerror エラーが発生したときにどうするかを指定します。 "undef" はエラー処理をプログラマに任せます。 この場合は error()error_lines() を用いて手動でエラー処理を行うことになります。 "die" の場合はエラーを表示してその場でスクリプトを終了させます。 これはコマンドラインのスクリプトなどで有用です。 "warn" はエラーを表示しますが、それ以外の挙動は "undef" と同様です。 undef
changeこれを "1" (true) にすると Net_LDAP_LDIF はコンテンツファイルではなくチェンジセットを書き出します。false
lowercaseこれを true にすると、書き込み時に属性の名前を小文字に変換します。0
sort true にすると、エントリの書き込み時に属性名を並べ替えます。まず最初が objectclass で、それに続けてその他の属性をアルファベット順に並べます。 0
version 書き込み時に、作成する LDIF のバージョンを設定します。 RFC 2849 によると、今のところこのオプションに指定できる値は 1 だけです。 1
wrap 出力時に行の折り返しを行う桁数。40 以下を指定した場合は折り返しを行いません。 できあがるファイルの可読性を上げるために有用です。 78
熟練者向けの情報: ファイルのパスではなく、事前に作成済みのファイルハンドルを渡すこともできます。 その場合はモードの指定は無視されます。これを使用すると、 ふたつの Net_LDAP_LDIF インスタンスで同じファイルハンドルを共用することで LDIF コンテンツと LDIF チェンジセットを同じファイルに書き込むことができます。 それ以外の場合でもこの機能は便利です。 ふたつめ以降の Net_LDAP_LDIF インスタンスを作成する際には、 handle() を使用して最初のインスタンスのファイルハンドルを取得します。

Net_LDAP_Entry オブジェクトへの LDIF ファイルの読み込み

Net_LDAP_LDIF の 2 つのモードのうちのひとつが、 LDIF ファイルを読み込んでそれをパースし、 Net_LDAP_Entry オブジェクトの配列にするものです。 これは read_entry() メソッドで行います。 このメソッドは、次のエントリを返します。すべてのエントリを取得したい場合は、 eof() を用いて入力ファイルの終端を検出します。

Net_LDAP_Entry オブジェクトの LDIF コンテンツファイルへの書き出し

LDIF ファイルへの書き出しも非常に簡単です。 単に、書き出したいエントリを write_entry() メソッドに渡すだけでいいのです。注意しなければならないのは、 ファイルを "w" モードでオープンした場合は そのファイルにこれまで書かれていたデータがすべて消えてしまうということです。 単にデータを追加したいだけの場合は "a" (追記) モードでオープンしましょう。

Net_LDAP_Entry オブジェクトの LDIF チェンジファイルへの書き出し

変更内容の書き出し処理は、コンテンツの書き出しと同じです。 しかし、違うところがふたつあります。まず、オプションとして "changes" を渡さなければなりません。また、書き込む内容が変更でなければなりません。 変更を含まないエントリを指定した場合は、何も書き出されません。

LDIF データの取得

時には LDIF ファイルの内容を読み込みたいこともあるでしょう。 その際には current_lines() メソッドや next_lines() メソッドを使用します。 これらのメソッドの挙動は、ちょっととまどうことがあるかもしれません。 current_lines() が返す行は、常に現在の Net_LDAP_Entry オブジェクトで read_entry() の後に current_entry() をコールしたときの行と同じものになります。 next_lines() が返す行は、その時点での次のエントリのものとなります。 つまり "最後に読んだエントリの次のエントリ" ということです。 しかし、この挙動をオーバーライドすることもできます。 next_lines() で "force" パラメータを使用すると、 全エントリをループするようになります。current_entry() の挙動はまさに current_lines() と同じようになります。

読み込んだ行情報を Net_LDAP_Entry オブジェクトにしたい場合は、 parseLines() メソッドで行をパースしてエントリに格納します。 これは、巨大な LDIF ファイルの一部のエントリだけを使いたい場合に便利です。

例 54-7LDIF の行の読み込み

// LDIF ファイルを読み込み用にオープンします
// (この例では読みやすくするためにエラーチェックを省略していますが、
//  実際に使用する際には必ずエラーチェックをしましょう!)
$ldif = new Net_LDAP_LDIF('somefile.ldif', 'r');

// まだ何も読んでいないので、これは空の配列を返します
$empty_array = $ldif->current_lines();

// ではまず、最初のエントリのデータを読んでみましょう
$first_entry_lines = $ldif->next_lines();

// もう一度コールしたとしても、2 番目のエントリを読むわけではありません。
// これはもう一度最初の行を読むことになります!
$first_entry_lines_again = $ldif->next_lines();

// ここで current_lines() をコールしても、
// 先ほどと同様に次には進みません
$empty_array_again = $ldif->current_lines();

// 次に進めたい場合は read_entry() メソッドを使用します。
// これは、読み込んだ後に次に進みます
$first_entry = $ldif->read_entry();

// ここで、current_lines() は最初のエントリを返します。
// 一方 next_lines() は 2 番目の行を返します。
$first_entry_lines  = $ldif->current_lines();
$second_entry_lines = $ldif->next_lines();

// 行を移動するにはもうひとつのやりかたもあります。
// もし LDIF のコンテンツを読みたいだけなのならこちらのほうが高速です。
// この場合は "force" パラメータを next_lines() に渡します
$third_entry_lines  = $ldif->next_lines(true);
$fourth_entry_lines = $ldif->next_lines(true);
$fifth_entry_lines  = $ldif->next_lines(true);

// 行を Net_LDAP_Entry に変換したい場合は
// parseLines() を使用します
$fourth_entry = $ldif->parseLines($fourth_entry_lines);

// 手動で移動させたのは行だけなので、
// current_lines() は直近の Net_LDAP_Entry オブジェクト
// (最初のエントリ) の行を返します
$first_entry_lines  = $ldif->current_lines();

// 次のエントリに移動したい場合は、このようにします
$sixth_entry = $ldif->read_entry();

// これで current_lines() が移動しました
$sixth_entry_lines = $ldif->current_lines();