我正在开发一个 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);
}
}
关于这个例子的两个注意事项;首先,我当然把事情过分简单化了。其次,您可以采用的一个巧妙技巧是稍微修改子类,以便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 的类型提示机制。因此,您应该阅读它的手册条目,以便了解细微差别(例如默认空值)。
我不认为有语言支持的方式,所以这将取决于技巧。您可以做的是向您的私有类的构造函数添加一个秘密参数,该参数只有您的主类知道。如果不存在,则抛出 NotAllowed 异常。
我知道这很丑陋,而且不是很安全(是的,没有人喜欢通过默默无闻的安全性),但它可能足以满足您的具体情况......
我知道这个话题现在有点老了,但我只是在想我在 Java 中如何做到这一点是使用调用堆栈检查,PHP 没有类似的东西吗?事实上它确实如此,尽管它是一个 PECL 模块:
http://www.php.net/manual/en/function.apd-callstack.php
获取调用堆栈,根据您的代码点检查它,如果不匹配则抛出异常。你甚至可以创建一个通用的超类来为你做这个检查。