私は、暗号化されたコードをクライアントに提供するPHPライブラリに取り組んでいます。コードには、ライセンス検証を処理し、使用するメソッドを公開する、インスタンス化できるメインクラスが含まれます。メインクラスは、それぞれが独自のファイルに含まれているいくつかのサブクラスをインスタンス化します。クライアントがサブクラスファイルを含めたり、サブクラス自体をインスタンス化して使用できないようにするにはどうすればよいですか?メインクラス以外でサブクラスがインスタンス化されないようにする方法はありますか?
3 に答える
大げさな推測ですが、メインクラスにはシングルトンを使用し、すべてのサブクラスには(メインクラスの)依存性注入を伴うファクトリ/シングルトンを使用します。そうすれば、サブクラスは、プライマリクラスのインスタンスへの有効な参照がないとロードされません。
編集:この回答が受け入れられたので、将来の読者の利益のために、例を提供することにしました。また、すべてのクラスを最終としてマークすることを忘れないでください。
プライマリクラス:
final class myPrimaryClass {
private static $instance = null;
private function __construct() {
// do something or not
return $this;
}
public static function getInstance() {
if (is_null(self::$instance) || !(self::$instance instanceof myPrimaryClass))
self::$instance = new myPrimaryClass;
return self::$instance;
}
}
シングルトンサブクラス:
final class mySingletonSubClass {
private static $instance = null;
private function __construct(myPrimaryClass $primaryClassInstanceRef) {
return $this;
}
public static function getInstance(myPrimaryClass $primaryClassInstanceRef) {
if (is_null(self::$instance) || !(self::$instance instanceof mySingletonSubClass))
self::$instance = new mySingletonSubClass($primaryClassInstanceRef);
return self::$instance;
}
}
ファクトリーサブクラス:
final class myFactorySubClass {
private function __construct(myPrimaryClass $primaryClassInstanceRef) {
return $this;
}
public static function getNewInstance(myPrimaryClass $primaryClassInstanceRef) {
return new myFactorySubClass($primaryClassInstanceRef);
}
}
この例に関する2つのメモ。まず、もちろん、私は問題を大幅に単純化しすぎています。次に、使用できる巧妙なトリックの1つは、サブクラスをわずかに変更して、getInstance()
メソッドが最初に引数として渡されるプライマリクラスのインスタンスを常に持つ必要がないようにすることです。ここでは、シングルトンクラスの例を示します。
final class mySingletonSubClass {
private static $instance = null;
private static $classInstanceRef = null;
private function __construct(myPrimaryClass $primaryClassInstanceRef) {
return $this;
}
public static function getInstance(myPrimaryClass $primaryClassInstanceRef = null) {
if (!is_null($primaryClassInstanceRef))
self::$classInstanceRef = $primaryClassInstanceRef;
if (is_null(self::$instance) || !(self::$instance instanceof mySingletonSubClass))
self::$instance = new mySingletonSubClass(self::$classInstanceRef);
return self::$instance;
}
}
これは、 PHPの型ヒントメカニズムに大きく依存していることに注意してください。そのため、微妙な違い(デフォルトのnullなど)を理解できるように、マニュアルのエントリを読む必要があります。
言語をサポートする方法はないと思うので、それはトリックにかかっています。できることは、プライベートクラスのコンストラクターに秘密の引数を追加することです。これは、メインクラスだけが知っています。それが存在しない場合は、NotAllowed例外をスローします。
私はそれが醜く、あまり安全ではないことを知っています(はい、隠すことによるセキュリティが好きな人は誰もいません)が、あなたの特定のケースには十分に機能するかもしれません...
このトピックはもう少し古いことは知っていますが、Javaでこれを行う方法は、呼び出し元スタック検査を使用することであり、PHPには同様のものがないのではないかと考えていました。実際には、PECLモジュールですが、次のようになります。
http://www.php.net/manual/en/function.apd-callstack.php
コールスタックを取得し、コードポイントと照合し、一致しない場合は例外をスローします。このチェックを行う共通のスーパークラスを作成することもできます。