I am writing a Proxy class in PHP.
To do so, I am using magic method to catch calls/get/set... to the proxied instance, and forward them to that instance.
However, I am unsure what to do in this situation:
class Proxy {
// Proxied object
private $instance;
// ...
function __destruct() {
// unset($this->instance); ?
// $this->instance->__destruct(); ?
// nothing ?
}
}
Should I (can I) call the destructor explicitly? Or should I just unset the object, knowing it won't really destroy it for sure (at least, immediately)?
Or should I just do nothing and wait for the garbage collector to destroy the instance?
Don't do anything. It'll be taken care of by the garbage collector, probably at around the same time as the proxy.
I highly suggest that you do not free the instance class when the proxy dies. I'm not sure how you do things in your codebase, but it is possible something will still hold a reference to your instance class. Safer to let GC take care of it. Destructors are rarely useful in PHP.
Related
The project I'm working on requires me to have some objects, including an event manager, (read-only) configuration manager and plugin manager, that are available everywhere in the system.
I was using global variables for these, until someone (with a C++ background) kindly pointed out that "You're probably doing something wrong if you need global variables".
He suggested using a state object that's passed to all functions that need it.
So I did:
$state = new State();
$state->register('eventManager' , new EventManager());
$state->register('configManager', new ConfigManager());
$state->register('cacheManager' , new CacheManager());
$state->register('pluginManager', new PluginManager());
$state->get('pluginManager')->initialize($state);
While I can see the benefit of this method in more stateful languages, it seems kind of pointless to me in a (mostly?) stateless language like PHP, where the state is lost after the page is done loading.
Is there any benefit to passing a state object around in a (mostly) stateless language like PHP, does it hold any benefits over other approaches (i.e. a globals-based system) and are there better ways to handle this?
The registry that you propose is still a global variable. And if you want to access a global variable (even if it is an object, although a global one), you are doing something wrong.
A proper application only has on phase where global state plays a role: When bootstrapping it. The request starting the script is global, any request data sent with it is global, and any configuration that affects the application and is stored in a file or some other appropriate storage is global.
The first phase should initialize some dependency injection that puts all the parts that make up the application together. That object graph would be created on demand when the processing of the request has decided which part of the code should be called to respond to the request.
Usually this decision is done inside a framework processing the request, and the dependency injection likely will be also done via a framework. Your own code would only accept either the values needed to operate, or the other objects that are needed.
For example, if your code would need a database, then you'd configure the database object to accept the URL and credentials for your database, and then you'd configure your reader object to accept that database object.
It would be the task of the dependency injection to either create only one single database object, or multiple of them. You don't have to use the outdated "singleton antipattern" because it has many drawbacks.
So in this scenario, there are some objects existing in the dependency injection part that are only created once and injected when needed. These objects do not enforce to be only created once, and they are not stored inside a globally accessible variable. However, something has to live in a global variable, but this is only the main framework object and probably the dependency injection container, and they are never shared into the remaining code as a global variable - so this is not harmful at all.
One way to do this is with singletons:
class ConfigManager {
private static $instance = NULL;
public static function getInstance(){
if(self::$instance === NULL) {
self::$instance = new ConfigManager();
}
return self::$instance;
}
private function __construct(){
// Notice that this is private - only getInstance() can call this.
}
}
// When you need it:
$config = ConfigManager::getInstance();
There are many different opinions on how to do what you're asking - and I myself don't think singletons are always the best way to do this, either. It really depends on your use-case.
That said, singletons are just one common pattern for a class whose instance is supposed to be accessible everywhere.
I guess this might be a silly question, but I cant wrap my head over it.
So I have some code which looks like so:
$process = new ProcessTree();
$process->start();
and the class processTree is:
class ProcessTree()
{
public function __construct()
{} //dummy constructor...
}
public function start()
{
$this->init();
$this->doThis();
$this->doThat();
//etc...
}
So I guess my question is about the dummy constructor. According to good design, should the constructor not do something? Or even, shouldn't the body of start() be inside __construct() instead?
You don't need to use constructor if you don't really need it. I don't think it's a best practice just to put an empty constructor.
You should also don't move code from start() to constructor. Constructor should only help to initialize object (for example set some properties) and if you want to do some actions you should simple run those methods or create wrapper method (as you did) to run multiple methods at once.
Of course we don't know what you do in init(), doThis() and doThat() methods. If they do actions that are always necessary to use other object's method, you can move them into contructor, but as I said we don't know what's code in them.
In general the constructor should not do "too much" because that would violate the Single Responsibility Principle: the constructor's responsibility is to prepare the object for use, so that's its actions should be limited to.
Of course there will be exceptions to all kinds of rules. For example, the constructor of PDO initializes a database connection, which it's not really required to do. But in the context of PDO this makes sense because:
You will always want to make that connection (and sooner rather than later)
There is always a real possibility that the connection will not be successful (so by having the constructor connect and throw on failure you can check for this conveniently)
If the PDO constructor didn't connect or throw then all the other methods would have to be ready to do the same. But PDO's error reporting strategy can be switched to return codes; in this scenario you would be forced to sprinkle "connection failed" logic throughout the code. That would be a really unfortunate outcome, but it's prevented once and for all by connecting in the constructor.
But as a rule of thumb, whenever in doubt don't go off doing things in the constructor.
Is there some assurance when __destruct is called, when considering simple objects without reference cycles? I know from java, that it is not defined when and if the function finalize is called, it depends on the garbage collector.
For example if you have a function like:
1 function test(){
2 $x = new SomeObject();
3 $y = new SomeObject();
4 $x = null;
5 }
Where SomeObject has no reference cycles.
Can you assume $x->__destruct is called at line 4 and $y->__destruct is called at line 5?
Testing the following script seems to indicate that this is true:
https://gist.github.com/KAYLukas/0b1d65e57b52862f8da5
Furthermore, SplFileObject seems to work on this predicate: it is impossible to close the file, instead you just need to set the variable to null. If this would not call __destruct directly it would be impossible to open the file reliable after it has been opened with SplFileObject.
I have found that there is an assurance that the __destruct will be called eventually, just not when.
Yes, you can assume that.
__destruct is always called at the moment where the last reference to the object disappears: when you can't access that object anymore in any way from the outside.
If there exist circular references, you need to wait until it circular garbage collector comes in, where it isn't defined at what point that happens.
If you have stored the object somewhere else too, you need to first remove it from there before the destructor is called.
For further information: Internal objects don't always destruct their resources upon __destruct (as the user might call it directly), but only when the object really is destroyed. (technical measure to prevent segfaults)
Also during shutdown, first variables and arrays are removed in the reverse order they were defined and where the last reference to an object disappears the object is destroyed. Then circular garbage collector comes in and removes the other objects and calls __destruct there.
The only thing which is undefined here, is the order in which the circular garbage collector removes objects and calls their __destruct function.
I have been wondering for a while already how does static variables work regarding memory use and should that even be really considered?
I understand that static variables will only use up one area of memory, doesn't matter how many instances there are of the class itself. So in this sense, it should be wise to use static variables for wise memory consumption too, right? But I've never stumbled across anyone talking about the memory usage of static variables (only that you can share the data with different instances).
For example:
class Something () {
static $DB = null;
__construct ($DB) {
$this->DB = $DB;
}
}
If I would create 10 instances of this class, then it would generate less memory usage, than with non-static $DB-variable, right?
And if it is so, is the effect so small, it doesn't really matter?
and should that even be really considered?
No you shouldn't worry about statics for that reason.
The reason you have to worry about the use of static is the fact that you cannot unit test your code anymore and you have tightly coupled classes and code to Something::DB (i.e. the Something class) and you are working with global state.
Also check out an previous answer by me about how to handle those "global" instances: Which is the best practice to access config inside a function?
In your case, please, rethink your software design. In case of using static variables - you are trying (if its not, so why you need static?) to make something accessible from one place, without recreating it, like using Singleton pattern for making single instance of db object.
But if we are talking about memory usage, so yes, if you will create more objects, so you duplicating the variables - it will take more memory, but there are no real change in memory usage about its static or not.
Yes, a static attribute of a class would be stored in a single instance of memory.
But, that is not a concern in making a decision in having a variable as static. They are used for class level information such as to keep a count of the instances of a class.
Go through the following Stackoverflow post on when to use static variables:
When do I use static variables/functions in php?
You should use
self::$DB
to access static variables (as $this has no meaning in a class wide context)
Should use static for something that all objects of that class share.
You should not use parameters from the constructor to create static variables. Doing so the static variable gets overwritten when you create a new object of that type
I've been trying to learn the object oriented side of PHP, and was wondering:
If I used a _constructor to open a connection to a database, used a function within that class (eg. insert), would the defined __destructor close the connection after the method "insert" is executed?
class data(){
function __constructor {
// connect to db
}
function insert($data){
// mysql_query(...)
}
function __destructor {
// close connection to db
}
}
$obj = new db();
$obj->insert('mumbo jumbo');
Or would the connection to the database still be open?
Cause I read that the destructor is only run if the object is destroyed. But how do you destroy an object?
In PHP, an object is destroyed when it goes out of scope. This is normally when the script stops executing or when the function it was created within ends, but you can destroy an object early in your code using:
unset($my_variable);
So, to answer your question, you should be fine allowing the destructor to handle closing the DB for you in most situations, especially with small scripts.
Yes, that will work fine, as long as you use the correct names, __construct() and __destruct(), for your constructors and destructors, as opposed to what you have there.
The object is destroyed once there is no more reference to it, for example by unset()-ting the last variable holding the object or when the script execution terminates.
By the way, the magic methods are named __construct and __destruct, without the trailing -or.
BTW, the constructors and destructors are called __construct and __destruct.
__destructor would be called when there are no more references to the the db. Typically, this occurs when the object goes out of scope, but if you have saved other references to it, this won't happen. You can remove references to the db using
unset($obj);
and likewise if you have stored $obj anywhere.
Keep in mind that PHP also supports persistent connections to databases, which means that even if your object has been destroyed, the connection to DB is still open "in the background" and will be reused when you call the correspondending pconnect (or PDO analogue) the next time.