サブバージョン設定 · 1 min read · Jan 19, 2026
PHP駆動のウェブサイトのためのモジュラーサブバージョンリポジトリの設定
PHP駆動のウェブサイトのためのモジュラーサブバージョンリポジトリの設定
Willem Bogaerts - Kratz Business Solutions
概要
プロジェクト間でコードを共有することは、サブバージョンでは依然として簡単なことではありません。特に、SourceSafeに慣れている場合、サブバージョンはコードの共有を難しくします。サブバージョンは、バージョンの混乱を作成するのが得意であり、それを解決するのも得意ですが、ソースコード管理が必要な理由は、そのような混乱を防ぐためです。ここでサブバージョンは大いに改善されるべきですが、不可能ではありません。このハウツーでは、サブバージョンの共有メカニズムを考慮したディレクトリ構成や、リポジトリがもたらす他の問題について説明します。
このハウツーの規約
多くの場所で
サブバージョンが何であるか、基本的な使い方を知っていて、リポジトリを持っているか、作成できることが前提とされています。
このハウツーは、リポジトリを整理する「最良の」方法を提供するものではありません。なぜなら、それはあなたのニーズに依存するからです。いくつかの決定とそれがリポジトリの構造にどのように影響するかを示すことで、助けることを目的としています。
サブバージョンのコード共有の方法
作業コピー内のディレクトリは、svn:externalsプロパティを定義することで他のリポジトリへのリンクを含むことができます。これにより、リンクされたリポジトリディレクトリが作業コピーに含まれますが、プロジェクト自体の一部にはなりません。つまり、作業コピー内でファイルを含むディレクトリを見ることができますが、中央リポジトリには表示されません。中央リポジトリではプロパティのみを見ることができます。
この共有方法にはいくつかの欠点があります:
- リンクには絶対URLのみを指定できるため、リポジトリをシームレスに移行することはほぼ不可能です。プロトコルを切り替える(例えば、svn://からhttps://へ)ことでも、壊れた作業コピーや多くの問題が発生します。
- ファイルをリンクすることはできず、ディレクトリのみをリンクできます。これはコードの整理に大きな影響を与えます。
PHPディレクトリの問題
ウェブサイト上のディレクトリ、特にPHPで作業する際に考慮すべきことがいくつかあります。セキュリティの観点から、ブラウザからアクセス可能なディレクトリにすべてのソースを置きたくありません。ブラウザによって呼び出される必要があるファイルのみをそこに置きます。これらのファイルを「実行」ファイルと呼び、クラス定義や関数定義のみが含まれる「定義」ファイルと対比します。実行コードと定義コードを1つのファイルに混在させることは、一般的には良いアイデアではありません。
また、セキュリティの観点から、多くのサイトにはユニットテスト、エラーログページ、または完全なバックオフィスサイトを含む制限エリアがあります。この制限エリアは通常、ウェブサーバーによってパスワード保護されています。
したがって、プロジェクトには定義ファイルを含むディレクトリと、実行ファイルを含むウェブルートディレクトリ(通常はwww/またはhtdocs/)が含まれ、オプションで制限エリアがあります。
PHPと相対ディレクトリ
残念ながら、PHPはインクルードファイルの場所を決定する非常に直感に反する方法を持っています。ファイルのインクルードコマンドはすべて、最初に呼び出されたファイルに対して機能し、現在のファイルに対しては機能しません。さらに悪いことに、元の場所が存在するファイルに繋がらない場合、現在のファイルの場所が使用されます。
これは複雑に聞こえますが、実際にそうです。以下に例を示します:
「index.php」というページを呼び出すとします。このページは「library/functions.php」というページをインクルードします。これが「settings.php」をインクルードします。「settings.php」はライブラリディレクトリで検索されると思うかもしれませんが、実際にはそうではありません。「index.php」と同じディレクトリで検索されます!
上記のように、PHPはファイルが見つからない場合、期待されるディレクトリで探し続けます。したがって、すべてが期待通りに機能しているように見えますが、異なるディレクトリに同じ名前のファイルがある場合に問題が発生します。その場合、PHPが「突然」間違ったディレクトリからファイルを選択する理由を見つけるのは非常に難しいです。
これは、相対パスで他のファイルを安全にインクルードできないことを意味します。次のようなコードで絶対パスにする必要があります:
require_once(dirname(__FILE__) . '/library/functions.php');相対パスの最初に’/‘を忘れないでください。dirname関数はトレーリングスラッシュなしのパスを返します。
リポジトリの整理
プロジェクトのコードに関して考慮すべきことがいくつかあります。開発のためには、プロジェクト全体を一度にチェックアウトするのが便利です。しかし、ライブサーバーでは、これが望ましいとは限りません。データベースコード(SQLスクリプト)をウェブディレクトリから遠く離れたディレクトリにチェックアウトしたい場合もあります。サーバーに全く置きたくないプロジェクトの部分もあるかもしれませんが、開発には必要なドキュメントファイルのように。
さらに、共有コードを保存するための中央の場所が必要です。理論的には、他のプロジェクトからコードを「借りる」ことができますが、どのプロジェクトがどの他のプロジェクトに依存しているかを追跡するのは非常に難しいです。代わりに、標準コードを中央の場所に移動します。
ルートディレクトリ
すべての標準コードを含む中央の場所は「
ブランチとタグ
サブバージョンリポジトリでは、コードを「trunk」と呼ばれるブランチに保ち、必要に応じて同じレベルに他のブランチを作成するのが良い習慣です。ブランチをまだ作りたくない場合でも、プロジェクトの直下に「trunk」というディレクトリを作成してください。trunkはアクティブなブランチです。
これを考えてみてください。 標準ライブラリのtrunkにリンクすると、アクティブなブランチにリンクすることになります。これは、リンクされたライブラリのすべてのエラー修正が作業コピーを更新するたびに更新されることを意味します。しかし、エラーを導入した場合、それも作業コピーに更新されます。ライブウェブサーバー上のものも含まれます!より安定したブランチにリンクしたいかもしれませんが、エラー修正には少し多くのオーバーヘッドが必要です。
どのリンクを選んでも、後でいつでも切り替えられることを知っておくと良いでしょう。
コンポーネントまたはプロジェクトに含まれるもの
リポジトリに入れたいものはたくさんあり、すべてをウェブサーバーの同じ場所に置きたくありません。いくつかのものは、ウェブサーバーに置かない方が良いか、別のサーバー(データベースサーバーなど)にチェックアウトされるべきです。
開発マシンでの作業コピーのセットアップは、サーバー上のものとは異なることに注意してください。開発マシンでは、すべてのプロジェクトのための中央のルートディレクトリがあるでしょう。このディレクトリは、ローカルホストのウェブサーバーを介してアクセス可能として設定されるため、作業中の各プロジェクトのためにサーバーを再構成する必要はありません。ライブサーバーでは、いずれにせよ設定が必要であり、セキュリティ上の考慮から、必要なファイルのみをチェックアウトし、それ以上は行いません。まず、各コンポーネントに次のディレクトリを作成します(必要に応じて):
documentation/顧客の入力、データベースおよびオブジェクトスキーマなど。ウェブサーバーに置く必要はありませんが、開発者には非常に便利です。sql/データベース作成、更新、変換スクリプト。データベースサーバーでのチェックアウト用。code/実際のアプリケーションコード test/ユニットテスト
これらのディレクトリは、プロジェクト内でもほぼ同じように見えますが、ユニットテストは実行可能であるべきであり、したがってコードセクションの一部です。ユニットテストをライブサーバーに存在させたくない場合は、別に保管できます。プロジェクトのために、私のセットアップは次のようになります:
documentation/上記の通り。使用されるコンポーネントからの参照も含まれます。database/データベース作成スクリプトと参照を含む
sql
使用されるコンポーネントからのディレクトリ。web/定義されたアプリケーションコード。web/htdocs/実際の実行アプリケーションコード、HTMLページ、スタイルシートや画像などの他のウェブコンテンツを含むサイトルート。web/htdocs/restricted/制限エリア。web/test/ユニットテスト。使用されるコンポーネントのテストからの参照を含む。selenium/機能テスト(参照:
)。
実行コードと定義コード(再び)
実行コードと定義コードを別々のディレクトリに置くことができるので、実行コードをウェブルート内の別のディレクトリにチェックアウトできます。しかし、これは、そのコードを含むサブディレクトリがURLの一部になることを意味します(例えば、www.example.com/restricted/errorhandling/viewerrorlog.phpのように)、これは望ましくないかもしれません(www.example.com/restricted/viewerrorlog.phpのようにしたいかもしれません)。これには解決策があります。実行ファイルをアクセスできない場所に置き、アクセス可能な場所に一種のプロキシを置くことができます。このプロキシは、アクセスできない場所のファイルを指すインクルードまたはリクワイアステートメントだけを持つPHPファイルです:
/htdocs/restricted/viewerrorlog.phpと呼ばれる
// これは、ブラウザから直接呼び出すことができない/errorhandling/viewerrorlog.phpを指すプロキシです。
// (ウェブルートの外にあるため)
require(dirname(__FILE__) . '/../../errorhandling/viewerrorlog.php');
?> ディレクトリerrorhandlingは、標準ライブラリから共有され、エラーを処理するための「定義」クラスファイルと、それらを表示するための「実行」ファイルを含みます。
マシン依存の設定
設定ファイルはリポジトリ内では少し異常です。リポジトリに持っておきたいですが、自動的に更新されることは望ましくありません。私の設定ファイルのための中間的な方法を使用しています:設定ディレクトリにsettings_example.phpというファイルを作成します。このファイルには、異なるマシンのための設定方法に関するコメントとともに、すべての設定が含まれています。また、settings.phpというファイルにコピーする必要があるというコメントも含まれています。
他のファイルからsettings.phpを参照するだけで、settingsディレクトリに「settings.php」という値のsvn:ignoreプロパティを設定します。これにより、作業コピーは「箱から出して」実行されませんが、マシン依存の設定に依存しているため、実行されないでしょう。svn:ignoreプロパティは、異なるマシンの設定が更新時にあなたの設定を上書きするのを防ぎます。
実践に移す
例を挙げましょう。メールを送信し、PDFファイルを作成する必要があるプロジェクトがあるとします。PEARからPHPMailerを使用し、FPDFライブラリを使用することに決めました。PHPの設定に特別な制限を課さないために、PHPMailerをダウンロードして「pear install」メソッドを使用せずにインストールします。
また、このプロジェクトには標準のエラーハンドリングと標準のデータベースクラスがあります。簡単のために、空のリポジトリから始めると仮定します。
必要なディレクトリの作成
まず、上記で説明したルートディレクトリを作成します:
まず外部ライブラリに対処します。PHPMailerとFPDFをダウンロードして解凍し、それぞれ
次に、作業するプロジェクトを作成します。このプロジェクトは顧客「CustomerInc」のもので、プロジェクト名は「SamplePrj」です。あなたがプロジェクトに対してより良い名前を思いつくことができると確信しています。したがって、
共有の作成
これまで、リポジトリに直接すべてを行ってきました。しかし、コードを共有するためには、まず作業コピーを作成する必要があります。では、それを行いましょう。
ローカルホストのウェブサーバーがすべてのプロジェクトコードにアクセスできる必要があるため、ファイルシステムのルートフォルダー(/projects/
作業コピーには、htdocsディレクトリがあるwebディレクトリがあり、FPDFとPHPMailerへのリンクを作成したいと考えています。これらのリンクを作成するには、次の値を持つサブバージョンプロパティsvn:externalをwebディレクトリに追加します:
fpdf /external/fpdf/trunk/code
phpmailer /external/phpmailer/trunk/code (はい、値は2行で構成されています)その後、作業コピーを更新します。これで、プロジェクトの作業コピーの更新時に2つの追加ディレクトリが得られるはずです。
注意:私はtrunkへのリンクを作成しました。代わりにブランチにリンクするか、特定のリビジョン番号にリンクすることもできます。私はコードセクションへの外部参照のみを作成しました。おそらく、外部ライブラリのドキュメントへの外部参照も作成したいでしょう。
標準ライブラリへの有用なコードの移動
プロジェクトが成熟するにつれて、他のプロジェクトで役立つコードがますます増えていきます。私たちのケースでは、エラーハンドリングパッケージとデータベースクラスを開発したとしましょう。もちろん、最初のステップは、このコードからプロジェクト依存関係を削除することです。共有するコード(パッケージと呼びましょう)を別のディレクトリに置きます。これは、標準ライブラリから戻すときに別のディレクトリに置く必要があります。したがって、一般的なエラーハンドリングコードはwebディレクトリの下にerrorhandlingというディレクトリにあり、データベースクラスはdatabaseというディレクトリにあります。
svn mkdirおよびsvn moveコマンドや、任意のグラフィカルサブバージョンクライアントを使用して、プロジェクト内のパッケージを
サーバー上の各変更後に作業コピーを更新すれば、何も問題は起こりません。問題は、元のプロジェクトの場所にまだパッケージがある作業コピーがあり、その同じディレクトリがsvn:externals参照から来る状態に更新したい場合に発生します。それを試みると、外部参照のターゲットディレクトリがすでに存在するため、外部参照を作成できないというエラーが表示されます。これは、作業コピーを更新する前にそのディレクトリを手動で削除することで簡単に解決できます。
ユニットテスト、ドキュメント、SQLスクリプトなども同様の方法で標準ライブラリに移動します。
ライブサーバーの更新
複数の人がウェブまたはデータベースサーバーにアクセスする場合、すべての人に1つのアカウントを使用する方が良いです。これにより、.svnディレクトリが競合するアカウント設定やユーザー権限の影響を受けないことが保証されます。さらに、そのアカウントにリポジトリへの書き込み権限を拒否することができるため、侵害されたウェブサーバーが悪意のあるものを簡単にコミットすることはできません。
Linuxウェブサーバーでは、次の権限が意味を持ちます:ライブ作業コピーを更新するユーザーに対して読み取りおよび書き込み、グループ(ウェブサーバーのグループ)に対して読み取り権限、他のユーザーには権限なし。ディレクトリにSGIDビットを設定すると、追加されたすべてのファイルもウェブサーバーにアクセス可能になります。chmod g+s
drwxr-s--- 9 webdev abyssd 4096 2007-09-08 12:42 restricted/
-rw-r----- 1 webdev abyssd 441 2007-09-08 12:42 index.php
-rw-r----- 1 webdev abyssd 2954 2007-09-08 12:42 main.cssモジュラーなデータベースコード
PHPでのインクルードの仕組みについてはすでに説明しましたが、SQLでファイルをどのようにインクルードするのでしょうか?リポジトリをこのように整理したため、SQLコード内で異なるディレクトリから異なるファイルをインクルードできる必要があります。PHPコードを共有する場合は、対応するSQLコードも共有する必要があります。それを行うために、少しのPHPと少しのPythonスクリプトを書きました。これらはhttp://www.w-p.dds.nl/sqlincludeparser_php.txt(PHP)およびhttp://www.w-p.dds.nl/sqlincludeparser_py.txt(Python)で見つけることができます。これらのスクリプトを使用すると、次の形式の基本ファイル内でインクルードステートメントを定義できます:
CREATE DATABASE IF NOT EXISTS someDatabase;
USE someDatabase;
-- @include(errorhandling/errortables.sql) # (再)作成するエラーハンドリングパッケージによって使用されるテーブル
DROP TABLE IF EXISTS someTable;
CREATE TABLE someTable
(someID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
...etc.すべてのインクルードファイルと基本ファイルを繰り返し可能にすれば、クリーンな状態に何度も戻すことができ、テストや開発に非常に便利です。使用するには、私のスクリプトの出力をSQLコマンドラインクライアントにパイプします:
sqlincludeparser.py | mysql -u -p [] 新しい投稿を受信箱で受け取る
スパムはありません。いつでも購読を解除できます。