web-dev-qa-db-ja.com

パラメータの配列で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クエリステージで出力されるリストに変換する方法はありますか?

21
David G

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は、参照によって2番目以降のパラメーターを想定しています。


編集:あなたのクエリは間違っているようです。たぶん、あなたはそこにある変数よりもフィールドが少ないでしょう。行う:

"INSERT INTO Users (field1, field2, field3, field4, field5, field6) VALUES (?, ?, ?, ?, ?, ?)"

フィールドの名前を正しい名前に置き換えます

27
bwoebi

PHP 5.6以降では、call_user_func_arrayの代わりに引数のアンパックを使用でき、多くの場合3〜4倍高速です。

<?php
function foo ($a, $b) {
     return $a + $b;
}

$func = 'foo';
$values = array(1, 2);
call_user_func_array($func, $values);
//returns 3

$func(...$values);
//returns 3
?>

here から取得。

したがって、コードは次のようになります。

public function bind($query, $type, $params)
        {

            $this->query = $query;
            $stmt = $this->mysqli->prepare($this->query);
            $stmt->bind_param($type, ...$params);
            $stmt->execute;
        }
10
Havardox

$ this-> mysqli-> prepareでなんらかのエラーが発生するため、「非オブジェクトでメンバー関数bind_param()を呼び出す」というエラーが発生する可能性が高くなります。 ( http://php.net/manual/de/mysqli.prepare.php)を参照 -エラーの場合にFALSEを返します。

その問題を解決したら、$ stmt-> bind_paramを呼び出す代わりにこれを試してください。

call_user_func_array(array($stmt, 'bind_param'), array_merge($type, $params));
2
phry

easiestの方法は明らかに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());
}
1

今日、prepareステートメントを使用するより短い方法を作成するために、私はいくつか自分で調査しました。回答@bwoebiは非常に役立ちますが、不明な量のパラメーターに対しては機能しないため、これは彼の回答への追加です。

例えば:

public function bind($query, $type, &...$params)
    {

        $this->query = $query;
        $stmt = $this->mysqli->prepare($this->query);
        call_user_func_array(array($stmt, "bind_param"), array_merge([$type], $params));
        $stmt->execute();
    }

このスレッドを使用する: PHP:可変長引数リスト(参照)?

不明な量のパラメーターをクラス内のバインド関数に渡すことができました。次に、$ type変数の配列マージを使用して、call_user_func_array(...)を使用してbind param関数を呼び出します...(マージのために配列内に配置する必要があります)

これで、$ emailと$ passwordが参照されているこの関数を呼び出すことができます。

$myClass->bind($query, "ss", $email, $password);
0
Mart

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 );

}

}
0
Danijel