Подготавливаемые запросы

Всем добрый день! Не совсем понимаю, почему при формировании запросов с помощью 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 шт):

Автор решения: Alex Krass

Если вы посмотрите определение метода 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();
}

Важное предупреждение

Злоупотреблять таким подходом не стоит. Если нет серьёзных причин передавать переменную по ссылке, этого делать ни в коем случае не стоит. Вы на собственном примере убедились, что такой подход запутывает разработчика и усложняет понимание кода.

Поэтому в вашем собственном варианте просто определяйте переменную до использования. Поскольку в вашем случае нет ни одной причины делать по-другому.

→ Ссылка