[RFC]: Change Default mysqli Error Mode

php.internals

Kamil Tekiela

5 years ago
Hi Internals, Following my earlier announcement in https://wiki.php.net/rfc/improve_mysqli I decided to submit a dedicated RFC for the first proposal. This RFC proposes to change the default mysqli error reporting mode to exception mode. This change follows the same change in PDO. The RFC can be found here https://wiki.php.net/rfc/mysqli_default_errmode Kind Regards, Kamil Tekiela

Larry Garfield

5 years ago
On Wed, Jan 20, 2021, at 5:04 PM, Kamil Tekiela wrote:
> Hi Internals, > > Following my earlier announcement in https://wiki.php.net/rfc/improve_mysqli > I decided to submit a dedicated RFC for the first proposal. > > This RFC proposes to change the default mysqli error reporting mode to > exception mode. This change follows the same change in PDO. The RFC can be > found here https://wiki.php.net/rfc/mysqli_default_errmode > > Kind Regards, > Kamil Tekiela
Consistency FTW. +1 --Larry Garfield

BohwaZ/PHP

5 years ago
We should do the same with SQLite3 extension.

Björn Larsson

5 years ago
Den 2021-01-21 kl. 00:04, skrev Kamil Tekiela:
> Hi Internals, > > Following my earlier announcement in https://wiki.php.net/rfc/improve_mysqli > I decided to submit a dedicated RFC for the first proposal. > > This RFC proposes to change the default mysqli error reporting mode to > exception mode. This change follows the same change in PDO. The RFC can be > found here https://wiki.php.net/rfc/mysqli_default_errmode > > Kind Regards, > Kamil Tekiela >
If I understand this correctly, does it imply that a lot of legacy code that works today, will not work any longer and needs to change? Like: if ("mysqlierror") { "error handling" } If so I think that like in other RFC's an investigation should be done on how much code that is affected to assess BC impact. Btw, I liked your proposal on how to improve prepared statements in mysqli a lot! Regards //Björn Larsson

Kamil Tekiela

5 years ago
On Thu, 21 Jan 2021 at 21:51, Björn Larsson <bjorn.x.larsson@telia.com> wrote:
> If I understand this correctly, does it imply that a lot of > legacy code that works today, will not work any longer and > needs to change? Like: > if ("mysqlierror") { > "error handling" > } > > If so I think that like in other RFC's an investigation should > be done on how much code that is affected to assess BC impact. >
The code will still work as it did before, but if there is an error then an exception will be thrown. This means that by default the custom error handlers will become redundant. Generally, this should not be a problem, but I can imagine that some projects heavily rely upon the manual error checking. Among the popular PHP projects that I know of, only CodeIgniter and WordPress still use mysqli. CI does offer PDO as an option but due to legacy reasons, many people still chose mysqli. However, they already use the exception mode. https://github.com/codeigniter4/CodeIgniter4/blob/d5673f4376dc981196607bc159368bee9990033c/system/Database/MySQLi/Connection.php#L94 WordPress ... the black sheep of PHP ... uses mysqli with a fallback to mysql_* API. They use manual error handling, which would be replaced by normal exceptions unless they silence it. They should modernize their codebase at some point as they can't cling on to the past forever. For the moment if they want to continue using manual error checking then they need to explicitly disable mysqli errors without relying on the default setting. That is only 1 additional line of code. This would be the same as what I have done in PHP internal test cases. I don't see any problems there. In fact, I don't really see this as a major breaking change. If any project really needs the mysqli errors silenced then they can just set the error mode back to OFF. The change is aimed at new users, not existing projects. Silenced error reporting was a source of confusion for plenty of beginners who were unaware of the setting. Kind Regards, Kamil Tekiela

Christian Schneider

5 years ago
Am 21.01.2021 um 23:46 schrieb Kamil Tekiela <tekiela246@gmail.com>:
> In fact, I don't really see this as a major breaking change. If any project > really needs the mysqli errors silenced then they can just set the error > mode back to OFF. The change is aimed at new users, not existing projects. > Silenced error reporting was a source of confusion for plenty of beginners > who were unaware of the setting.
As this definitely is a BC (applications stop running) I think we should go through a phase were it throws a warning instead of aborting, i.e. changing it to mysqli_report(MYSQLI_REPORT_ERROR); first and change it to throw an exception after a grace period. This would be in line with most other newly introduced exceptions for the default configuration. Plus this would most certainly help people who host other people's websites who want to upgrade to PHP 8.x. PS: IMHO The same should be (retroactively) done with round() and friends! - Chris

Girgias

5 years ago
On Mon, 25 Jan 2021 at 15:41, Christian Schneider <cschneid@cschneid.com> wrote:
> Am 21.01.2021 um 23:46 schrieb Kamil Tekiela <tekiela246@gmail.com>: > > In fact, I don't really see this as a major breaking change. If any > project > > really needs the mysqli errors silenced then they can just set the error > > mode back to OFF. The change is aimed at new users, not existing > projects. > > Silenced error reporting was a source of confusion for plenty of > beginners > > who were unaware of the setting. > > > As this definitely is a BC (applications stop running) I think we should > go through a phase were it throws a warning instead of aborting, i.e. > changing it to > mysqli_report(MYSQLI_REPORT_ERROR); > first and change it to throw an exception after a grace period. > > This would be in line with most other newly introduced exceptions for the > default configuration. > Plus this would most certainly help people who host other people's > websites who want to upgrade to PHP 8.x. > > PS: IMHO The same should be (retroactively) done with round() and friends! > > - Chris > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > >
The BC break is totally minimal as it's a one line of code that needs to be added (and for all intent and purposes should already be done). Moreover, I'd rather we get rid of the warning modes all together as they make the least sense to me. Either you're handling the failures explicitly anyway and you use the silent mode, or you don't and want it to throw with the exception mode. The warning mode is literally the worst of both worlds, it doesn't fail on failure so you need to check for failure manually, and you need to suppress the warnings because otherwise you get false negatives. Best regards, George P. Banyard

Benjamin Morel

5 years ago
> > Moreover, I'd rather we get rid of the warning modes all together as they > make the least sense to me. > Either you're handling the failures explicitly anyway and you use the > silent mode, or you don't and want it to throw with the exception mode. > The warning mode is literally the worst of both worlds, it doesn't fail on > failure so you need to check for failure manually, > and you need to suppress the warnings because otherwise you get false > negatives. > > Best regards, > > George P. Banyard >
I'd just like to say amen to that. Please move as much code as possible to throwing exceptions, and get rid of warnings. Most of the time when a warning is thrown in PHP, what you actually want is to deal with it, or stop execution. - Benjamin

Christian Schneider

5 years ago
Am 25.01.2021 um 16:59 schrieb G. P. B. <george.banyard@gmail.com>:
> The BC break is totally minimal as it's a one line of code that needs to be added (and for all intent and purposes should already be done).
That does not change the fact that it is a BC break which should be treated accordingly. You are basically advocating people should add mysqli_report(MYSQLI_REPORT_OFF) to their setup which will totally defeat the purpose of the change. Or (probably more what you have in mind) that they should add mysqli_report(MYSQLI_REPORT_ERROR) now (to prepare for the change) and switch to MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT later once they know they are ready. And this is exactly what I think should be done by the PHP default so people don't have to go through this manually.
> Moreover, I'd rather we get rid of the warning modes all together as they make the least sense to me. > Either you're handling the failures explicitly anyway and you use the silent mode, or you don't and want it to throw with the exception mode.
This is where you are missing a key component: I want to go through a phase where I will notice parts where manual error handling (or exception handling after the change) is missing without having my application abort. This is what warnings are good for. To some of us this is a very valuable step when upgrading. - Chris

Björn Larsson

5 years ago
Den 2021-01-25 kl. 17:25, skrev Christian Schneider:
> Am 25.01.2021 um 16:59 schrieb G. P. B. <george.banyard@gmail.com>: >> The BC break is totally minimal as it's a one line of code that needs to be added (and for all intent and purposes should already be done). > > That does not change the fact that it is a BC break which should be treated accordingly. > > You are basically advocating people should add mysqli_report(MYSQLI_REPORT_OFF) to their setup which will totally defeat the purpose of the change. > Or (probably more what you have in mind) that they should add mysqli_report(MYSQLI_REPORT_ERROR) now (to prepare for the change) and switch to MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT later once they know they are ready. > And this is exactly what I think should be done by the PHP default so people don't have to go through this manually. > >> Moreover, I'd rather we get rid of the warning modes all together as they make the least sense to me. >> Either you're handling the failures explicitly anyway and you use the silent mode, or you don't and want it to throw with the exception mode. > > This is where you are missing a key component: I want to go through a phase where I will notice parts where manual error handling (or exception handling after the change) is missing without having my application abort. This is what warnings are good for. > > To some of us this is a very valuable step when upgrading. > > - Chris >
I fully agree on this! Just changing one line of code is not a good enough justification, since for legacy code that could be a change that is not needed. Think one should ask if for a stable released product, changing on line of code incurs cost for testing and release management. So it's not just about changing one line of code... When it comes to warnings vs exceptions for me the main benefit with warning & grace period is that when migrating legacy code the timeline is not forced by the application stopping and one can see all the warnings generated by the app and fixing them. But of course I fully support the overall strategy on going for exceptions in Mysli. r//Björn L

Girgias

5 years ago
On Mon, 25 Jan 2021 at 16:25, Christian Schneider <cschneid@cschneid.com> wrote:
> Am 25.01.2021 um 16:59 schrieb G. P. B. <george.banyard@gmail.com>: > > The BC break is totally minimal as it's a one line of code that needs to > be added (and for all intent and purposes should already be done). > > That does not change the fact that it is a BC break which should be > treated accordingly. > > You are basically advocating people should add > mysqli_report(MYSQLI_REPORT_OFF) to their setup which will totally defeat > the purpose of the change. > Or (probably more what you have in mind) that they should add > mysqli_report(MYSQLI_REPORT_ERROR) now (to prepare for the change) and > switch to MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT later once they know > they are ready. > And this is exactly what I think should be done by the PHP default so > people don't have to go through this manually. > > > Moreover, I'd rather we get rid of the warning modes all together as > they make the least sense to me. > > Either you're handling the failures explicitly anyway and you use the > silent mode, or you don't and want it to throw with the exception mode. > > This is where you are missing a key component: I want to go through a > phase where I will notice parts where manual error handling (or exception > handling after the change) is missing without having my application abort. > This is what warnings are good for. > > To some of us this is a very valuable step when upgrading. > > - Chris >
I've never said there is no BC break, and frankly this change (and other similar ones) should probably have been done in PHP 8 at the same time with PDO. And yes I'm basically advocating for people to add mysqli_report(MYSQLI_REPORT_ERROR) (or even mysqli_report(MYSQLI_REPORT_OFF) if they fancy) to their setup, I'm even advocating for them to do it *right now* such that they can catch anything ahead of time. Moreover, this proposal does not prevent you from using the warning mode instead of jumping to exceptions directly, the key point is that you need to specify it, and I personally believe that having the warning mode as the *default* mode is the worst choice for the reasons I mentioned previously. The removal of the warning modes is completely orthogonal to this proposal, and I agree it is a very useful tool for transitioning to the exception mode, but this transition can already be done in PHP 5, 7 and 8. The grace period for completing this transition is from whenever you want to whenever, if ever, the warning mode gets deprecated and removed. On the note that a one line code change is not a good enough justification for saner defaults, I don't know what to say. At worst you need to find all usages of a connection start and add the line to downgrade the error reporting (even to silence if too many warnings are emitted). I don't see what testing needs to be done, you're reverting to the previous state which supposedly is already working. Best regards, George P. Banyard

Christian Schneider

5 years ago
Am 25.01.2021 um 18:22 schrieb G. P. B. <george.banyard@gmail.com>:
> And yes I'm basically advocating for people to add mysqli_report(MYSQLI_REPORT_ERROR) (or even mysqli_report(MYSQLI_REPORT_OFF) if they fancy) to their setup, I'm even advocating for them to do it right now such that they can catch anything ahead of time.
Defaults matter. Most people will *not* do this step and their code will fail on upgrade.
> Moreover, this proposal does not prevent you from using the warning mode instead of jumping to exceptions directly, the key point is that you need to specify it, and I personally believe that having the warning mode as the default mode is the worst choice for the reasons I mentioned previously.
Agree to disagree. If I have the choice to make the smoothen the transition centrally with PHP defaults or rely on each user to do it manually by proactively setting warning modes I prefer the defaults way. Remember: I am not advocating staying in the warning mode, I'm just seeing it as a useful intermediate step for legacy stuff we want to fix. - Chris

Alexandru Pătrănescu

5 years ago
On Mon, Jan 25, 2021 at 7:33 PM Christian Schneider <cschneid@cschneid.com> wrote:
> Am 25.01.2021 um 18:22 schrieb G. P. B. <george.banyard@gmail.com>: > > And yes I'm basically advocating for people to add > mysqli_report(MYSQLI_REPORT_ERROR) (or even > mysqli_report(MYSQLI_REPORT_OFF) if they fancy) to their setup, I'm even > advocating for them to do it right now such that they can catch anything > ahead of time. > > Defaults matter. Most people will *not* do this step and their code will > fail on upgrade. > > > Moreover, this proposal does not prevent you from using the warning mode > instead of jumping to exceptions directly, the key point is that you need > to specify it, and I personally believe that having the warning mode as the > default mode is the worst choice for the reasons I mentioned previously. > > Agree to disagree. > > If I have the choice to make the smoothen the transition centrally with > PHP defaults or rely on each user to do it manually by proactively setting > warning modes I prefer the defaults way. > > Remember: I am not advocating staying in the warning mode, I'm just seeing > it as a useful intermediate step for legacy stuff we want to fix. > > - Chris > >
Hi Chris, I think PHP is far from targeting a zero cost on version upgrade for projects. There will be other parts that will require testing, whatever you do. Trying to optimize this to reduce the 1 line quick fix that could be easily read in the documentation at https://www.php.net/manual/en/migration81.php sounds to me like we're trying too hard to reduce this cost, ignoring others. Other technical costs would be to not switch earlier to new exception mode as long as the default will cover the cases. I am thinking about this with a legacy system in mind that is long due on exception handling for the database layer. I know that having exceptions by default would spark an interest in developers' minds to do this change sooner rather than later because they will feel the default is the recommended way. Due to bandwidth allocation, they might add the line there, but a task will be created to fix it in the next few months, maybe a year. There will be a cost of upgrading. New scenarios and tests that might not even exist currently, negative flow scenarios. Regards, Alex

Christian Schneider

5 years ago
Am 26.01.2021 um 07:57 schrieb Alexandru Pătrănescu <drealecs@gmail.com>:
> There will be other parts that will require testing, whatever you do. Trying to optimize this to reduce the 1 line quick fix that could be easily read in the documentation at https://www.php.net/manual/en/migration81.php <https://www.php.net/manual/en/migration81.php> sounds to me like we're trying too hard to reduce this cost, ignoring others.
The migration guides are already getting quite long, just have a look at https://www.php.net/manual/de/migration80.incompatible.php <https://www.php.net/manual/de/migration80.incompatible.php> "Just one more line" can add up and that's why I want to be able to proactively fix my code, not fixing it at the time of migration. If the error mode would be changed to warnings instead of exceptions first then every developer interested in best practices could and would already adapt their code. But they could do it gradually without the disruption of hard fails looming over them. I just think giving developers a warning period (per default, not opt-in) is the right thing to do for BC breaks. [ Did I mention round()? ;-) ] I start to sound like a broken record, I'll leave it at that, - Chris

Nikita Popov

5 years ago
On Thu, Jan 21, 2021 at 12:05 AM Kamil Tekiela <tekiela246@gmail.com> wrote:
> Hi Internals, > > Following my earlier announcement in > https://wiki.php.net/rfc/improve_mysqli > I decided to submit a dedicated RFC for the first proposal. > > This RFC proposes to change the default mysqli error reporting mode to > exception mode. This change follows the same change in PDO. The RFC can be > found here https://wiki.php.net/rfc/mysqli_default_errmode > > Kind Regards, > Kamil Tekiela >
Fully support this proposal. Throwing exceptions is the right default, it matches what PDO does, and restoring the old behavior is one line of code. Regards, Nikita

Sebastian Bergmann

5 years ago
Am 25.01.2021 um 11:03 schrieb Nikita Popov:
> Fully support this proposal. Throwing exceptions is the right default, it > matches what PDO does, and restoring the old behavior is one line of code.
I second that emotion.

Johannes Schlueter

5 years ago
On Wed, 2021-01-27 at 15:17 +0100, Sebastian Bergmann wrote:
> Am 25.01.2021 um 11:03 schrieb Nikita Popov: > > Fully support this proposal. Throwing exceptions is the right > > default, it > > matches what PDO does, and restoring the old behavior is one line > > of code. > > I second that emotion.
The issue is, as said, that this only happens in an error situation. Thus if users only test "does my site still work after update?" (what many do ...) won't notice this, till something fails, which would have been caught nice beforehand. I agree that the proposed behavior is better, but we have to mind migration paths. johannes

Kamil Tekiela

5 years ago
> > The issue is, as said, that this only happens in an error situation. > Thus if users only test "does my site still work after update?" (what > many do ...) won't notice this, till something fails, which would have > been caught nice beforehand. >
I don't see why this would be such an issue. If the code fails for any reason then an error is produced. The error might be surprising, but it is not something that would cause problems. In situations where the code depends on the silenced errors to work properly then the developers would know this and they would test for it during the upgrade. This change fixes more problems than it creates. I believe it is still worthy to put it in 8.1. Every PHP release contains backwards-incompatible changes. In comparison to other BC changes PHP has put in minor releases this one has a very easy fix. You don't have to scour the code looking for places to fix. PHP can't improve if we have to think of people who upgrade without reading the release notes. We also shouldn't be held back by outdated tutorials. In fact, this will help people who still use such tutorials. This isn't a major change that would affect everyone on the planet. This will only affect people who still use mysqli and didn't set the error reporting mode before upgrading. I understand your worries but I don't think this is a good enough reason to not go ahead with this change. Kind regards, Kamil

Rowan Collins

5 years ago
On 27/02/2021 16:23, Kamil Tekiela wrote:
> I don't see why this would be such an issue. If the code fails for any > reason then an error is produced. The error might be surprising, but it is > not something that would cause problems.
Just addressing this argument, not the proposal itself, a function throwing an exception that previously failed silently absolutely could cause problems. Consider this code: function get_product($product_id) {     $sql = "Select * From products Where product_id = '" . $dbWrapper->escape($product_id) . "'";     return $dbWrapper->runQuery($sql); } If product_id is actually an integer column, this function is technically broken: given a non-integer input, it will produce an error in the database. However, with lax error handling, the calling code will simply treat this as the product not existing, and handle it gracefully. If $dbWrapper->runQuery suddenly starts throwing exceptions, functions that were inadvertently relying on this behaviour will start failing, possibly with an uncaught exception propagating to the user. The exception is certainly pointing out a real bug, and the function can easily be fixed once the problem is spotted, but the change has a real negative impact on the application. To be clear, I am not saying I agree or disagree with this particular proposal. I note that the user could in this example update their DB wrapper to set the error mode explicitly, or to catch exceptions. I just wanted to show that "it only happens on error" doesn't mean the impact is zero. Regards,
-- Rowan Tommins [IMSoP]

Kamil Tekiela

5 years ago
> > If product_id is actually an integer column, this function is > technically broken: given a non-integer input, it will produce an error > in the database. >
I'm sorry, but I do not understand why would that code produce an error. The value is properly escaped and formatted so there should be no error at all. Is this based on some SQL setting? That SQL looks correct to me and I do not see any syntax errors. Also, silenced or not, if an error occurs on MySQL side then PHP has to check for it one way or another or it will break with some other horrendous error.

Rowan Collins

5 years ago
On 27/02/2021 16:57, Kamil Tekiela wrote:
> > If product_id is actually an integer column, this function is > technically broken: given a non-integer input, it will produce an > error > in the database. > > > I'm sorry, but I do not understand why would that code produce an > error. The value is properly escaped and formatted so there should be > no error at all. Is this based on some SQL setting? That SQL looks > correct to me and I do not see any syntax errors.
That's precisely why it's the kind of code that goes unfixed for years, but it is broken: if $product_id is the string 'hello world', then this line... $sql = "Select * From products Where product_id = '" . $dbWrapper->escape($product_id) . "'"; ...produces this SQL: Select * From products Where product_id = 'hello world' If product_id is a column of type int, then the database will raise an error about incompatible types. If the PHP database wrapper just swallows this error and returns false, then somewhere else in the code, you can write this: $product = get_product($_GET['product_id']); if ( ! $product ) {    display_error_message('Sorry, we could not find that product.'); } So although the code is wrong, the user always gets a reasonable error message. Now replace the database implementation with one that throws exceptions, and that message will never display; if you're lucky, there's a default exception handler set; if not, the user will get a blank white page. Regards,
-- Rowan Tommins [IMSoP]

Kamil Tekiela

5 years ago
> > Select * From products Where product_id = 'hello world' > > If product_id is a column of type int, then the database will raise an > error about incompatible types. >
No, this query would produce a warning. I am unaware of an SQL mode that would turn this warning into an error. Maybe I am wrong and there is a way to convert this into an error, but that would be pointless. I believe you have chosen the wrong example. That query, even when executed with PDO, doesn't throw an exception. The point of this RFC is that mysqli should treat SQL errors the same way that PDO does. By default, all errors should be reported. An error in SQL is the same as an exception in PHP code; it means that something went terribly wrong. I have been using PDO for a few years now and I never had a need to silence its error reporting. SQL doesn't spit out exceptions randomly. Examples, that would truly be effected are something like this: $stmt = $mysqli->query('INSERT INTO tableA (uniqueColumn) VALUE("repeated value")'); if (1062 === $mysqli->errno) { echo "Can't add this value because it already exists!"; } If the developer didn't silence the errors then the user will see a generic error instead of the specific one.

Kamil Tekiela

5 years ago
> The code shown here https://www.w3schools.com/php/func_mysqli_connect.asp is
relatively correct at the moment. Maybe not nice, but it handles the error. That is the second hit on google (after php.net manual) when searching for "php tutorial mysqli_conect") Most other books, tutorials, ... teach the same. w3schools is hardly something that should be regarded as a reputable source of information and should not impact the direction PHP is heading in. This problem comes mostly from the fact that the developers who wrote these tutorials were unaware that there is automatic error reporting available. PHP manual didn't explain this either. This RFC proposes to change that by making it the default so that people can't miss it. The reason why I really want this default setting to change is that I was lied to by books and tutorials when I was learning PHP. I wish I knew about automatic error reporting instead of struggling with invisible SQL errors. I still hold a grudge against the tutorials teaching me manual error checking or the use of real_escape_string. I do not want new developers in the era of PHP 8 to suffer the same pain I did.
> Spend a day looking at stackoverflow and you see a different world. Also
many users just want to use a PHP app and don't care about PHP. Yes, but once again the problem is the old tutorials that teach it incorrectly. Most of them still are vulnerable to SQL injection. We can't change the tutorials but we can change the recommended setting in PHP.
> In 8.1 add deprecation notices to mysqli_connect & friends AND to access
to the connection_error (if I remember right that goes via the __get hook, thus we can add a deprecation note to a "property" access)
> The later is a good place as many people use the @ operator on the
connect, but not on the error check.
> In a later version we change it. > That gives a chance to reach users. We will still miss many, but for a
notable amount of people there is a chance. I believe Nikita has proposed it already. I am not very happy about it as this would mostly go unnoticed. People who have mysqli error reporting silenced often have every other error reporting silenced too including deprecation notices. Adding such deprecation notice would just create another confusing PHP error that developers would have to fix. I am sorry to say this about my fellow developers but many of the ones that you are targeting with this proposal who wouldn't read an upgrade guide before upgrading, are also the ones who would ignore this deprecation warning in their error logs. "Hey, the code still works, I don't know what this deprecation notice is talking about!" For these reasons, I am unwilling to go through a deprecation phase. I believe it would be just a waste of time. But if this is the only way that this change will land in PHP then I would also accept it as a very unsatisfying compromise.

Rowan Collins

5 years ago
On 27/02/2021 18:10, Kamil Tekiela wrote:
> > Select * From products Where product_id = 'hello world' > > If product_id is a column of type int, then the database will raise an > error about incompatible types. > > > No, this query would produce a warning. I am unaware of an SQL mode > that would turn this warning into an error.
Right, I forgot we were talking about MySQL, which has the same "ignore and carry on" tradition as PHP; in other DBMSes, that would be an error: PostgreSQL:
> ERROR: invalid input syntax for type integer: "hello world" > LINE 1: Select * From products Where product_id = 'hello world';
Microsoft SQL Server:
> Msg 245 Level 16 State 1 Line 1 > Conversion failed when converting the varchar value 'hello world' to
data type int. However, the main point of the example was to show that an error could go unnoticed, and actually have no immediate negative effects, such that replacing it with an exception makes things worse.
> Examples, that would truly be effected are something like this: > > $stmt = $mysqli->query('INSERT INTO tableA (uniqueColumn) > VALUE("repeated value")'); > if (1062 === $mysqli->errno) { >     echo "Can't add this value because it already exists!"; > } > > If the developer didn't silence the errors then the user will see a > generic error instead of the specific one.
Precisely, and this is what people are concerned about: if someone is writing code from scratch, exception-by-default is a good thing; but if they have existing error handling, by-passing that handling by throwing an exception is not. Regards,
-- Rowan Tommins [IMSoP]

Johannes Schlueter

5 years ago
On February 27, 2021 5:23:47 PM GMT+01:00, Kamil Tekiela <tekiela246@gmail.com> wrote:
>> >> The issue is, as said, that this only happens in an error situation. >> Thus if users only test "does my site still work after update?" (what >> many do ...) won't notice this, till something fails, which would >have >> been caught nice beforehand. >> > >I don't see why this would be such an issue. If the code fails for any >reason then an error is produced. The error might be surprising, but it >is >not something that would cause problems. In situations where the code >depends on the silenced errors > to work properly
The code shown here https://www.w3schools.com/php/func_mysqli_connect.asp is relatively correct at the moment. Maybe not nice, but it handles the error. That is the second hit on google (after php.net manual) when searching for "php tutorial mysqli_conect") Most other books, tutorials, ... teach the same.
> then the developers >would >know this and they would test for it during the upgrade.
That is true for the ones posting here and talking at conferences. Spend a day looking at stackoverflow and you see a different world. Also many users just want to use a PHP app and don't care about PHP. In many cases some agency (which often have no idea about software development, but mostly care about the UI design and reaching a goal quickly) created an app and the users just want to run it and got an server with thestest version. This isn't nice, but it is a reality.
>This change fixes more problems than it creates. I believe it is still >worthy to put it in 8.1.
It is true that more consistent error reporting via Exceptions would be better and solve many problems. These are the reminders of the "OO wars" we fought around the time of the PHP 4 - PHP 5 transition and I think it is great that many people are working on cleaning this up!
> Every PHP release contains >backwards-incompatible >changes.
There is a balance we're always fighting about. There are cases where BC breaks are done and hopefully most of them explode loud. For instance of we add a new keyword. This emits and error quite quickly, a simple lint check is enough to find it. Just including the file will fail. Here we are talking about a case where the break will only occur in an errorous situation. Which users will only spot when reading the upgrading guide carefully. In an area 99% of beginner tutorials and books touch.
> In comparison to other BC changes PHP has put in minor >releases >this one has a very easy fix. You don't have to scour the code looking >for places to fix.
The fix is easy. Getting awareness is hard.
>PHP can't improve if we have to think of people who upgrade without >reading >the release notes. We also shouldn't be held back by outdated >tutorials. In >fact, this will help people who still use such tutorials. This isn't a >major change that would affect everyone on the planet. This will only >affect people who still use mysqli and didn't set the error reporting >mode >before upgrading. >I understand your worries but I don't think this is a good enough >reason to >not go ahead with this change.
I am not about stagnating and not doing anything. As said: I think the idea is good. I am about thinking about the process and timing. What about this approach: In 8.1 add deprecation notices to mysqli_connect & friends AND to access to the connection_error (if I remember right that goes via the __get hook, thus we can add a deprecation note to a "property" access) The later is a good place as many people use the @ operator on the connect, but not on the error check. In a later version we change it. That gives a chance to reach users. We will still miss many, but for a notable amount of people there is a chance. johannes

Benjamin Eberlei

5 years ago
On Sat, Feb 27, 2021 at 5:24 PM Kamil Tekiela <tekiela246@gmail.com> wrote:
> > > > The issue is, as said, that this only happens in an error situation. > > Thus if users only test "does my site still work after update?" (what > > many do ...) won't notice this, till something fails, which would have > > been caught nice beforehand. > > > > I don't see why this would be such an issue. If the code fails for any > reason then an error is produced. The error might be surprising, but it is > not something that would cause problems. >
I think you are very wrong about this, there could be perfectly valid code doing: if (!$conn->query("select 1") && $conn->errno == 2006) { // mysql gone away $conn = new mysqli(....); } With your proposed change the query would throw an exception instead, potentially breaking follow up code that is required to run. This is the kind of code you have that only gets triggered every 100000 times and that is very hard to write a real test for. If the test here uses a mock, then you wont catch the behavior change.
> This change fixes more problems than it creates. I believe it is still > worthy to put it in 8.1. Every PHP release contains backwards-incompatible > changes. In comparison to other BC changes PHP has put in minor releases > this one has a very easy fix. You don't have to scour the code looking for > places to fix. >
There are projects out there that do a mysqli_connect on *every* script. You underestimate the impact of this break. PHP can't improve if we have to think of people who upgrade without reading
> the release notes. We also shouldn't be held back by outdated tutorials. In > fact, this will help people who still use such tutorials. This isn't a > major change that would affect everyone on the planet. This will only > affect people who still use mysqli and didn't set the error reporting mode > before upgrading. >
I am sorry, but to me that feels a bit like you want to take the easy way out.. As a counterexample, Nikita made a very good RFC for 8.1 / 9.0 deprecating and changing the nullable to internal functions behavior: https://wiki.php.net/rfc/deprecate_null_to_scalar_internal_arg This RFC goes above and beyond to provide a migration path, deprecation messages and such. Yes it has a higher potential break impact, but i don't expect this change to wait until 9.0 either. I would wish your RFC would throw a deprecation message in 8.1 that you cannot make a query without setting the reporting level before by calling mysqil_report() explicitly. Then in 8.2 we could change the behavior.