rfc:mysqli_bind_in_execute

This is an old revision of the document!


PHP RFC: mysqli bind in execute

  • Version: 0.9
  • Date: 2021-02-11
  • Author: Kamil Tekiela, dharman@php.net
  • Status: Draft

Introduction

PDO has always offered binding values to the prepared statement directly in the execute() call by providing an array with the values. The same functionality was never present in mysqli, and many users have been confused by that lack of seemingly easy functionality. (See Bug #40891, Bug #31096)

Proposal

I would like to propose adding a new optional argument to mysqli_stmt::execute() same as PDO does with PDOStatement::execute(). The goal of this proposal is to simplify mysqli usage with a simple fix which does not require major refactoring.

This proposal tries to address the following mysqli limitations:

// mysqli can only bind by reference and each variable needs to be passed as a separate argument. 
$id = 1;
$name = trim(' Dharman ');
$stmt = $mysqli->prepare('INSERT INTO users(id, name) VALUES(?,?)');
$stmt->bind_param('ss', $id, $name);
$stmt->execute();
 
// The following would fail and throw an error
$stmt = $mysqli->prepare('INSERT INTO users(id, name) VALUES(?,?)');
$stmt->bind_param('ss', 1, trim(' Dharman '));
$stmt->execute();
 
// Binding an array can be very confusing
$arr = [2,3,5,8,13];
$stmt = $mysqli->prepare('SELECT name FROM users WHERE id IN ('.str_repeat('?,', count($arr) - 1) . '?)');
$stmt->bind_param(str_repeat('s', count($arr)), ...$arr);
$stmt->execute();
 
// SOLUTION:  bind in execute 
// it is now possible to bind by value
$stmt = $mysqli->prepare('INSERT INTO users(id, name) VALUES(?,?)');
$stmt->execute([1, trim(' Dharman ')]);
 
// binding an array becomes less of a chore
$arr = [2,3,5,8,13];
$stmt = $mysqli->prepare('SELECT name FROM users WHERE id IN ('.str_repeat('?,', count($arr) - 1) . '?)');
$stmt->execute($arr);

What about type specifications?

MySQL can type juggle as easily as PHP. The safest way to bind parameters if you are not 100% certain of their type is to bind as a string. In many cases, this is the preferred simplest way. Type specifications should only be used in rare situations when the data should be passed to MySQL with a specific type. In reality, such situations are scarce and they depend on the SQL not on PHP data type. For these rare cases, we can continue using bind_param() with the right type specification.

Difference between PDO and mysqli

While the idea came from PDO bind-in-execute implementation, the mysqli proposal differs in two small ways.

  1. Array keys are completely ignored. mysqli doesn't have emulated prepares nor does it have named parameters. Relying on the array keys/indices would make the implementation unnecessarily complex and it would cause unintentional confusion.
  2. Re-binding empty array throws an error in mysqli. PDO simply ignores an empty array and continues to use previously bound values.

libmysql support?

Unfortunately, I am limited to Windows programming and I have no way of developing the same for libmysql and testing it myself. In theory, it should be possible to add this for libmysql with slight adjustments, but support for libmysql is not actively maintained at the moment and there are more problems that would probably need to be addressed by whoever decides to maintain libmysql support.

Backward Incompatible Changes

None that I can find.

Proposed PHP Version(s)

Next PHP 8.x

RFC Impact

This RFC will have no impact on any existing functionality. We would only be adding a new optional parameter to an existing function.

New Constants

None

php.ini Defaults

None.

Open Issues

Unaffected PHP Functionality

The traditional way of binding variables to placeholders in mysqli remains unchanged. However, it is not possible to mix both styles in the same prepared statement as both expect all parameters to be provided in a single method call.

Future Scope

None, but see related RFC mysqli_execute_parameters

Proposed Voting Choices

Simple yes/no vote.

Patches and Tests

The implementation is available at https://github.com/php/php-src/pull/6271

Implementation

After the project is implemented, this section should contain

  1. the version(s) it was merged into
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature
  4. a link to the language specification section (if any)

References

Links to external references, discussions or RFCs

Rejected Features

rfc/mysqli_bind_in_execute.1613070630.txt.gz · Last modified: 2021/02/11 19:10 by dharman