Bind Param с массивом параметров - программирование
Подтвердить что ты не робот

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?

4b9b3361

Ответ 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 );

}

}