Deconstructor in PHP - php

After taking a look at some old code:
//Nothing like a destructor!!
function destroy() {
settype(&$this, 'null');
}
And called by
$Cache->destroy();
However in PHP 5.3 I get
Deprecated: Call-time pass-by-reference has been deprecated in /blah/-cache-.php on line 154
How should I do this?

Your immediate problem can be met by removing the & in $this, but the whole construction doesn't make sense to me. If it's not plain invalid to destroy $this from within the object's context, it's definitely not good practice.
To destroy an object, a simple
unset($Cache);
will do.
If one wants to execute stuff when the object is destroyed, one should define a destructor in the class. (The comment in your destroy() code says that this is not the point here, though. :)

Just destroy the object like normal.
unset($Cache);
I don't know why they would do that nasty looking mess above. Keep in mind that if the object has pointers in different places you will need to unset all of them - not just that one line. (singletons are an example)

The error you're getting is not related to having a destructor. The error is simply because you've tried to pass $this by reference in a function call.
PHP used to allow this, but in current versions of PHP, if you want to pass something by reference, you should specify it in the function declaration.
Therefore, your function call should look like this:
settype($this, 'null');
(ie without the &). (btw -- the word 'null' in a string??? is that what you meant?)
And if you want to pass by ref, your function should look like this:
function settype(&$object, $secondparameter) {
...whatever the function does...
}
ie with the & in the function parameter.
This rule applies in all cases in PHP. As I said, it has nothing to do with your destructor method, or with it being an object; that's just how you pass by reference in modern PHP.
Now onto the other part of your question: A destructor method.
PHP does allow for an automatic destructor function, written within your class like this:
function __destruct() {
print "Destroying " . $this->name . "\n";
}
If you write this code, the __destruct() method will be called when the object is destroyed. This may or may not be what you want -- depends on how you want it to work. The object will be destroyed when all references to it are unset or come out of scope. If you're passing the object handle around by reference, this may not happen when you expect it to -- ie the object may persist in memory even when you say unset($myobject);. In this case, it may only actually get destroyed when the PHP program finishes running. If this is the case, and you need it to be called sooner than that, you may be fine continuing with the destroy() method you have already, and calling it explicity.
Hope that answers your question.

Related

Anyone know of a PHP Magic Constant for Trait's Redefined Name in a Class?

To make it simple, I have noticed that PHP doesn't seem to offer any magic constant for determining what the name that a trait has been changed to in a class. Since this sounds confusing to me in words, I will give an example, as it is rather easy and would expect it to be somewhere in the new PHP 5.5, I don't see a way to doing it. So here it is:
Say we have some class, that uses some trait that conflicts with some function inside the class, example:
class SomeClass {
use \Name\Space\SomeTrait { SomeFunction as private NewFunctionName; }
function SomeFunction() {
$this->NewFunctionName();
}
}
Since, obviously this class has the "SomeFunction" function, and we are aware that inside of SomeTrait we have included, is a function that is matching by name to a function we have inside this class. Now, since the "SomeFunction" came into this class via a trait inside of a \Name\Space, these 2 functions do 2 different things, but happen to use the same name, and inside of either another function or literally our 'SomeFunction', we then use the "SomeFunction" from our trait, by calling it by the "NewFunctionName".
So hopefully I haven't lost anyone here, as here is what my question comes down to in the above scenario. Within the \Name\Space\SomeTrait\SomeFunction(), how could one get the "NewFunctionName" that this trait function was assigned too? One would think to use a magic method, such as __FUNCTION__, or __METHOD__, or even __TRAIT__, except none of these give the expected result, so does anyone know a way to get this information without passing it to the function as a parameter and resulting in a hacky code? Maybe PHP 5.6 needs to add a new Magic Constant __AS__, or adjust the result of __TRAIT__, I dont understand why __TRAIT__ and __FUNCTION_ need to return the same information (or nearly the same information). Any help would be awesome, if it is an unconventional hacky method, Im interested in seeing my options, until I can open up a bug report with php regarding this. (if it is truly a bug)
edit:
My current, least hacky, method seems to be,
debug_backtrace()[0]['function']
and though it works, I feel it is doing a lot to get a simple string, especially if you use the function a lot. :/
This is the solution I ended up using. It's not very good but probably better than using the debug_backtrace function.
Problem example:
Trait ExampleTrait {
protected function doSomethingRecursive() {
// this is a problem because it could be renamed
$this->doSomethingRecursive();
}
}
Solution example:
Trait ExampleTrait {
protected function doSomethingRecursive() {
// this is a problem because it could be renamed
$this->__internal_doSomethingRecursive();
}
private function __internal_doSomethingRecursive() {
// this works because the class would have
// used and renamed the above function
// but this "internal" function *should*
// remain available under it's original name
$this->__internal_doSomethingRecursive();
}
}
Of course it's possible to break this but for most cases it should be fine. You could also include the name of the trait in the internal function name to further prevent conflicts.
Your current solution is going to be the best, with a couple tweaks:
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,1)[0]['function']
The DEBUG_BACKTRACE_IGNORE_ARGS and the frame limit of 1 there will make the backtrace shallow, faster, and use less memory.

Does function definition order matter?

In the script below, does the order in which items are declared matter?
For example, if the add_action points to a function that has not yet been defined? Does it matter or should the function declaration always precede any code in which its called?
add_action('load-categories.php', 'my_admin_init');
function my_admin_init(){
//do something
}
That doesn't matter if the function is declared before or after the call but the function should be there in the script and should be loaded in.
This is the first method and it will work:
some_func($a,$b);
function some_func($a,$b)
{
echo 'Called';
}
This is the second method and will also work:
function some_func($a,$b)
{
echo 'Called';
}
some_func($a,$b);
From the PHP manual:
Functions need not be defined before they are referenced, except when a function is conditionally defined as shown in the two examples below.
However, while this is more of a personal preference, I would highly recommend including all the functions you actually use in an external functions.php file then using a require_once() or include_once() (depending on tastes) at the very top of your main PHP file. This makes more logical sense -- if someone else is reading your code, it is blindingly obvious that you are using custom functions and they are located in functions.php. Saves a lot of guesswork IMO.
you can call a function before it's defined, the file is first parsed and then executed.
No.
It is not C :P...
As you can see here , the whole file is first being parsed and then executed.
If a function that doesn't exist is being called, php will throw an error.
Fatal error: Call to undefined function
As per my personal experience, In some special cases (Like, passing array's in function or function inside a function and so on). It's best option to define the function above the call. Because of this sometimes neither function works nor PHP throw an error.
In normal php functions, it doesn't matter. You can use both of the types.
It does not matter, as long as it is declared somewhere on the page.
as seen here:
http://codepad.org/aYbO7TYh
Quoting the User-defined functions section of the manual :
Functions need not be defined before
they are referenced, except when a
function is conditionally defined
So, basically : you can call a function before its definition is written -- but, of course, PHP must be able to see that definition, when try to call it.

Is using php destructor appropriate for displaying HTML?

If a class is implemented that builds HTML for a page by constructing it and calling various methods, is it appropriate to define the display/echo part of the class within the destructor?
Instead of having a explicit Class:displayHTML(); method, having the echo $this->html in the destructor and whenever you are ready to display call unset($object); which would display it?
I know the destructor probably is not the best place for this but wonder what others thoughts are on this?
That doesnt sound feasible to me. unset does not equal echo. It's a fundamentally different thing. Also, keep in mind that objects are not only destroyed on unset but also when they are no longer referenced and/or when the script terminates. That has a lot potential for unwanted side effects.
If you dont want to have/call a displayHTML() or render() method, implement that part in __toString() and just echo the instance.
class HTMLSomething
{
/* ... */
public function __toString()
{
/* create $output */
return $output;
}
}
$something = new HTMLSomething;
echo $something;
Which of these two has a more obvious outcome?
unset($object);
or:
$object->displayHTML();
Think about that, and then go read about the Principle of Least Astonishment.
This is not the way to go because you do not have complete control over your destructor. The destructor will be called when your script finishes, but you may not want to display anything under certain conditions (say: load, validate, validation fails, display something else).
Also, as Dominic pointed out, there is the matter of readability. You don't want to read your code a year later and say: Why do I unset the object? WTF was I thinking back then?! . As you can see this will increase the WTF/minute ratio and we all know that is a bad thing.
Seems like a bad idea. I don't really see this:
unset($view);
as better than this
$view->displayHTML();
It seems the only real advantage is that you don't really need to call unset() (since at the end of the script that should happen).
However, is that really a good thing? How then do you prevent it from being displayed? Once it's set you couldn't. Or you would need a special clear() function to unset the output before it's automatically output by the destructor.
To me, I don't see an advantage here.

Should a function be used in both static and object context

In my company's codebase, i see functions used in both static and object context. For e.g. a class A has a function b() which is called both using A::b() and/or object_of_type_A->b(). I know this throws an error if strict is turned on. But I wanted to know if this is a bad practice and if yes, then why? Thanks for any answers.
Let me know if I don't make sense anywhere. I would be happy to clarify.
I'm not a php guy, but this sounds just like Java, where it's allowed but discouraged.
If it's static, I would strongly recommend only calling it in a static way. Otherwise it looks like it depends on the state of the object you're supposedly calling it on.
In Java the best example of this is Thread.sleep(). It's a static method which puts the current thread to sleep, always. But look at this code:
Thread t = new Thread(someTask);
t.start();
t.sleep(1000);
What does it look like that code is doing? It appears to be putting the other thread to sleep, whereas in fact it'll be the current thread that's sleeping. When you change it to a plain static call, it's more obvious:
Thread.sleep(1000);
That doesn't refer to t, so must be about the current thread.
Unless there's something specific to php where calling the static method via a variable gives you some sort of polymorphism, I suggest you stick to calling it in the static way. The fact that strict mode tells you to do this is a pretty strong hint, IMO :)
Here's some test code:
<?php
error_reporting(E_ALL | E_STRICT);
class Foo{
public function a(){
}
public static function b(){
}
}
$MyFoo = new Foo;
Foo::a(); // Strict Standards: Non-static method Foo::a() should not be called statically
Foo::b();
$MyFoo->a();
$MyFoo->b(); // No complaints
?>
PHP/5.3 warns about static calls to non-static methods, which is fine since they are subject to failure as soon as you want to access $this. But it does not complain about object context calls to static functions: there's nothing that can go wrong. This behaviour is documented:
Declaring class properties or methods
as static makes them accessible
without needing an instantiation of
the class. A property declared as
static can not be accessed with an
instantiated class object (though a
static method can)
[...]
Because static methods are callable
without an instance of the object
created, the pseudo-variable $this is
not available inside the method
declared as static.
So, as far as PHP is concerned, what you found in the code base is not wrong. However, I think it's slightly confusing.
There is 'currently' no harm in using it either way except of course when called as a static function you can't access the $this member.
The reason it errors in strict is because not writing your code to strict standards can result in errors occurring due to a lack of diligence. in the future it may also cause your code to break. a static function has no $this member and it may break parameter passing.
Play it safe only call static functions with A::b() type calls.
DC
Regarding accessing $this in a static function I found something a bit strange a while back (might be changed in later versions of PHP though, think I ran 5.2 or something).
You can read about it here but it's in swedish. But use google translate and it should be understandable.
http://www.phpportalen.net/viewtopic.php?p=560080#560080

Is there anyway to get the order of the OOP method being called?

For example lets say I have a set of classes and methods to do so:
$obj->method1()->method2();
Is there anyway for method1() to know with in itself that its the first method being called or for method2 to know that its the last?
Some more details
I just want to be able to build a set of these calls so that it either returns an instance of itself if the call to the method isnt at the end of the chain or return something different if its at the end.
For example
$obj->method1()->method2(); #Here method 2 will return lets say a string.
$obj->method1()->method2()->method3(); #Since method2 isnt at the end of the chain, it should return an instance of itself (or another object) here so that the chain could continue.
EDIT: anyone whoz trying to do this - it is a bad design pattern.
This does seem to be a duplicate. Refer to this question for more answers.
Not out of the box, not even with a Stack trace.
I guess you could put something together using constants or global variables:
Don't try this at home!
$GLOBALS["chain"] = array();
$obj->method1()->method2(); // method1 adds member to $GLOBALS["chain"],
// array_push($GLOBALS["chain"], __FUNCTION__);
// method2 does the same...
print_r($GLOBALS["chain"]);
That would give you the full chain - not yet which one is the last one, to do that, you would have to pass a flag to method2().
But it would be horribly hacky and pollute your code.
Is there a specific reason you need this for?
All you could do is find out which methods have been called so far, by setting some kind of global state in the class. But you can't find out what methods are being called after a method, and you wouldn't be able to tell the difference between methods in one chain and methods in another:
$obj->m1()->m2();
$obj->m3(); // You would think that m1() and m2() came before this in the same chain
You would need to have a method at the end of each chain to clear the global state in the class.
Since it seems you need to see which method comes next in a chain, this won't work for you.
I would say that this is a really bad design pattern, at least for PHP (and every other language I've worked in). Each method should do one thing only. If you need a method to either return a string or an object depending on what you need it for later, you are doing something wrong.
Granted, I have done something like this before. It was a meta-information class for images submitted by users -- you could set it up like this:
$meta = new ImageMeta();
$meta->first_name("foo")->last_name("bar")->email("baz")->id("guid");
But, if you did this:
$meta->first_name();
it would return a string. The default value for the first parameter was NULL, and if the method got NULL, it returned a string. Otherwise it set (and escaped) an internal value and returned $this.
At first I thought it was kind of cool, but it turned out to be a mistake. I hate using that class now. Just make one method/function do one thing only and you will be much happier.
I don't think this is possible, no -- at least, I've never seen anything about this.
(Out of curiosity : why would you need that ? Maybe it would be possible to use onther solution to solve your actual problem ?)
The only way this is possible is to let the methods save some global state.
If both methods are in the same class, you could add a variable to the class and let each class set a unique value.
But the question is if this is desirable. This kind of behavior is often not very smart in the long run.

Categories