I'm a bit lost here because I want to do something that is very easy in Java but seems a bit complicated in PHP.
We are building an SDK for our product and in Java, we have this one class that must not (!) be instantiated by the user (i.e. the coder), since there are several constraints regarding it's integrity. So we've built that as a nested class "X" inside of the "XFactory" and you will get an instance of X by calling XFactory.buildMeMyX(); - Easy...
Now PHP does not support nested classes at all, and I wonder how to apply the same here. In Java, X's constructor is hidden (private), so only XFactory can call it.
In PHP, it looks like I will have to make __construct() public and move the nested class X out of XFactory. Hence, the user will be able to create an instance without the Factory.
Now - I COULD move the factory functionality to X itself and move all the stuff there, but this would kind of break the design of the SDK. Is there a useful way to do such things in PHP after all?
For PHP 5.x you already described your options, there are no private/protected classes or inner classes at all, so there is no further way to restrict instantiation.
However, with PHP 7 this is going to change.
There are still no nested classes (although we might get them in the future, see: https://stackoverflow.com/a/31454435/664108), but you could instantiate an anonymous class and only provide the consumer with its interface like this:
class XFactory
{
public function buildMeMyX()
{
return new class() implements XInterface {
public function doWhatEverAnXCanDo()
{
// X X X
}
// ...
};
}
}
interface XInterface
{
function doWhatEverAnXCanDo();
}
As the others have said, there currently is no clean way to implement this behavior in PHP. In my opinion, the only valid use case for private constructors are factories inside the class that implement that factories.
Whenever you try to get around that use case it gets messy. No one should ever try to invent clever ways to bypass PHP's language limiations.
I just violated that rule by myself just to prove it is indeed possible. But please refrain from using that in production, or better: using it anywhere. I will try to find some bulletproof arguments for that suggestion and edit the answer afterwards.
<?php
class Dependency {}
class SomeClass {
protected $dep;
private function __construct(Dependency $dep)
{
$this->dep = $dep;
}
public function doSomething()
{
var_dump($this->dep);
echo "Doing Stuff and even having dependencies";
}
}
class SomeClassFactory {
public function buildSomeClass()
{
return $this->instantiateSomeClassWith(new Dependency);
}
protected function instantiateSomeClassWith()
{
$reflectionClass = new ReflectionClass('SomeClass');
$someClass = $reflectionClass->newInstanceWithoutConstructor();
$constructor = $reflectionClass->getConstructor();
$constructorClosure = $constructor->getClosure($someClass);
call_user_func_array($constructorClosure, func_get_args());
return $someClass;
}
}
$factory = new SomeClassFactory();
$someClass = $factory->buildSomeClass();
$someClass->doSomething();
?>
Output: object(Dependency)#2 (0) { } Doing Stuff and even having dependencies
The theory is simple. The constructor of the class that will be built via the Factory is made private. We make use of reflection within the factory to create an instance of the class without invoking the constructor.
Once we have an instance, we grab the closure of the constructor and invoke it via call_user_func_array(). That way you can make use of Dependency Injection just as you would if the constructor was public.
As I said before. That way is a single smell. By creating an object without invoking it's constructor, there is no real way to validate an objects state upon creation
This is a proof of concept, but the concept sucks.
There is no native way to do so, yet. However, if you really want to "enforce" that your class is only created from your factory class, there is a little "hackish" way to do so limiting the instantiation by inistantiating class.
class X
{
function __construct()
{
new Y();
}
}
class Y
{
function __construct()
{
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
if (!isset($trace[1]['object']) || !($trace[1]['object'] instanceof X)) {
throw new \RuntimeException('This is a private class');
}
}
}
new X(); // All is fine
new Y(); // Exception
Please note that there is no "real" way to protect the class from being instantiated from elsewhere even using this approach - it still can be done via reflection by bypassing the constructor, or simply modifying your source.
Related
I want to disable a class to be instantized by new operator, but lets suppose a getObject method what creates and returns an instance of it. Is it doable?
class C
{
protected function __construct()
{
}
public static function getObject()
{
return new self();
}
}
UPDATE:
The code above fulfills the requirement: the class cannot be instantiated using new, one needs to use the factory method getObject() to create an object. However, the OP did not specify the reason they need such a construct.
There are several reasons such a design emerges; one of them is when the creation of objects of type C needs to be completed with some initialization that, for whatever reason, cannot be done in the class' constructor.
Another reason for this way of constructing objects of class C is the Singleton design pattern; which in fact is an "anti-pattern", but this is another discussion; in order to implement a Singleton, class C should look like this:
class C
{
private static $instance = NULL;
protected function __construct()
{
}
public static function getObject()
{
if (! isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
Singleton or not, because method getObject() is static it cannot be stubbed or mocked by the test frameworks and its original implementation have to be used. More, because it is the only way to create objects of class C, other classes that use this class cannot be tested in isolation.
All in all, even the construction is possible, it is not recommended. Enforcing the creation of objects of class C using language mechanisms made the class a nuisance for testing other classes that use it.
If the creation of objects of class C needs to be done by a certain method because of its complex initialization, a better way is use the Builder design pattern. Make it a non-static method of another class (the "builder") and instruct the programmers (using the class documentation) to not create objects of class C directly, using new. This way it does not affect the testability of other classes.
I want to disable a class to be instantized by new operator
A common approach is to privatize the constructor.
class Example {
private function __construct() {
}
}
The following would result in a fatal error.
$object = new Example();
While this will work, I would encourage you, and future readers, to review Design Patterns in PHP.
I am trying to develop an object oriented PHP application in which whole php application will be extending from MyApplicationBase base class. But the problems is I want to create only single instance of MyApplicationBase. Below is the code which explains what I mean
class MyApplicationBase{
static $called=0;
public var $db;
function __construct()
{
self::$called++;
echo "<pre>MyApplicationBase Created ".self::$called." times</pre>";
$this->db=new DatabaseWrapper();
}
}
class ApplicationSecurity extends MyApplicationBase{
function is_logged_in()
{
$res=$this->db->query("user check db query goes here");
return ($res)?true:false;
}
//..... other methods related to ApplicationSecurity class
}
class ApplicationBusinessLogic extends MyApplicationBase{
// business logic methods here which may use base class vars like $db
// this may also use instance of ApplicationSecurity class
}
class ApplicationTemplating extends MyApplicationBase{
protected function outputHeader()
{
require_once('path/to/themes/header.php');
}
protected function outputSidebar()
{
require_once('path/to/themes/siderbar.php');
}
protected function outputMainbody()
{
require_once('path/to/themes/mainbody.php');
$app=new ApplicationBusinessLogic();
$app->initiate();
}
protected function outputFooter()
{
require_once('path/to/themes/footer.php');
}
public function outputTemplate()
{
$this->outputHeader();
$this->outputSidebar();
$this->outputMainbody();
$this->outputFooter();
}
}
//index.php file code starts here--------
$myPhpApplication = new ApplicationTemplating();
$myPhpApplication->outputTemplate();
My goal is when I create instance of my application then It only call the single instance of "MyApplicationBase" class instead of calling it multiple times. Please do tell me how can I achieve this. I am google for 5 hours but unable to find any solution yet.
I am trying to develop an object oriented PHP application in which whole php application will be extending from MyApplicationBase base class.
As PHP has single inheritance, this is by far the most worst idea to do object oriented PHP programming.
But the problems is I want to create only single instance of MyApplicationBase.
As every class is a MyApplicationBase you actually don't want that because it would mean you could instantiate exactly one class in your whole application.
What you're probably looking for is some kind of ApplicationClass which you pass along and of which just a single instance exists.
This would at least allow you in the future to throw such a "block in road" away more easily then if you would have got extended from there.
In any case you should program against an ApplicationInterface instead of an ApplicationClass to make this throwing away - as it will be necessary - easier.
The best thing for sure would be to not do anything in that direction and only write code you need in the first place.
To only write code you need, you need to develop test-driven. Why not start with that if you want to do object oriented programming?
Well I suppose that you want to avoid multiple connections to the database in this case. Solution is simple with Dependency injection, just initialize your database connection outside of MyApplicationBase class and then pass it as a constructor parameter (beware of constuctor hell though). Like this:
class MyApplicationBase{
static $called=0;
public $db;
function __construct($db)
{
self::$called++;
echo "<pre>MyApplicationBase Created ".self::$called." times</pre>";
$this->db= $d;
}
}
$db = new DatabaseWrapper();
$templating = new ApplicationTemplating($db);
$security = new ApplicationSecurity($db);
You could also take a look at some framework, they usually come with some dependency injection capabilities.
Not sure if my title is correct cause I am not even sure I am using the correct terms.
I have a class that has a property that is an object. When setting this property the object has to be created. My question is how do I do this without tight coupling?
Example:
class A
{
protected $_depending;
protected $_somePropertyObject;
public function __construct(\Lib\Dependency $depending)
{
$this->_setDepending($depending);
}
protected function _setDepending(\Lib\Dependency $depending)
{
$this->_depending = $depending;
}
public function setSomeProperty($someProperty)
{
// I want to prevent this
$this->_somePropertyObject = new \Lib\some\Object($someProperty);
}
}
I could just pass the required object through the construct but what happens more are needed?
When if I understand correctly the factory pattern, what would this change? I would still need to create the object somewhere? Not the object itself but the factory. Again tight coupling? Seems endless to me. When re factoring class(es) it however is isolated where and how the class(es) are made.
If I set the setSomeProperty function to only accept \Lib\some\Object then is still needs to be created by the parent object that is passing it to begin with. Seems only to shift the placement of where it is created?
Hopefully I am clear enough in what I am trying to ask.
Thanks in advance!
EDIT What I am asking is the sequence of what is created when,where,why.
The purpose of a factory in dependency injection patterns is to produce instances for another instance, without that other instance needing to know how to produce it.
At its core, a "factory" is just an object-returner: something that returns an instance when invoked.
This is easier to see in more capable languages. For example in Python classes are callable (there is no new operator), and invoking a class produces an instance of the class. So classes can be their own factories if the class requires no arguments. Likewise any zero-argument function that returns an instance can be considered a factory. This makes dependency injection very clear and free-of-boilerplate.
In more rigid languages (Java/C++/C# static-typed tradition, or where classes or functions are not completely first-class like in PHP), you need to obscure dependency injection behind a "pattern", because "design patterns" are missing language features. In PHP 5.3+ you can use a closure as a factory, or you can go the Java/C# way and define a FactoryInterface and a new class per factory.
For example, with your class, you could do this:
class Aprime extends A
{
public function setSomeProperty($somePropertyFactory)
{
$this->_somePropertyObject = $somePropertyFactory();
}
}
In this class, setSomeProperty requires a zero-argument callable "factory", which you could produce like this:
$other_dep_factory = function(){ return new SomeOtherClass(); };
Or like this:
class ClassFactory {
function __construct($classname, $args=array()) {
$this->class = new ReflectionClass($classname);
$this->args = $args;
}
function __invoke() {
return $this->class->newInstanceArgs($this->args);
}
}
$other_dep_factory = new ClassFactory('SomeOtherClass');
Prior to PHP 5.3, you need to do it like Java would:
interface IObjectFactory {
function getObject();
}
// this B-and-D interface is optional
// it has no body because PHP doesn't support
// type-hinting return values
interface ISomeOtherClassFactory {}
class SomeOtherClassFactory implements ISomeOtherClassFactory {
function getObject() {
return new SomeOtherClass();
}
}
class Aprime extends A
{
public function setSomeProperty(ISomeOtherClassFactory $somePropertyFactory)
{
$this->_somePropertyObject = $somePropertyFactory->getObject();
}
}
$other_dep_factory = new SomeOtherClassFactory();
$myAprimeObject->setSomeProperty($other_dep_factory);
So when do you use a factory? Whenever an object needs to create another object. If the object just needs to use another object, just pass in an instance.
I like to use the Factory Pattern when you need to collect "information" to create the object that's stored in $_somePropertyObject. For instance let's say you have to assign values to some properties to instantiate it or run a couple of methods right after you instantiate it.
Also, you'll want to consider whether you might need to later change the inheritance tree. If you might be assigning $_somePropertyObject a \Lib\some\Object now, you might find yourself wishing you could easily swap it out for a \Lib\some\FancyObject later. If you use Dependency Injection, you can easily swap subtypes.
Here's a primer: http://net.tutsplus.com/tutorials/php/the-whens-and-whys-for-php-design-patterns/
Also, too: https://stackoverflow.com/a/2083455/1121827
I've recently read that using the keyword "new" in a constructor is highly frowned upon, but I'm not sure I understand why? For example, how is:
class A {
public $foo;
function __construct() {
$this->foo = new Bar();
}
}
Any different from:
class A {
public function someMethod() {
$foo = new Bar();
}
}
???
This is really the theory behind dependency injection.
It's not that using "new" is a bad idea, per se. Rather, by instantiating objects inside of your class your are creating hard dependencies which can never be changed or switched out without changing the class itself.
It also violates the paradigm of "coding to interface, not implementation"
Example:
class Phone {
protected $network;
public function __construct() {
$this->network = new Verizon();
$this->network->distinctiveRing();
}
}
class Verizon {
public function call($number) {
....
}
public function distinctiveRing() {
}
}
Now, suppose one day you wanted to create an ATT, TMobile and Sprint phone? Surely they are all able to make calls, and can do so having just a phone number. Also, the phone class shouldn't care who the carrier is, as it's job is to facilitate entering a number - not to actually make a network connection, right?
So, that being said, we shouldn't have to create a new SprintPhone class that can instantiate another Sprint network object, right? Right.
So what's the better way?
class Phone {
protected $network;
public function __construct(NetworkInterface $network) {
$this->network = $network;
}
}
interface NetworkInterface {
public function call($number);
}
class Verizon implements NetworkInterface {
...
}
class Sprint implements NetworkInterface {
...
}
Well now, you can just say: $phone = new Phone(new Sprint()) or $phone = new Phone(new Verizon())
Also notice that our call to distinctiveRing is gone. Why? Well, because we don't know that any object implementing NetworkInterface will necessarily support a distinctive ring. But this is good because now our Phone can support ANY Network with no code changes.
If you want support for distinctive ring, you can always create a new interface that supports the distinctiveRing method. In your Phone object, you can check if your Network implements DistinctiveRingerInterface and, if so, make your distinctive ring. But you're no longer tied to a specific network with this approach. Better yet, you were forced to do this because you took the right approach from the start.
And, any other network which can feasibly be created later down the road. More importantly, your class no longer has to care about what kind of Network object it's given. It knows, (because it received an object implementing NetworkInterface), that the Network object is able to make a call with a $number.
This also tends to lead to much better code, with a better separation of concerns.
And finally: testing.
With the first example, if you tried to test your Phone object, it was going to make a call on the Verizon network. Sucks to be the person getting called all day because you're running unit tests, right? Right.
Well, simply create a TestNetwork class that implements NetworkInterface, and pass that to your phone object. Your TestNetwork class can do anything you want inside of it's call method - or do nothing.
Furthermore, you can just create a mock object using PHPUnit, and ensure that the call method on your TestNetwork actually gets called. You couldn't do this before because the Network was being instantiated inside of your Phone.
It seems that your question and your code example do not share too much?
Your first code sample should work, because you assign to a class variable:
class A {
public $foo;
function __construct() {
$this->foo = new Bar();
}
}
Your second sample assigns it to a variable local to the __construct() method, so you will have no chance of retrieving the value later on:
class A {
public function someMethod() {
$foo = new Bar();
}
}
Besides: Using new is usually fine. However, you might have read about inversion of control or IOC which is a technique to avoid having dependencies and so you would try to avoid the creation of classes directly in the constructor, see for example http://ralphschindler.com/2011/05/18/learning-about-dependency-injection-and-php
In first example $foo is available in any method in this class and also outside the object
so you can do:
$a = new A();
$a->foo->sth;
In second example $foo is available only inside someMethod.
For dependency injection, I understand that I have to pass an instance of one class to the main instance instead of the main class creating it's own instance, like so (php):
class Class_One {
protected $_other;
public function setOtherClass( An_Interface $other_class ) {
$this->_other_class = $other_class;
}
public function doWhateverYouHaveToDoWithTheOtherClass() {
$this->_other_class->doYourThing();
}
}
interface An_Interface {
public function doYourThing();
}
class Class_Two implements An_Interface {
public function doYourThing() { }
}
class Class_Three implements An_Interface {
public function doYourThing() { }
}
// Implementation:
$class_one = new Class_One();
$class_two = new Class_Two();
$class_three = new Class_Three();
$class_one->setOtherClass( $class_two );
$class_one->doWhateverYouHaveToDoWithTheOtherClass();
$class_one->setOtherClass( $class_three );
$class_one->doWhateverYouHaveToDoWithTheOtherClass();
This is all fine. I know that since both Class_Two and Class_Three both implement An_Interface, they can be used interchangeably in Class_One. Class_One wouldn't know the difference between them.
My question is, is it ever a good idea to, instead of passing an instance to setOtherClass, pass a string such as "Class_Two", and have Class_One's setOtherClass method actually create the instance itself like so:
class Class_One {
...
public function setOtherClass( $other_class_name ) {
$this->_other_class = new $other_class_name();
}
...
}
Does this sort of defeat the purpose of Dependency Injection, or is this completely valid? I thought this type of set up may help me with configuration, where a user can specify which class he wants to use in a string earlier on and this can later be passed to the Class_One..
Actually, writing this out has made me think that it's probably not a good solution, but I'll still post this in case someone can give me some good feedback on why I should/shouldn't do this.
Thanks =)
Ryan
That theoretically defeats the purpose of dependency injection; you are telling Class_One, which depends on An_Interface, which concrete implementation of that interface it should instantiate. That requires Class_One to know how to instantiate ANY An_Interface implementation, tightly coupling Class_One to ALL An_Interface implementations. If you add a new An_Interface Class_Four, you have to go back and tell Class_One how to instantiate a Class_Four.
In PHP, you get away with this AS LONG AS all An_Interface implementations have a parameterless constructor. However, if any implementation needs OTHER dependencies injected, you're screwed; you can't tell Class_One to just new up a Class_Four if a Class_Four needs a Class_Five that Class_One doesn't know about.
Pass an object that's specified by an interface. Otherwise how will you always know with 100% accuracy what it will take to construct the object?
public function __construct(MyInterface $object) {
}
That way, it doesn't matter how you create the object, you just need to know if you can use it how you need to (the interface you're programming against)...
Either way is technically equivalent IMO. The main test to tell if you are doing dependency injection right is to see if you are using any constant strings with "new" or with static method calls. Your code looks good, as long as in the implementation section, the classes can be changed via configuration or some other mechanism. The only downside with passing a string name of a class is that you can't be sure that it implements an specific interface or extends some other object. The checking for this could get messy. However, if your application can handle this issue gracefully, then you should be alright. Passing an actual instantiated object though is the best technique.