framework: laravel PDO invalid attribute exception with PHP 8.2.9/8.1.22
Laravel Version
10.17
PHP Version
8.2.9
Database Driver & Version
php_pdo_sqlsrv_82_ts_x64 5.11, Microsoft sql server 2019
Description
PHP just released a new minor version 8.1.22 / 8.2.9. There are some changes related to PDO.
My applications work fine with php 8.1/8.2 previous minor versions.
With 8.1.22 (laravel 9.* ) or 8.2.9 (laravel 10.* ), have a connection to a Microsoft sql server 2019, with official Microsoft database php pdo driver,
I got
Illuminate \ Database \ QueryException SQLSTATE[IMSSP]: An invalid attribute was designated on the PDO object.
for any queries in laravel.
I have also tested with raw php, pdo seems working fine.
It seems related to this line https://github.com/laravel/framework/blob/10.x/src/Illuminate/Database/Connectors/SqlServerConnector.php#L19
Steps To Reproduce
- laravel application with php 8.1.22/8.2.9 and Microsoft pdo driver, either windows or linux,
- connecting to a Microsoft sql server
- do a query in laravel.
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 14
- Comments: 61 (24 by maintainers)
Commits related to this issue
- ci: 🎡 Workaround for sqlsrv https://github.com/laravel/framework/issues/47937 — committed to mpyw/laravel-unique-violation-detector by mpyw 10 months ago
- Support laravel/framework#47973 (v10.20.0) (#3) * feat: 🎸 Support laravel/framework#47973 * ci: 🎡 Test on both ^10.20 and 10.19.* * ci: 🎡 migrate configuration * ci: 🎡 Workaround for sql... — committed to mpyw/laravel-unique-violation-detector by mpyw 10 months ago
An alternative to downgrading to PHP 8.1.21 or 8.2.8, if is not possible or not an option, the following could be of help.
Set a custom connection class to be used by Laravel by registering it in the service container:
Extend
SqlServerConnector
:Then, from
AppServiceProvider
, register it in the service container.It has been released!
https://github.com/microsoft/msphpsql/releases/tag/v5.11.1
For those who do not have the option of rolling back to 8.2.8/8.1.21 and have to implement this solution as a stopgap instead:
If you’re adding this custom connector somewhere within the logic of your app (i.e., in
app/Database/Connectors
), don’t forget to either add a backslash before all uses ofPDO
(as I’ve done in the quote above), or add ause PDO;
statement at the top – otherwise you’ll get complaints that the classApp\Database\Connectors\PDO
cannot be found.Okay i already check. This is from PHP side. When you use PHP 8.2.9 and 8.1.22, you will get this kind of problem. Downgrade PHP version to 8.2.8, the problem is solved.
I have same problem with this. Already format a laptop and make a fresh installation with PHP and Laravel. I got same error message
Illuminate \ Database \ QueryException SQLSTATE[IMSSP]: An invalid attribute was designated on the PDO object.
My solution…
I have reviewed the PDO documentation, and you can specify the “error mode” with the PDO::ATTR_ERRMODE attribute: https://www.php.net/manual/en/pdo.error-handling.php
Laravel set the PDO::ERRMODE_EXCEPTION value by default, the quick and easy solution is set value to PDO::ERRMODE_SILENT in
config/database.php
with “options” key`:Another solution here is to create a custom connector and override the binding. This then also gives protection in the future to fix any object issues before a global patch becomes available, albeit you’d need to manage any updates/new requirements too.
Then in
App\Providers\AppServiceProvider
add in the following:Well no one likes doing hotfixes but when you manage something used by so many people that is broken…
Really hoping a final fix isn’t weeks away.
Yes. @SakiTakamachi got that PR merged but still waiting for another msphpsql release. Next release wasn’t planned until end of the year though so waiting to hear back if they will do a patched fix in the mean time (really hope they do)
My solution to this for now was to re-write my docker container to build off the php image instead of Ubuntu. Using apt to install php prevented me from downgrading PHP easily between minor releases.
So if you can downgrade to php 8.1.21 that is the best solution until msphpsql releases a patched version.
@rickycheers
Does this work?I think it can’t be replaced with DI because it’s directly new inConnectionFactory
.Oops, excuse me, you can DI this.
I haven’t had time to test it yet, but I think it will probably look something like this.If you wrap it with try catch, it will work as expected, so I think something like this would work too.
https://github.com/SakiTakamachi/laravel-sqlsrv-err-avoid
@taylorotwell Please unpin this from the “issue” tab since it’s been closed for over 3 months.
Its released! I updated works good.
WIll do production tonight. A
On Fri, Sep 8, 2023 at 1:48 AM Saki Takamachi @.***> wrote:
On a positive note, it looks like there may be a patch this week from Microsoft.
In this case, you don’t have to worry about that.
This is because the exception is raised at the end after the attribute is accepted by the driver.
I would be careful as the long term ramifications of silently killing any PDOException related to setting attributes may cause future issues. Suppose we encounter an issue where the driver from Microsoft drops support for an attribute that we expected to have a certain effect on the results of a query.
~This situation is an example of that. By killing the exception from trying to set PDO::ATTR_STRINGIFY_FETCHES, values returned from a query may have a different type than your application is expecting.~
Edit: As noted by Saki below, she did test that the try/catch solution for this scenario is fine. However, I do think it is worth being careful with the try/catch solution, as it will catch any PDOException related to setting attributes, not just for this specific scenario. Ideally, this would never be an issue, as Saki pointed out in a separate thread, the setAttribute method should only return false on failure (not raise an exception), however we see here that Microsoft’s messed this up once, there’s no telling if they might do it again in the future in a different way that ends up impacting the results of a query.
This is the solution that worked for me.
In
App\Providers
, I created a file calledCustomSqlServerConnector.php
.I placed the following code in that file:
Then I edited
app/Providers/AppServiceProvider.php
and now the file looks like this:That seems like the cleanest workaround until we see Microsoft update the driver.
Since there was no response, I opened an issue. https://github.com/microsoft/msphpsql/issues/1474
You are right, in that case it returns false positives.
My solution is really quick and temporary… to be able to unlock the environments where the bug is occurring right now.
The final solution should be done at https://github.com/microsoft/msphpsql/
This will give back a result instead of an exception, the value will be [] and the logic after this query will treat it as a REAL VALUE, I think it’s crazy to use this without a custom error handling for each query…
The lead of PDO SQLSRV seems to have a negative opinion of hotfixes. I’m still convinced that the problem is on the PDO SQLSRV side, but it’s also true that it’s getting harder to fix early.
So, I proposed a temporary workaround on the php-src side. If you are following information on this issue, please check this: https://github.com/php/php-src/issues/12038
I see your point, but I think it doesn’t seem to fit the context of this issue.
Don’t use a try catch to swallow errors. That is extremely bad practice.
Hello - just wanted to say thank you! 👍 After about 45mins of searching, I finally found this thread and it tells me everything I needed to know.
@SakiTakamachi thank you for your fix ServiceProvider - time saving!
@huynguyen-twentyci Yes,
PDO SQLSRV
does not supportPDO::ATTR_TIMEOUT
.Also, you should write your other options like this:
I have prepared a repository that will be somewhat better than a steady build. https://github.com/SakiTakamachi/pdo-sqlsrv-extend
However, this should only be used when “there is really no other option but to use this”.
We should revert back to the prev php version and wait for an official driver to be released.
I took a closer look at the code and it looks like it’s throwing a different exception after all. I will prepare a fix PR.
Opps, when I looked at it again, I found that the exception was caught.
I’ll check it out properly again.