Bind Param с массивом параметров
У меня есть функция, которая делает это:
function registerUser($firstName, $lastName, $address, $postcode, $email, $password)
{
$params = array($firstName, $lastName, $address, $postcode, $email, $password);
$result = $this->db->bind("INSERT INTO Users VALUES (?, ?, ?, ?, ?, ?)", 'ssssss', $params);
}
Отправляется в мой класс базы данных, который делает это:
public function bind($query, $type, $params)
{
$this->query = $query;
$stmt = $this->mysqli->prepare($this->query);
$stmt->bind_param($type, $param);
$stmt->execute;
}
Проблема в том, что это не работает.
То, что я надеялся сделать, заключалось в том, чтобы взять список $params
и перечислить их после $type
, чтобы запрос был похож:
$stmt->bind_param('ssssss', $firstName, $lastName, $address, $postcode, $email, $password);
Но, очевидно, я ошибаюсь.
Есть ли способ сделать массив... как бы преобразованным в список, который будет распечатан на этапе запроса bind_param
?
Ответы
Ответ 1
call_user_func_array()
!
call_user_func_array(array($stmt, "bind_param"), array_merge(array($type), $params));
должен выполнить работу
UPDATE: вы также должны изменить свой массив params:
$params = array(&$firstName, &$lastName, &$address, &$postcode, &$email, &$password);
как mysqli_stmt::bind_param
ожидает второй и следующие параметры по ссылке.
ИЗМЕНИТЬ: Ваш запрос кажется неправильным. Возможно, у вас меньше полей, чем у вас есть переменные. У:
"INSERT INTO Users (field1, field2, field3, field4, field5, field6) VALUES (?, ?, ?, ?, ?, ?)"
где вы заменяете имя полей правильными именами
Ответ 2
Начиная с PHP 5.6 вы можете использовать распаковку аргументов в качестве альтернативы call_user_func_array и часто в 3-4 раза быстрее.
$func = 'foo';
$values = array(1, 2);
call_user_func_array($func, $values);
//returns 3
$func(...$values);
//returns 3
?>
Взято из здесь.
Итак, ваш код должен выглядеть примерно так:
public function bind($query, $type, $params)
{
$this->query = $query;
$stmt = $this->mysqli->prepare($this->query);
$stmt->bind_param($type, ...$params);
$stmt->execute;
}
Ответ 3
Вы получаете свою ошибку "Вызовите функцию-член bind_param() для не-объекта", скорее всего, потому что ваш метод $this- > mysqli- > встречает какую-то ошибку.
(см. http://php.net/manual/de/mysqli.prepare.php - он возвращает FALSE при ошибке, что, кажется, имеет место здесь)
После устранения этой проблемы попробуйте это вместо вашего вызова $stmt- > bind_param:
call_user_func_array(array($stmt, 'bind_param'), array_merge($type, $params));
Ответ 4
Самый простой способ - переход от mysqli к PDO
Это позволит вам делать это так, как вы хотите, и даже без каких-либо дополнительных функций:
function registerUser($firstName, $lastName, $address, $postcode, $email, $password)
{
$sql = "INSERT INTO Users VALUES (NULL, ?, ?, ?, ?, ?, ?)";
$stmt = $this->db->prepare($sql);
$stmt->execute(func_get_args());
}
Ответ 5
Важно отметить, что mysqli_stmt_bind_param()
требует, чтобы параметры передавались по ссылке, поэтому параметры для call_user_func_array()
должны быть ссылкой. Пример, взятый из контекста класса:
function execute( string $query, string $type, array $params )
{
if ( !$stmt = $this->mysqli->prepare( $query ) )
throw new \Exception( 'Prepare failed: ' . $query . PHP_EOL . $this->mysqli->error );
// call stmt->bind_param() with variables to bind passed as a reference
call_user_func_array(
array( $stmt, 'bind_param' ),
array_merge(
array( $type ),
array_map( function( &$item ) { return $item; }, $params )
)
);
if ( !$stmt->execute() )
throw new \Exception( 'Execute failed: ' . PHP_EOL . $stmt->error );
}
}