$this->use_mysqli = (bool) USE_EXT_MYSQL;
Seems like we should rename it to USE_EXT_MYSQLI
or use !USE_EXT_MYSQL
to set use_mysqli
21663.13.diff adds a constant called USE_EXT_MYSQL. Rather than the more forward-thinking driver approach, this simply restricts it to applying to the enabling/disabling of ext/mysql.
$this->use_mysqli = (bool) USE_EXT_MYSQL;
I think you meant:
$this->use_mysqli = !USE_EXT_MYSQL;
That said, methinks the define should actually be USE_EXT_MYSQLI
to *enable* MySQLi, rather than USE_EXT_MYSQL
to *disable* MySQL.
Imho, the odds are ridiculously low that someone would actually go in his wp-config file and define a constant to use the clunky old library, whereas I can readily imagine a number of hackers going in there and happily define a constant that allows to use the more modern library.
aaroncampbell, you mentioned previously that we've had problems with adding defines in the past - are there particular problems we've had that you think would apply to this situation? Given how early $wpdb
is created, it seems a define would be the only practical way for a site to be able to change the driver.
Sorry, I missed this with my last comment. The problem has been mostly in unit testing. If you define something like USE_EXT_MYSQL
to make a unit test to see that it works, you can't then change it during the testing so that another unit test can test the other option. If filters can't be run at the point where the DB is loaded though, we don't have a lot of options.
Sorry, I missed this with my last comment. The problem has been mostly in unit testing. If you define something like USE_EXT_MYSQL
to make a unit test to see that it works, you can't then change it during the testing so that another unit test can test the other option. If filters can't be run at the point where the DB is loaded though, we don't have a lot of options.
For unit testing purposes, couldn't we simply add a filter that we explicitly document as e.g. "internal, for unit testing purposes only — this hook cannot be used by plugins, because these are not loaded at this stage".
Alternatively, and perhaps more ideally, we could tweak the load procedure so to ensure that add_filter()
exists when wp-config.php is loaded. It's a matter of including a couple of files in wp-load.php
, and changing the calls to require_once
(instead of require
) in wp-settings.php
. That would ensure backwards compatibility with plugins that mindlessly include wp-config.php
, and forward compatibility of the needed filter.
I can readily imagine a number of hackers going in there and happily define a constant that allows to use the more modern library.
Honestly, the only reason why I'm even considering the constant is for development/testing purposes and easy recourse for broken sites. For this situation, said hackers should update to PHP 5.5. If they want to use a more modern library, then the onus should be on them to use a more modern version of PHP.
For unit testing, we can extend wpdb
and set use_mysqli to true. That property should probably be protected, not private.
the mysql_* functions are officially deprecated for PHP 5.4 and will begin throwing E_DEPRECATED errors in the next version of PHP.
http://marc.info/?l=php-internals&m=131031747409271&w=2
Wordpress should use PDO by default, but fall back to mysql_* when PDO is not present.
See also: #11622 for last year's discussion.
I have created a PDO backend for mysql_* functions for exiting old projects which I didn't want to have to go through the code, update, and re-test:
https://github.com/AzizSaleh/mysql
Hopefully it helps someone else.
Sorry, I missed this with my last comment. The problem has been mostly in unit testing. If you define something like USE_EXT_MYSQL
to make a unit test to see that it works, you can't then change it during the testing so that another unit test can test the other option. If filters can't be run at the point where the DB is loaded though, we don't have a lot of options.
Alternatively, and perhaps more ideally, we could tweak the load procedure so to ensure that add_filter()
exists when wp-config.php is loaded. It's a matter of including a couple of files in wp-load.php
, and changing the calls to require_once
(instead of require
) in wp-settings.php
. That would ensure backwards compatibility with plugins that mindlessly include wp-config.php
, and forward compatibility of the needed filter.
Ticket with patch: #27208
Would the code for switching to mysqli in development versions also disappear during RC or code freeze? Just curious since it would mean the unit tests would also always use mysqli across the board (including with PHP 5.2), which will be great for testing, but leaves us without results on ext/mysql all the way up to the very final tagged release even though it's still going to be used with 99% of installations right now. I'm not really too concerned about it, but it's something to think about.
For this situation, said hackers should update to PHP 5.5. If they want to use a more modern library, then the onus should be on them to use a more modern version of PHP.
Completely agreed here. If there's actually anyone in a situation where they could legitimately use mysqli enhancements or optimizations, the choice of upgrading to PHP 5.5 should make much more sense anyway, and they most likely already have the power to do this on their server(s). I'm honestly having a hard time even coming up with some use cases that might cover more than even 0.1% of users, and for that many, installing a DB drop-in is still a perfectly acceptable solution.
Would it make sense to create translation functions for mysql_* if they're not available?
I can see this being a saving grace for plugins / themes that do not use $wpdb
. Example plugin
Incomplete non-functioning concept code:
if (!function_exists('mysql_query')) {
$pdo_conn = null;
function mysql_connect($host = 'localhost', $user = '', $pass = '' ) {
global $pdo_conn = new PDO('mysql:;host=' . $host, $user, $pass);
function mysql_query($sql) {
global $pdo_conn;
return $pdo_conn->query($sql);
function mysql_fetch_assoc($rs) {
return $rs->fetch(PDO::FETCH_ASSOC);
// ... etc.
That is exactly what I did for my library to enable sites to work without mysql_* functions using PDO as a backend:
https://github.com/AzizSaleh/mysql
Copy those files to a folder and then in your wordpress wp-includes/load.php file replace the following two lines:
wp_load_translations_early();
die( __( 'Your PHP installation appears to be missing the MySQL extension which is required by WordPress.' ) );
With the following:
$pathToMySQL = 'C:\\xampp\\htdocs\\mysql\\';
require_once($pathToMySQL . 'MySQL_Definitions.php');
require_once($pathToMySQL . 'MySQL.php');
require_once($pathToMySQL . 'MySQL_Functions.php');
Last edited 10 years ago
by AzizSaleh
(previous)
(diff)
In terms of offering a mysql_* fallback for plugins, I don't see the benefit. This will only help when ext/mysql is missing, and it never is. ext/mysql will start to be disabled more often over time, but by the time that's any measurable footprint, we should be able to have moved the needle on plugins using MySQL directly.
There is little left here (please weigh in on anything I'm missing):
- Email the authors of all plugins that use mysql_* functions directly.
- Get Travis CI to run the test suite under MySQLi. It'd double the time it takes to do the tests, but it's probably worth it at least for now.
Given the decision not to do the full abstraction this time around, please carefully test and consider how this will affect the existing database abstraction plugins that many sites have installed in order to support databases other than MySQL.
One such plugin is "Wordpress Database Abstraction" ( http://wordpress.org/extend/plugins/wordpress-database-abstraction/ ), which (though not updated for a few years) is still working nicely with WordPress 3.8.1 . With the original developers of that plugin apparently gone, a way forward is needed to continue using alternative databases (such as MSSQL) with WordPress 3.9 .
One option would be for markoheijnen's plugin to be updated and to merge in the extra features from "Wordpress Database Abstraction", especially the query adjustment logic they put in their MSSQL driver (they apparently cared little for getting their other drivers right anyway).
What benjamin4 is seeing can be totally fine. You can specify a different default host in php.ini for MySQL and MySQLi. And if you only changed one then you can experience this weirdness.
I would say that it is a configuration mistake by the user since when using a socket connection you should never trust the default setting and always specify the location yourself.
I agree it is an configuration issue, however IMO it took me too much time to figure this out.
If I hadn't enabled WP_DEBUG, I wouldn't have seen the notice of mysqli_real_connect(), but only the generic "Error establishing a database connection"-Site, where sockets aren't even mentioned.
So instead of preventing the error (which we can't), we should improve its documentation. My suggestions:
- wp-config.php could include Syntax examples for valid uses of DB_HOST
- The error site on /wp-admin/ could link to a specific troubleshooting site on Codex instead of linking to the forum in general.
- It could also mention the recent move to Mysqli as possible cause.
To try and workaround situations where mysqli fails to connect, but mysql probably works, attachment:21663.17.diff implements a fallback to mysql, if the first attempt to connect through mysqli fails.
This patch doesn't try to figure out why the mysqli connection failed - if it's a connection configuration issue as described in comment:212, then it should just fallback nicely to mysql. If it's a more serious issue (ie, the server has gone away), mysql will return the same error as mysqli.
This allows us to avoid breaking a site that works under ext/mysql but is misconfigured for ext/mysqli.
props pento.
see #21663.
What's left here? I got:
- Don't force ext/mysqli in RC versions, as we had at one point discussed.
- Documentation on this new complexity in our database layer.
- Email the authors of all plugins that use mysql_* functions directly.
- Get Travis CI to run the test suite under both MySQL and MySQLi. (As noted by pento, if we didn't force ext/mysqli in development versions, this would already just happen automatically for PHP 5.2/5.3/5.4 versus PHP 5.5. I'm fine with Travis running like that if we can make it work.)