Hi, list!
This is my first email to this mailing list, so please pardon me for misuse
of the traditions you may have here (formatting, phrasing, etc.).
Maybe this has been discussed in depth earlier, but: I want to ask if there
is an explicit reason for not giving a "close" instance method in the PDO
class.
The Web is full of wrong disputes about why one would want to explicitly
close a PDO connection, since it is auto-released at end of script
life-cycle. Of course this is wrong, because among many other use cases,
for example a long running script (daemon-like) may want to free a DB
Connection slot when they know they have to sleep for some time.
The manual says that one has to assign to null, the variable retaining the
PDO instance. One also has to null out all the variables holding a
statement coming from that PDO instance).
IMHO this is not good practice enough, especially given the way many PHP
developers (mis)understand reference counting and variables.
$a = new PDO(...);
$b = $a;
$a = null;
This above snippet will not close the connection when assigning $a = null;
(at list not until PHP 5.6 incl).
In an application made of dependency injection, closures and many levels of
function calls split over many files, it is virtually impossible to keep
reference counting mentally, and you mostly end up never knowing what other
component of the application still retains a reference to the PDO object.
And yet, in some use cases, you still know that you want to release the
connection before going to sleep or doing a lengthy operation (which might
anyway cause a "Sql server has gone away", so you're better off not
occupying a DBMS connection slot for nothing during the lengthy operation.
I think it could be recommended to export a "closeConnection" method.
I would be happy to know what people think (and pardon me again if the
debate has been conducted already : please guide me to the corresponding
literature?)
If it is of any interest, what would be the next step? For me to open an
RFC?
Thanks,
Regards,
Gabriel
Gabriel Zerbib wrote on 21/01/2016 14:32:
Hi, list!
This is my first email to this mailing list, so please pardon me for misuse
of the traditions you may have here (formatting, phrasing, etc.).
Welcome! :)
Maybe this has been discussed in depth earlier, but: I want to ask if there
is an explicit reason for not giving a "close" instance method in the PDO
class.
I think the main problem with a close method on something that
represents a resource like a PDO connection object is how the object
should behave after it has been closed. That is, what should the
following code do?
$pdo = new PDO($dsn);
$pdo->closeConnection();
$pdo->query('Select 1 as test');
The object needs to track the fact that it is in a closed state, and do
something - maybe throw a ConnectionAlreadyClosedException? But then
what should the calling code do about that? If you have many objects
with reference to that PDO object, then any one of them could "close"
it, and any one could then try to execute a query. If you're not
careful, your closeConnection() method could become a
killScriptNextTimeAQueryIsAttempted() method.
If what you are actually doing is putting the connection to sleep, to be
"woken up" later, you need all the references to the object to have
the ability to "wake it up", because if you just create a new
connection, you've somehow got to propagate it to all the same places
you'd have to unset() in the current implementation. So that means the
close() method needs to be accompanied by a reopen() method, which means
saving the DSN and credentials, and any initialisation calls you want to
make at the beginning of the connection (setting encoding, etc)...
In an application made of dependency injection, closures and many levels of
function calls split over many files, it is virtually impossible to keep
reference counting mentally, and you mostly end up never knowing what other
component of the application still retains a reference to the PDO object.
One solution to this is to create a wrapper around PDO, which is the
only thing allowed to have a direct reference to the PDO object itself.
To this object, you can add a close() method to your wrapper, and maybe
isOpen(). If you save the DSN as well as the connection object, you can
then go further and have reopen(), openOnNextQuery() (lazy-loading), or
have your implementation of query() silently ensure that a connection is
open. You could have a hook that fires on connection / disconnection to
notify other objects, a list of SQL calls to run on connection, etc. etc.
That's not to say that a simple implementation of just
close-and-fire-exception would be a horrible idea in PDO, but having one
object which represents an open connection, and a separate one which
represents a potential connection (maybe open, maybe closed, maybe
not-open-yet) is a useful abstraction, and doesn't need anything in PDO
itself.
Regards,
Rowan Collins
[IMSoP]