Qual é a diferença entre bindParam e bindValue?

Respostas:

190

A resposta está na documentação para bindParam:

Diferente de PDOStatement :: bindValue (), a variável é vinculada como referência e só será avaliada no momento em que PDOStatement :: execute () for chamado.

E execute

chame PDOStatement :: bindParam () para vincular variáveis ​​PHP aos marcadores de parâmetro: variáveis ​​vinculadas passam seu valor como entrada e recebem o valor de saída, se houver, de seus marcadores de parâmetro associados

Exemplo:

$value = 'foo';
$s = $dbh->prepare('SELECT name FROM bar WHERE baz = :baz');
$s->bindParam(':baz', $value); // use bindParam to bind the variable
$value = 'foobarbaz';
$s->execute(); // executed with WHERE baz = 'foobarbaz'

ou

$value = 'foo';
$s = $dbh->prepare('SELECT name FROM bar WHERE baz = :baz');
$s->bindValue(':baz', $value); // use bindValue to bind the variable's value
$value = 'foobarbaz';
$s->execute(); // executed with WHERE baz = 'foo'
acrrosman
fonte
667

Na entrada manual paraPDOStatement::bindParam :

[With bindParam] Diferentemente PDOStatement::bindValue(), a variável é vinculada como referência e será avaliada apenas no momento em que PDOStatement::execute()é chamada.

Então, por exemplo:

$sex = 'male';
$s = $dbh->prepare('SELECT name FROM students WHERE sex = :sex');
$s->bindParam(':sex', $sex); // use bindParam to bind the variable
$sex = 'female';
$s->execute(); // executed with WHERE sex = 'female'

ou

$sex = 'male';
$s = $dbh->prepare('SELECT name FROM students WHERE sex = :sex');
$s->bindValue(':sex', $sex); // use bindValue to bind the variable's value
$sex = 'female';
$s->execute(); // executed with WHERE sex = 'male'
lonesomeday
fonte
9
Brilhante, obrigado! Pergunta - por que você pode querer usar um sobre o outro? Como quando seria útil ou necessário ter o parâmetro bind avaliado apenas no tempo execute ()?
Coldblackice
32
@ Coldblackice Se você estivesse executando a consulta várias vezes com dados diferentes. Com isso, bindValuevocê precisará vincular novamente os dados toda vez. Com bindParamvocê só precisa atualizar a variável. A principal razão para o uso bindValueseria dados estáticos, por exemplo, strings ou números literais.
Loneomeday
11
Por exemplo, você deseja usar o bindValue com os valores de retorno da função: $ stmt-> bindValue (': status', strtolower ($ status), PDO :: PARAM_STR);
paidforbychrist
11
queria votar, mas como é 666, vou deixar
eddy147 31/03
219

Aqui estão alguns em que posso pensar:

  • Com bindParam, você só pode passar variáveis; não valores
  • com bindValue, você pode passar ambos (valores, obviamente, e variáveis)
  • bindParamfunciona apenas com variáveis ​​porque permite que os parâmetros sejam dados como entrada / saída, por "referência" (e um valor não é uma "referência" válida em PHP) : é útil para os drivers que (citando o manual):

suporta a invocação de procedimentos armazenados que retornam dados como parâmetros de saída e alguns também como parâmetros de entrada / saída que enviam dados e são atualizados para recebê-los.

Com alguns mecanismos de banco de dados, os procedimentos armazenados podem ter parâmetros que podem ser usados ​​para entrada (fornecendo um valor do PHP ao procedimento) e saída (retornando um valor do processo armazenado para o PHP); Para vincular esses parâmetros, você precisa usar o bindParam e não o bindValue.

Pascal MARTIN
fonte
@PascalMartin Exatamente o que eu queria saber, você pode vincular valores ao bindParam. Felicidades.
yehuda 28/03
11
Ainda não tenho idéia do que isso significa exatamente, quais são exatamente as variáveis ​​e quais são os valores. Eu uso bindParam para vincular um valor a um espaço reservado e com bindValue eu posso fazer o mesmo! - no meu exemplo, pelo menos ...
Richard
29

De instruções preparadas e procedimentos armazenados

Use bindParampara inserir várias linhas com uma ligação única:

<?php

$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);

// insert one row
$name = 'one';
$value = 1;
$stmt->execute();

// insert another row with different values
$name = 'two';
$value = 2;
$stmt->execute();
Nezar Fadle
fonte
27

Para o objetivo mais comum, você deve usar bindValue.

bindParam tem dois comportamentos complicados ou inesperados:

  • bindParam(':foo', 4, PDO::PARAM_INT) não funciona, pois requer passar uma variável (como referência).
  • bindParam(':foo', $value, PDO::PARAM_INT)mudará $valuepara string após a execução execute(). Obviamente, isso pode levar a erros sutis que podem ser difíceis de detectar.

Fonte: http://php.net/manual/en/pdostatement.bindparam.php#94711

Denilson Sá Maia
fonte
4

Você não precisa mais lutar, quando existe uma maneira como isto:

$stmt = $pdo->prepare("SELECT * FROM someTable WHERE col = :val");
$stmt->execute([":val" => $bind]); 
Thielicious
fonte
4

A maneira mais simples de colocar isso em perspectiva para memorização por comportamento (em termos de PHP):

  • bindParam: referência
  • bindValue: variável
tfont
fonte