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?
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).
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...
I know this topic is a little old by now, but I was just thinking that how I'd do this in Java is with Caller Stack Inspection, and doesn't PHP have something similar? In fact it does, though it's a PECL module:
http://www.php.net/manual/en/function.apd-callstack.php
Get the call stack, check it against your code points, throw an exception if it doesn't match. You could even create a common superclass that does this checking for you.
Related
I'm working on learning OOP PHP and have come across this:
//Store the single instance
private static $_instance;
/*
Get an instance of the database
#return database
*/
public static function getInstance () {
if (!self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
What is the point of setting $_instance to a new self()? I know that all this line is doing is creating a new instance of the class it's in but why would one need to do this? Is there any reason this would ever be needed? I don't ever even call it again in the class. Thanks for any help in advanced.
The idea is that whenever you call getInstance() throughout your code, you will always get the same instance.
This is useful in some cases where you only want to get access to the same object. Often objects like this might have a private constructor, which effectively forces you to always act on the same instance (also known as a singleton).
Generally people say 'Singletons are evil'. They are good to avoid because they can cause major design issues. In some cases they can still be a good idea though.
work example
class Singleton
{
public $data;
private static $instance = null;
public function __construct()
{
$this->data = rand();
}
public static function getInstance()
{
if (is_null(self::$instance))
self::$instance = new self;
return self::$instance;
}
//no clone
private function __clone() {}
//no serialize
private function __wakeup() {}
}
$singleton = Singleton::getInstance();
echo $singleton->data;
echo '<br>';
$singleton2 = Singleton::getInstance();
echo $singleton2->data;
echo '<br>';
This is the Singleton pattern.
It is used when you have an object that requires initialization and/or tear-down work and that work should be performed just once.
The instance cache forces there to only be one instance of the class, ever.
Straight to the point:
I've got two singleton classes, both inheriting their singleton nature from a super-class. I initialize some properties on the first singleton, and then have the second singleton retrieve the instance of the first one. That instance, however, does not seem to be the one I initialized in the first place. Some example code might help to explain this:
First, the super-class, providing singleton nature (requires PHP 5.3 or greater):
class Singleton {
protected static $instance;
protected function __construct() { }
final private function __clone() { }
public static function getInstance() {
if (!(static::$instance instanceof static)) {
static::$instance = new static();
}
return static::$instance;
}
}
Then we've got the the first singleton carrying a value:
require_once('Singleton.php');
class SingletonA extends Singleton {
protected $value;
public function SingletonA() {
$this->value = false;
}
public function getValue() {
return $this->value;
}
public function setValue($value) {
$this->value = $value;
}
}
Then the second singleton that references the first singleton:
require_once('Singleton.php');
require_once('SingletonA.php');
class SingletonB extends Singleton {
public function getValue() {
return SingletonA::getInstance()->getValue();
}
}
Now for the test that shows how this fails:
require_once('SingletonA.php');
require_once('SingletonB.php');
SingletonA::getInstance()->setValue(true);
echo (SingletonA::getInstance()->getValue()) ? "true\n" : "false\n";
echo (SingletonB::getInstance()->getValue()) ? "true\n" : "false\n";
The test yields the following output:
true
false
Clearly, the SingletonA instance that the test code references is not the same instance that the SingletonB instance references. In short, SingletonA is not as single as I need it to be. How is this possible? And what magic can I wield to remedy this behaviour, giving me a true singleton?
Try using isset rather than instanceof:
class Singleton {
protected static $instances;
protected function __construct() { }
final private function __clone() { }
public static function getInstance() {
$class = get_called_class();
if (!isset(self::$instances[$class])) {
self::$instances[$class] = new $class;
}
return self::$instances[$class];
}
}
SingletonA and SingletonB are different classes. Although they inherit from the same class, they are separate classes and so they have different static instances.
If you change your code to get 2 instances of SingletonA or 2 instances of SingletonB, you will see the behavior you expect. But because they are different classes, they are not the same singleton.
I'm pretty sure it's because you are using static methods, which are not instanced.
Let's talk OO. :)
SingletonA and SingletonB are of type Singleton
thus it can be said:
SingletonA is Singleton
and
SingletonB is Singleton
i.e. they're both Singleton
The expected meaning of Singleton means there can be only one. Many people from an OO background using your code will be confused.
Usually, implementation of Singleton would be on a per class basis because most OO languages will not be bent to allow the intent of what you are proposing.
That PHP might do (via get_called_class() magic) doesn't mean it should.
I can absolutely accept that from a utilitarian point of view, the accepted answer looks good. Given the niftyness of the accepted answer, I'd propose a name change that doesn't conflict with "standard" Singleton implementation. From a strict OO point of view, one could never inherit from a Singleton, so it really needs a different name.
Let's imagine that we have Registry pattern...
<?php
class Registry
{
private static $objects = array();
private static $instance = null;
public static function getInstance() {
if (self::$instance == null) {
self::$instance = new Registry();
}
return self::$instance;
}
protected function _get($key) {
return ($this->objects[$key]) ? $this->objects[$key] : null;
}
protected function _set($key, $val) {
$this->objects[$key] = $val;
}
public static function get($key) {
return self::getInstance()->_get($key);
}
public static function set($key, $object) {
return self::getInstance()->_set($key, $object);
}
}
?>
Using this realization is really easy...
<?
Registry::set('db', $db_client);
Registry::set('redis', $redis_client);
//Using registered objects is really easy
Registry::get('db')->query("...");
Registry::get('redis')->get("...");
?>
But as you can see, we're adding instances into registry even if we don't need them (yes, it's all about performance).
So, the question is... How to modify Registry pattern to be able to do lazy instantiation?
Here is what I'm looking for...
<?
class Registry
{
private static $objects = array();
private static $instance = null;
public static function getInstance() {
if (self::$instance == null) {
self::$instance = new Registry();
}
return self::$instance;
}
protected function _db() {
if (!$this->objects['db']) {
$this->objects['db'] = new DatabaseAdapter(DB_HOST, DB_NAME, DB_USER, DB_PASSWORD);
}
return $this->objects['db'];
}
protected function _redis() {
if (!$this->objects['redis']) {
$this->objects['redis'] = new Redis(REDIS_HOST, REDIS_DB, REDIS_USER, REDIS_PASSWORD);
}
return $this->objects['redis'];
}
public static function db() {
return self::getInstance()->_db();
}
public static function redis() {
return self::getInstance()->_redis();
}
}
?>
As you can see, DatabaseAdapter() or Redis() will be created only in we'll request them. Everything seems to be ok, but as you can see it's not a standalone class because _db(), _redis() methods contains connection constants etc.
How to avoid it? How can I define registry method within registry class to separate Registy class and objects inside it?
I'm really sorry about my English, but I hope it is clear for you.
Thank you.
PS: All code above was written 1 min. ago and wasn't tested.
If you use global constants you will always have a dependency on the global scope. It doesnt matter where it is. Also, even if you do not use constants, you still have the dependency on the Database class inside the Registry. If you want to dissolve those dependencies, you could use Factory methods on the to be created classes:
public function get($service)
{
if( !this->_data[$service] ) {
// requires PHP 5.2.3
this->_data[$service] = call_user_func($service .'::create');
}
return this->_data[$service];
}
So if you do get('DB'), the code would try to call the static DB::create() method inside the class you intend to create. But like I said, if you use global Constants for the configuration, you would just move the problem into another class.
Your db class could look like this:
class DB
{
protected static $_config;
public static setConfig(array $config)
{
self::_config = $config;
}
public static create()
{
return new self(
self::config['host'],
self::config['db'],
self::config['user'],
self::config['pass']);
}
}
The configuration can be stored inside an external configuration file, which you load and set to the DB class during bootstrap, e.g.
DB::setConfig(parse_ini_file('/path/to/db-config.ini'));
The disadvantage of this is, you have to add create() methods all over the place and all classes must be able to store their own configuration. You could centralize these responsibilities into a Builder pattern. But if you do this, you are half way to implementing an IoC Container anyways, so check out the following resources:
Fabien Potencier: What is Dependency Injection
Martin Fowler: Inversion of Control Containers and the Dependency Injection pattern
Design pattern – Inversion of control and Dependency injection
Note: You are using a "static" modifier for $objects - as you are working with an instance, this is probaby not necessary.
How can I define registry method within registry class to separate Registy class and objects inside it?
They are always separate: Each object inside the registry class is just a reference to the (independent) object. But if this question is about including the appropriate class definition (?) you may use the class_exists() function to load the class as soon as required.
BurninLeo
I have always used a Singleton class for a registry object in PHP. As all Singleton classes I think the main method looks like this:
class registry
{
public static function singleton()
{
if( !isset( self::$instance ) )
{
self::$instance = new registry();
}
return self::$instance;
}
public function doSomething()
{
echo 'something';
}
}
So whenever I need something of the registry class I use a function like this:
registry::singleton()->doSomethine();
Now I do not understand what the difference is between creating just a normal static function. Will it create a new object if I just use a normal static class.
class registry
{
public static function doSomething()
{
echo 'something';
}
}
Now I can just use:
registry::doSomethine();
Can someone explain to me what the function is of the singleton class. I really do not understand this.
A static function is a function that can be called without creating an object of a class.
registry::doSomething()
A Singleton is a design pattern, that should prevent the users of the class from creating more than one instance of a class. So, there is usually only one instance of a singleton class. A Singleton's constructor should be declared private and have a static method providing a single instance-object:
class Singleton
{
private Singleton()
{
}
private static var $instance = null;
public static getInstance()
{
if(self::$instance == null)
self::$instance = new Singleton();
return self::$instance;
}
}
For more information see http://en.wikipedia.org/wiki/Singleton_pattern
P.S: Sorry for my bad PHP, the syntax may not be 100% correct, but you should roughly understand what I mean in terms of OOP.
The fact that the Singleton is a design-pattern that restricts instantiation of a class to one single object, it is possible to do some stuff that is slightly more difficult with a static class:
Lazy initialization
Replace implementation internally by sub-classing the Factory
Manage via configuration
However, there are several drawbacks to singletons, so it is better in general to use patterns such as Factory as you get additional benefits such as decoupling.
UPDATE: Rephrasing the question to ask, 'are there too many' static methods (I realize that right now there are only 4 but I originally started with 2) in this class structure? If so, any suggestions on how to refactor these classes to use some sort of Finder class so that I can remove the static functions from the Model classes?
I have the following abstract class:
abstract class LP_Model_Abstract
{
protected static $_collectionClass = 'LP_Model_Collection';
protected $_row = null;
protected $_data = array();
public function __construct($row = null)
{
$this->_row = $row;
}
public function __get($key)
{
if(method_exists($this, '_get' . ucfirst($key)))
{
$method = '_get' . ucfirst($key);
return $this->$method();
}
elseif(isset($this->_row->$key))
{
return $this->_row->$key;
}
else
{
foreach($this->_data as $gateway)
{
if(isset($gateway->$key))
{
return $gateway->$key;
}
}
}
}
public function __set($key, $val)
{
if(method_exists($this, '_set' . ucfirst($key)))
{
$method = '_set' . ucfirst($key);
return $this->$method($val);
}
elseif(isset($this->_row->$key))
{
$this->_row->$key = $val;
return $this->_row->$key;
}
else
{
foreach($this->_data as $gateway)
{
if(isset($this->_data[$gateway]->$key))
{
$this->_data[$gateway]->$key = $val;
return $this->_data[$gateway]->$key;
}
}
}
}
public function __isset($key)
{
return isset($this->_row->$key);
}
public function save()
{
$this->_row->save();
}
abstract public static function get($params);
abstract public static function getCollection($params = null);
abstract public static function create($params);
}
And then this class which provides additional functionality for class table inheritance schemes (where type is important in determining additional functionality in a factory fashion):
abstract class LP_Model_Factory_Abstract extends LP_Model_Abstract
{
protected static $_collectionClass = 'LP_Model_Collection_Factory';
abstract public static function factory($row);
}
These ultimately result in the following type of class declaration:
class Model_Artifact extends LP_Model_Factory_Abstract
{
protected static $_artifactGateway = 'Model_Table_Artifact';
public static function create($params)
{
}
public static function get($params)
{
$gateway = new self::$_artifactGateway();
$row = $gateway->fetchArtifact($params);
return self::factory($row);
}
public static function getCollection($params = null)
{
$gateway = new self::$_artifactGateway();
$rowset = $gateway->fetchArtifacts($params);
$data = array(
'data' => $rowset,
'modelClass' => __CLASS__
);
return new self::$_collectionClass($data);
}
public static function factory($row)
{
$class = 'Model_Artifact_' . $row->fileType;
}
}
When do you know that you have too many static methods in a class? And how would you refactor the existing design so that the static methods are perhaps encapsulated in some sort of Finder class?
I'd have to agree with Brubaker and add that to my thinking it isn't the number of methods so much as the functionality of said methods. If you start thinking that your class has to many methods (static or otherwise) then you might find they can be re-grouped and refactored into a more intuitive architecture.
The first indicator I use when determining if I have to many static methods is if the methods functionality is not stateless. If the static methods change the state of the object they reside in, they probably shouldn't be static.
I agree with BaileyP and I'll add my couple of pennies:
I always work with the idea that a class should have a single reason for existing; it should have one job that it does, and it should do it well. After deciding that, and figuring out what the interface to that class should be, I go through and mark any functions that don't change the state of an instance of the class as static.
If you want to build reusable and testable code, you should avoid static methods altogether. Code which calls static methods (or constructors of non-data-like classes) cannot be tested in isolation.
Yes, you will have to pass around alot more objects if you eliminate static methods. This is not necessarily a bad thing. It forces you to think about the boundaries and cooperation between your components in a disciplined way.
Personally I find that any number of static methods are a sign of trouble. If your class has instance methods and static methods, then most likely you could split the class into two separate entities and change the static methods to instance methods.
Think of a class as a special kind of object, with the distinctive property that it is global by nature. Since it's a global variable, it implies a very strong level of coupling, so you would want to reduce any references to it. Static members will need to be referred, meaning that your code will get a strong level of coupling to the class.
I'll throw in my 2 cents.
First of all, I'll agree that setting some sort of arbitrary limit is not helpful, such as "Once I have more than 10 statics in a class that's too many!". Refactor when it makes sense but don't start doing it just because you've hit some imaginary boundary.
I wouldn't 100% agree with Brubaker's comment about stateful vs. stateless - I think the issue is more about classes vs instances. Because a static method can change the value of another static property which is a stateful change.
So, think of it like this - if the method/property is of or pertaining to the class, then it should probably be static. If the method/property is of or pertaining to an instance of the class, it should not be static.