I have a hard time understanding what SHOULD be done in a PHP class destructor
I'm coming from c++.
In c++, if I have this:
class A{
int n;
~A(){
}
}
class A2{
int* n;
~A2(){
delete n;
}
}
The language KNOWS that if an instance of A is out of scope, its member n should be deallocated, because n only belongs to that very instance.
BUT if an instance of A2 goes out of scope, it doesn't knows if the memory pointed by n should be deallocated (maybe there are other pointers out there pointing towards that same memory)
BUT, if we're sure we want to deallocate that memory IF A2 instance goes out of scope, we need to MANUALLY "delete" it, because its our intention.
What about php?
I'm a newcomer and I've seen several solutions:
class A3{
private $n;
public function __destruct(){
//Choice 1
unset($this->$n);
//Choice 2
delete $this->$n;
//Choice 3
}
}
I'm not sure of the difference between unset and delete, but whatever.
I was told (cf choice 3) that PHP does "by itself" deallocate the memory if we don't do anything.
But I don't then understand the use of delete or unset in the destructor.
We don't have the notion of "pointer" in php, so if an instance of A3 goes out of scope, it's natural to deallocate n.
so, is there anything that SHOULD be done in a destructor? If not, there is never a use of delete or unset in the destructor?
EDIT: rewritten code based on axiac comment
What do you write in the destructor in C++?
You probably write statements that release the resources acquired during the lifetime of the object, isn't it?
This is the same in PHP, but most of the times you don't need to put anything in the destructor because the unused memory and resources are automatically garbage-collected by the interpreter.
It is recommended, however, to release in the destructor the resources acquired in the constructor (or during the lifetime of the object) either to be sure the memory they use is freed earlier or as documentation: somebody that reads a destructor and finds a call to fclose() in it knows that in the constructor or maybe in another method of the class, a pairing call to fopen() was executed and the handler was stored inside the object.
P.S.
The line $n from:
class A3{
$n
public function __deconstruct(){
is incorrect. It should end with a semicolon (;) and if the intention is to declare a property the correct syntax is to start with one of the visibility specifiers (private, protected or public), like this:
class A3 {
private $n;
public function __destruct() {
The name of the destructor method is __destruct() and not __destructor().
There is no delete in PHP: http://php.net/manual/en/function.delete.php.
Your three choices are only one: choice #1 (unset($this->pdo);).
Read more about classes and objects in PHP. Start by forgetting most of what you know from C++ as PHP OOP works in a different way and your knowledge of C++ will probably make more harm than good on learning OOP in PHP.
Related
I would like to believe that I understand the concept of static/early binding vs late/dynamic binding as well as late static binding but I found some conflicting definitions after reading few articles about it.
From my understanding the following:
<?php
class A {
protected $greeting = 'Hello from A';
public function hello() {
echo $this->greeting;
}
}
$obj = new A();
$obj->hello();
is an example of static or early binding which happens at compile time (even though PHP is interpreted language). It is early binding because all information about the class is known & nothing needs to be dynamically figured out, so class & method binding happens at compile time.
Dynamic binding or also known as late binding happens at runtime where class & method binding happens at runtime. If we take the same example as above but use something like inheritance, that would be late or dynamic binding:
<?php
class B extends A {
protected $greeting = 'Hello from B';
}
$obj = new B();
$obj->hello();
so my question is, is my assumption/understanding of static/dynamic binding correct in PHP? I know there is also late static binding which combines static & late binding and makes static properties & methods work with inheritance, so instead of using self:: you would use static:: which would wait for runtime to do the binding.
For reference, these are the articles I've read after having doubts about my own understanding of this concept:
This article states that
Static binding happens when you use the scope resolution operator ::.
but per my understanding that is not always the case, isn't my example above the one without inheritance a version of static binding as well? Static in terms of binding does not necessarily mean static variables.
The following articles are the ones with conflicting information, so this is why I am kind of confused & want to know whether I understand it correctly & if my examples are correct or not. I could not find the original RFC on PHP to get more insight as to how exactly this works.
https://www.codeproject.com/Articles/853792/A-Walk-Through-Into-Late-Static-Binding-in-PHP
https://joshduck.com/blog/2010/03/19/exploring-phps-static-scoping/
https://blog.julien-maury.dev/en/php-late-static-binding/
Which one of these articles is more on point as to how binding really works in PHP?
... is an example of static or early binding which happens at compile time (even though PHP is interpreted language).
You've managed to fit quite a lot of confusion into one sentence here.
Firstly, PHP is a compiled language, it is just compiled "on demand", into a high-level intermediate representation. What's more relevant is that PHP is a highly dynamic language, which doesn't do very much analysis during compilation.
Secondly, the example code you show could be optimised to a known method at compile-time, but it might not be. As far as the language is concerned, the statement $obj->hello(); is evaluated at run-time based on the current value of $obj. The fact that you can see the class to use on the line above, and know that that class has no parents, doesn't mean the compiler will definitely know those things and compile the code differently.
Thirdly, "early" and "static" can't just be used as synonyms - otherwise, the term "late static binding" would mean "late early binding", and make no sense. A "static" call is one that references a particular class; a "non-static" call is one which references an instance.
The important difference from the user's point of view is that given these three lines of code:
$someObject->methodOne();
self::methodTwo();
static::methodThree();
The definition of methodOne used will be whichever class $someObject is an instance of at the time that code runs. It might be a different method each time the line of code runs, if $someObject has a different value. This is late binding.
It will also reference the specific instance in $someObject, placing it in the magic variable $this. It is a non-static call.
The definition of methodTwo used will be the one in the class where that line of code is written. Every time that line of code runs, it will reference the same class. This is early binding.
The definition of methodThree used will depend on how the code was called - if it was called with the name of a child class with its own version of methodThree, that version will be used. Like methodOne, the line might run a different method each time. This is late binding.
Both methodTwo and methodThree will only reference a class, not an instance. They will not populate the magic variable $this. They are static calls.
yes your understanding is correct, because after creating class B and extending it from A, there two different versions of function hello(), which one is called at runtime depends on the type of object(A or B - to be determined by the context) calling it. Another way to look at it is that it is polymorphism.
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
coming from Java, I only have a few vacational visits to PHP. Looking at magic get and set methods, my (Java influenced) tummy starts hurting: It looks as if you were accessing properties directly (although, of course, you are actually are using __get and __set).
So - except for less code you have to write, are there any advantages to using magic getter and setter methods instead of traditional getX()/setX() methods? Should I start using them when coding PHP?
Thanks and best!
The only benefit of __get() is the possibility of less code, but even then it's not necessarily the case. For example, if you have a set of 10 private members and you want the getter to reveal 5, you have to write __get() so that if one of the psuedo-visible members is called, you send it. Otherwise, you either issue an error (that would otherwise come naturally without __get() or return a value such as null that may not actually be helpful.
I must excoriate anyone who suggests using getters and setters in general at all. This usually indicates a problem with architecture. Explain the conceptual difference between the two following code blocks, for instance:
class _ {
public $_;
}
vs.
class _ {
private $_;
public function get_() {
return $this->_;
}
}
There isn't a difference.
However, as many will point out the advantage of having a getter is that this allows you to modify the return value in some way transparently to make it useful for the recipient. However, we come back to architecture problems. You should never have to expose the contents of a class for any reason at all. Instead, you should tell the class to perform an action (which may vary based on its state). Using getters generally lends to querying the class' state and performing an action externally based on the viewed state.
I have essentially the same arguments against __set() and setters, but there is one nice thing that __set() lets you do:
class _ {
private $_ = array();
public function __set($key, $val) {
$this->_[$key] = $val;
}
}
This lets you type the very nice $_obj->key = 'val'. Note that there is not much difference from this and adding another method such as add() that takes the key and value and does the same thing, I just prefer the object setter notation.
__get__ and __set__ are fully dynamic. So for example you can start a database request if they are called to enable lazy loading. Of course, you could do this with getters and setters, too, but then you would have to do this every time. You can also do something like AOP because every property call gets passed through one single method. So all in all __get__/__set__ offer more flexilibility against time they take to process. You can do really advanced/cool stuff with it.
The advantages are that when you're refactoring, direct assignments / reads can be handled without the need to immediately change the complete codebase too, the code can be somewhat shorter, and people can create strings somewhat more easily (for example: $title="<title>{$obj->title}</title>"; vs. $title='<title>'.$obj->getTitle().'</title>';.
However, __get & __set methods can become large and unwieldy fairly quickly, and when coding properly & explicitly, it is in my opinion better to use explicit set/getX() methods to make clear functions are called, and the minor increase of code verbosity is as far as I'm concerned justified as one can easily see what actually calls a function and what doesn't. A possible exception could be when you are building a decorator for another class/object, but that's about it.
there is few difference between getter and setter methods and __set() and __get() methods! these are magic methods!
__set() use when you wanna assign undefined state to a object and so __get() also use to fetch value of undefined state!
setter and getter are used to assign or fetch value of defined states
except for less code you have to write, are there any advantages to using magic getter and setter >methods instead of traditional getX()/setX() methods? Should I start using them when coding PHP?
Given that less code to write it's already a strong reason to start use them.
the other reason is that you can add a common behaviour to all your getter/setter
function __set() {
//> Do some code in common between all setter
//> set your var here
}
When writing getX()/setX() for each attribute, practically speaking, you'll have at a minimum, 7 lines of code. This is assuming that your opening method brace is on the same line as the definition and you only put a single line of code into the method, then you have your closing brace on its own line.
For a non-trivial object, multiply that by 6 (YMMV). That is 42 lines just for attribute access/mutation. That does not include input validation or normalization. For an alternative, check out: https://github.com/metaphp/attributes
There are overheads in dynamic programming (e.g. using magic methods). An old benchmark: Benchmarking magic
As PHP is a dynamic (and not a completely enterprise) language, reducing code lines and missing some nanoseconds seems good idea in many cases (for debugging, scalability, reducing errors and etc).
Basic setup. I have a classA instance which is a subclass of classX ... On construction (or sometime else), I want it to load another class classB which is also a subclass of classX and replace itself with classB in situ. Sort of like a factory, but one that replaces itself transparently. If need be, I can wrap classB with classA if there is a way to (at runtime) change the subclass of an object.
Currently I am using classA::__call() to emulate MRO magic, but is seems very inelegant. This needs to be done transparently to the caller of classA/B so that to the outside world, it isn't aware that classA has replaced itself with classB after construction (or anywhere else for that matter).
I know PHP can be a bit thin when doing things like this ... I am suspecting we can't, but it would be handy for my situation.
Also, 5.3 but ideally (yuck) 5.2/x
Thanks in advance (wishing I was coding in Python)
Ok, I've taken an interest in this question because I've reached the point where I'd like to discover the exact limits of PHP, including little hacks like this. Hopefully, I'll make sense this late at night and a few beers in me. Because of the ugly hackishness, I'm actually expecting to be downvoted.
Obviously, you can't do $this = $that. You also can't change the global variable you're currently trying to make into an object while it's being constructed, and attempting to do so will be ignored. As Charles said earlier, this can't be reasonably done. Not with clone, not serialize(), nothing within __construct().
So, unreasonably if you want $a to first become an object of class A, then convert mid-creation to class B, try this pseudo method: You'll have to call __construct of class A twice in a row. First time to handle construction of class A. Second time to complete the object converting it to class B. Class A handles the first half of construction, and class B the second half:
class A {
function __construct() {
$args = func_get_args(); // just to tell us the first round of __construct already occured
if (array_key_exists(0, $args) AND $args[0]) {
$GLOBALS['a'] = new B($GLOBALS['a']);
// stop because "reconstruction" has stopped. Nothing else you can do to $a in this scope.
$this->aprop2 = "yay";
// Seriously, stop. Don't bother putting more code at this point, you're wasting your time. Consider $a 'converted and returned' already.
}
// build on an object of class a here
}
}
class B {
function __construct($var) {
// maybe you'd like to do something with old $a? If so, here's $var for you
// continue constructing where A left off.
}
}
$a = new A(); // object of class A
$a->__construct(true); // object of class B
Maybe instead make another method of class A named more importantly sounding, which does the same thing to convert the global $a into object of class B, just so it doesn't look so stupid as my example. In other words, you're probably already doing it as best as PHP allows.
Edit: Really though, the above is nothing more than $a = new A(); $a = new B($a);. For better code readability and maintainability, you may want not to use my example and instead opt to implement a factory or handler class that creates and juggles these objects for you. I found a brief and insightful www.ibm.com article explaining the concept of factories how they are applied in PHP. Maybe conceptually, you want a static class that acts like a cd changer, and this is where Return by Reference - to work with a variable reference to the object in any scope - and Variable Objects (ref: midir's comments on that page) - to dynamically set or work with the object - comes in handy.
This is not currently possible in PHP...
Without doing stupid things.
If every instance of the object is a reference, and those references can be found in $GLOBALS, and the object knows what every one of those instances is called, you could replace each and every reference of the old object with your new object. The outside world won't know the difference.
This is, however, a spectacularly awful idea. Using __call magic is probably the least insane way of accomplishing your goal.
Edit: There's always runkit, which will let you do things like add and remove methods from classes. However, it's a PECL extension and might not even work correctly...