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.
Related
We've experienced some issues with our website going down from what I believe is an overload of database connections when running bulk processes from old code. This code was not dealing with closing database connections at all.
Can you confirm that this is an efficient way of going about a shared database connection?
common.php (included at the top of every php file on the server):
// Set a global DB connection
$db = new dbConnection();
$global_conn = $db->pdoConnect();
class_example.php:
public static function myFunctionName($) {
// Example query
$sql = "SELECT * ";
$stmt = $GLOBALS['global_conn']->prepare($sql);
I would then perform the following, nulling the shared global connection at the very end.
require_once "/includes/db.php";
require_once "/includes/class.php";
class->myFunctionName();
$global_conn = null;
Is one "null" of the connection variable enough. I don't need to do this in the functions that use it do I?
I don't particularly like global variables randomly popping from nowhere in the middle of arbitrary methods1 but, performance wise, you're effectively using a single connection all across the script as long as you aren't opening persistent connections by setting the PDO::ATTR_PERSISTENT flag (you don't really say). PDO doesn't have a class method to close connections so this is as close as you can get:
The connection remains active for the lifetime of that PDO object. To
close the connection, you need to destroy the object by ensuring that
all remaining references to it are deleted—you do this by assigning
NULL to the variable that holds the object. If you don't do this
explicitly, PHP will automatically close the connection when your
script ends.
The last statement means that you only need to do it explicitly if you want to release it early (i.e., you no longer need it but your script still has stuff to do).
(1) Database connections are not special variables. They can be used as function parameters or class properties like any other type and, since they're objects, what you're passing around is a reference to the same instance. E.g.:
public static function myFunctionName(dbConnection $global_conn) {
}
I want to know when an object in PHP will be destruct (destroy) by default. For example if we instantiate a class in a function, does it destruct at the end of function or still will be alive ?
It will eventually be destroyed when all variables that point to the object cease to exist. Variables cease to exist when they go out of scope or when they are unset. Variables go out of scope when the scope/function they were declared in exits.
Yes, it will. The object will live for the duration that it's instance is in scope. You may wish to browse the PHP Garbage Collection documentation. It's also worth noting that you can try these things out for yourself by implementing a __destruct magic method.
I am having problem with implementing custom session handler in php.
The code:
http://pastebin.com/9QV9f22Q
I initialize this once in my frameworks bootstrap, after I have connection with db:
require_once 'DbSession.php';
$session = new DbSession();
session_start();
But then I can't view my page. Firefox gets 302 Status with "Server not found" error. Firebug says that content is 5k long, but I can't view the page.
Log after one reload:
http://pastebin.com/JYe14nGR
I wonder why it still "loses" that created DbSession instance. Do yo have any ideas? TIA
Your code is based on a false premise: that you can return a different object from a PHP constructor. Quite the opposite: PHP entirely ignores the return value from a constructor.
Here's what's actually happening.
When your code calls:
$session = new DbSession();
the $firstTime == false check runs, meaning getInstance() gets called.
getInstance finds no existing instance, so it calls setup().
setup() calls new DbSession() again, this time passing in the argument preventing another call to getInstance(). It creates the object, registers it as the session handler, and returns it.
getInstance shoves the object in a static variable, and then returns it to the original constructor call. The original constructor call then drops the existing object on the ground and returns a brand new copy of itself.
You can fix some of this insanity by never instantiating the object outside of setup/getInstance(). Try making the constructor protected and only ever calling getInstance().
However, none of this explains why the code is malfunctioning for you. In fact, we can't explain it either. We're missing all the rest of the code, including what database adapter you're using, what ORM you're using (or even if you are using an ORM, your class and method names suggest it), what framework(s) might be involved, etc.
Try cutting all of the actual database touching from the class. Just write files on disk. Get that working first, then introduce the database layer. Chances are that your error will become obvious at that point.
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.
I have to migrate a php4 app that uses session_set_save_handler() to php5.
In php4 everything was fine, but in php5 the callback functions cannot access the global vars anymore, which were set on the page before session_set_save_handler() was called.
In the example below the global var $g1 cannot be accessed in the session_writer() (which is passed as a callback function)
Is there some explanation for this behavior or can you give a hint on migrating sessions with callbacks from php4 to 5?
This is the pseudo code:
function session_writer($id,$vars) {
global $g1;
echo "g1 not defined here: ".is_object($g1);
}
global $g1;
$g1 = SomeObject(); //which is the DB connection for the session writer
session_set_save_handler($o,$c,$r,"session_writer",$d,$g);
session_start();
This is actually noted in the documentation:
As of PHP 5.0.5 the write and close handlers are called after object destruction and therefore cannot use objects or throw exceptions. The object destructors can however use sessions.
It is possible to call session_write_close() from the destructor to solve this chicken and egg problem.
Essentially, you'll have to call session_write_close() from the destructor of your SomeObject, or alternatively, do the following:
<?php register_shutdown_function("session_write_close"); ?>
Either of those solutions should force the writing and closing of the session before all objects are destroyed, allowing you to keep your original callback function.
Molf's answer identifies the problem. Here's some more info:
session_write_close() takes as input an identifier and the data associated with it. If you're going for minimal change, you'll probably need to know the data is what is returned by session_encode() (which is a string encoding the contents of the $_SESSION array). The identifier is what is returned by session_id().