Pass parameters by reference when calling bindParam #146
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR fixes issue #143.
In the PHP 8 upgrading internals document, there is this note:
Here are some details about what that means in practice and how it compares to previous PHP releases.
PHP 8.0 emits a warning when a reference is needed and wasn't provided. The runtime still creates a reference, it is just noisy about having to do it.
Prior to PHP 8.0, a flag could be passed in which indicated whether the runtime should create a reference in such scenarios. If a reference was needed and one wasn't provided, the behavior is essentially what PHP 8.0 does (warning, but creates a reference anyway).
In our pdo instrumentation, we call nr_php_call to invoke
bindParam
. This uses PHP'scall_user_function
. At this particular call site, a reference is needed and since we don't provide one, a warning is emitted.The first attempt blindly created a reference for all parameters, but this breaks things as it introduces references where they are not expected. To truly copy the previous behavior, we would need to call ARG_SHOULD_BE_SENT_BY_REF which requires that we resolve the function before invoking
call_user_function
which will have to resolve the function again. This introduces extra overhead which would be best to avoid.We may be able to invoke a
call_user_function
variant that requires the function handle instead of the function name, but this is a more invasive change.The approach in the latest revision chooses to require each call site make the determination about whether a reference is needed before calling
nr_php_call
. If there are places where we usenr_php_call
and friends to make calls to arbitrary functions, such call sites will need to be reworked to programmatically determine whether a reference is needed. In practice, we usually just call a known function. We just now need to be sure to add references, where they are needed, before making such calls.The reported issue was found using Doctrine. The call path creates a prepared statement and calls bindValue for the parameters. I was unable to reproduce the warning message using
bindParam
despite that being what we instrument. I can only assume thatbindValue
somehow depends onbindParam
.The added integration test runs a prepared statement and calls
bindValue
on a single parameter which enough to trigger the warning when the fix is not present.