когда вызывать mysqli_stmt::close и mysqli_stmt::free_result?

Специалисты, подскажите, в каких случаях желательно вызывать методы mysqli_stmt::close и mysqli_stmt::free_result? На php.net ничего подобного не сказано.

Согласно документации mysqli_stmt::free_result чистит память после mysqli_stmt::store_result. Но если переменная mysqli_stmt итак выходит за область видимости — надо ли вызывать mysqli_stmt::free_result? Работа скрипта при этом продолжается.

Так же согласно документации mysqli_stmt::close надо вызывать для подготовленных запросов, то есть для запросов, для которых был вызван mysqli_stmt::prepare. Но если я дальше не планирую пользоваться запросом, и объект запроса у меня выйдет за область видимости, то надо ли вызывать mysqli_stmt::close?

Так же на php.net про mysqli_stmt::close написано:
Закрывает подготовленный запрос. mysqli_stmt_close() также освобождает дескриптор запроса.
Значит ли это, что буферизированные данные функцией mysqli_stmt::store_result будут корректно очищены при вызове mysqli_stmt::close без предварительного вызова mysqli_stmt::free_result?
  • Вопрос задан
  • 2663 просмотра
Пригласить эксперта
Ответы на вопрос 3
MrShoor
@MrShoor Автор вопроса
Частично сам себе ответил на вопрос. Согласно здравому смыслу, если объект mysqli_stmt будет уничтожен сборщиком мусора, то mysqli_stmt::close и mysqli_stmt::free_result должны быть вызваны в деструкторе, если в этом есть необходимость (поправьте если ошибаюсь).

Осталось разобраться когда произойдет сборка мусора. Для этого был написан тестовый пример:
<?php

class MyClass
{
  public $a;
  public function DoWork()
  {
    $this->a = time(); //на всякий случай чтобы запутать оптимизатор
  }
  public function __construct() 
  { 
    echo('MyClass created<br>');
  }
  public function __destruct() 
  { 
    echo('MyClass destroyed<br>');
  }  
}

function DoSomething()
{
  $tmp = new MyClass();
  $tmp->DoWork();
  //throw new Exception('Exception');
  echo($tmp->a.'<br>'); //на всякий случай чтобы запутать оптимизатор
}

try
{
  echo('before DoSomething<br>');
  DoSomething();
  echo('after DoSomething<br>');
}
catch (Exception $e)
{
  echo($e->getMessage().'<br>');
}

?>

Результат выполнения кода:
before DoSomething
MyClass created
1357535133
MyClass destroyed
after DoSomething

Как видно из результата — чистка мусора вызывается при выходе из функции. Если раскомментировать код с исключением, то результат будет:
before DoSomething
MyClass created
MyClass destroyed
Exception

Объект точно так же уничтожен при выходе из функции DoSomething до обработки исключения блоком catch.

Из этого я сделал вывод (опять же не на 100% верный, но наиболее вероятный) что мой объект mysqli_stmt будет уничтожен сразу же как счетчик ссылок на него станет равным нулю, а значит вызов mysqli_stmt::free_result и mysqli_stmt::close скорее всего произойдет в деструкторе.

А вот вопрос, нужно ли вызывать mysqli_stmt::free_result если вызывается mysqli_stmt::close — остается открытым.
Ответ написан
Комментировать
@mamontoff
Если верить документации — mysqli_stmt::close не только очищает дескриптор запроса, но и сбрасывает его результаты. Следовательно необходимости в предварительном вызове mysqli_stmt::free_result нету.
Ответ написан
Комментировать
romy4
@romy4
Exception handler
Учтите, что это может увеличить время выполнения. На малых объёмах считываемых данных это вообще лишнее.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы