Подготавливаемые запросы
Всем добрый день!
Не совсем понимаю, почему при формировании запросов с помощью mysqli мы можем присвоить значения переменным после того, как передали их в метод bind_param?
$conn = new mysqli('localhost', 'Phil', '123', 'publications');
if ($conn->connect_error) die($conn->connect_error);
$stmt = $conn->prepare('INSERT INTO classics VALUES(?,?,?,?,?)');
$stmt->bind_param('sssss', $author, $title, $category, $year, $isbn);
$author = 'Emily Brontë';
$title = 'Wuthering Height';
$category = 'Classic fiction';
$year = '1847';
$isbn = '9780553212587';
$stmt->execute();
printf("%d ROW inserted.\n", $stmt->affected_rows);
$stmt->close();
$conn->close();
А вот мой код, в котором я пытаюсь воспользоваться такой же возможностью. Но на экран ничего не выводится.
class test_class
{
public $variable = 'default value';
function give_param($variable)
{
$this->variable = $variable;
}
function execute()
{
echo $this->variable;
}
}
$obj = new test_class();
$obj->give_param($variable);
$variable = 'abc';
$obj->execute();
Ответы (2 шт):
Если вы посмотрите определение метода bind_param, то он принимает не переменные, а ссылки на переменные &$var. Читайте как используются ссылки на переменные в PHP.
class test_class
{
public $variable = 'default value';
function give_param(&$variable)
{
$this->variable = &$variable;
}
function execute()
{
echo $this->variable;
}
}
$obj = new test_class();
$obj->give_param($variable);
$variable = 'abc';
$obj->execute();
Это хороший вопрос, и у него есть два ответа - теоретический и практический.
Теоретический ответ
состоит в том, что переменная в bind_param передаётся по ссылке. Если посмотреть на описание функции в мануале, то можно увидеть значок & перед именем переменной. Вот это оно и есть.
Почитать про ссылки можно в мануале.
Если очень грубо, то мы передаем в функцию не значение, а только имя переменной (хотя корректнее говорить - ссылку на переменную), с которой будем работать. Одним из побочных эффектов этого будет возможность работать с переменной, которая ещё не определена на момент вызова функции.
Практический ответ:
Почему это сделано? Передача по ссылке нужна для того, чтобы можно было сначала подготовить запрос и привязать к нему переменные, а потом несколько раз вызвать execute, с разными значениями:
$stmt = $db->prepare("UPDATE users SET status = ? WHERE id = ?");
$stmt->bind_param("ss", $status, $id);
foreach ($data as $id => $status) {
$stmt->execute();
}
Важное предупреждение
Злоупотреблять таким подходом не стоит. Если нет серьёзных причин передавать переменную по ссылке, этого делать ни в коем случае не стоит. Вы на собственном примере убедились, что такой подход запутывает разработчика и усложняет понимание кода.
Поэтому в вашем собственном варианте просто определяйте переменную до использования. Поскольку в вашем случае нет ни одной причины делать по-другому.