I am working on a PHP library in which we will be supplying our clients with encrypted code. The code will include a main classes which they can instantiate that will handle license verification and expose methods for their use. The main class will instantiate several sub classes each contained in their own file. How can I prevent our clients from including the subclass files and instantiating the sub classes themselves for use? Is there a way to prevent a sub class from being instantiated except from our main class?
I don't think there's a language-supported way, so it'll be down to tricks. What you could do is add a secret argument to your private class's constructors, which is only known by your main class. If that's not present, throw a NotAllowed exception.
I know it's ugly, and not very safe (yes no-one likes security-through-obscurity), but it might work enough for your specific case...
Wild guess, but use a Singleton for the main class, and factory/Singleton with dependency injection (of the main class) for all the subclasses. That way the subclasses won't even load without a valid reference to an instance of your primary class.
EDIT: Since this answer was accepted I've decided to provide an example, for the benefit of future readers. Also, don't forget to mark all of your classes as final.
Primary Class:
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;
}
}
Singleton Subclass:
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;
}
}
Factory Subclass:
final class myFactorySubClass {
private function __construct(myPrimaryClass $primaryClassInstanceRef) {
return $this;
}
public static function getNewInstance(myPrimaryClass $primaryClassInstanceRef) {
return new myFactorySubClass($primaryClassInstanceRef);
}
}
Two notes about this example; first, of course I'm grossly oversimplifying the matter. Second, one neat trick you could employ is to modify the subclasses slightly so that the getInstance()
methods do not always need to have an instance of the primary class passed as an argument after the first time. I'll provide an example here with the singleton class:
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;
}
}
Please note, this relies heavily on PHP's type-hinting mechanism. As such, you should read the manual entry on it so you understand the nuances (e.g. default null).