PHP, как проверить, нужно ли закрывать MySQLi-запрос? - PullRequest
4 голосов
/ 19 декабря 2009

Я создал простой класс MySQLi для проекта, над которым я работаю, чтобы упростить и упростить извлечение и передачу в БД. ( также для более подробного ознакомления с ООП в PHP )

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

Warning: mysqli_result::close(): Couldn't fetch mysqli_result

Я думаю, что получаю вышесказанное специально, потому что он пытается закрыть запрос дважды подряд.

В настоящее время мой класс может делать подготовленные и неподготовленные заявления. Поэтому я пытаюсь закрыть запросы / заявления в 2 местах. При проверке утверждения я проверяю, подготовил ли я уже утверждение, и если да, мне нужно закрыть старое, прежде чем создавать новое и, наконец, в деструкторе класса.

Я понимаю, что мог бы просто закрыть запрос / оператор после того, как извлек и сохранил результат, но это кажется грязным по нескольким причинам. Для одного это исключает возможность повторного использования подготовленного заявления. Так же как и запретить мне получать некоторую информацию о запросе после его выполнения, такую ​​как затронутые строки и т. П.

Я знаю, что могу просто хранить эту информацию для каждого запроса, а что нет, но похоже, что правильным решением этой проблемы было бы закрыть / освободить запрос / оператор, если мне нужно сделать еще один, и снова в конце сценария.

Я попытался осмотреться и прочесть, как мне правильно справиться с этой задачей, но я ничего не смог придумать.

Итак, мой вопрос, есть ли способ проверить, нужно ли закрыть или освободить запрос или утверждение? Или есть лучший способ решить эту проблему?

Спасибо за любую помощь или понимание, которое может предложить каждый.

Ответы [ 6 ]

1 голос
/ 19 декабря 2009

Я думаю, что если в наборе результатов не осталось строк, он должен автоматически закрыться. Таким образом, если вы перебираете весь набор результатов, нет необходимости вызывать mysqli_result. Однако вы должны закрыть его, если, скажем, выбираете только первую строку из набора результатов, содержащего около 100 строк.

0 голосов
/ 07 ноября 2018

Самый безопасный способ, который я нашел:

try { 
    $result->close(); 
} 
catch (Exception $exception){}
0 голосов
/ 19 сентября 2013

Если результат запроса mysqli уже равен null, в PHP 5 вы получите следующее предупреждение:

 Warning: myfunction(): Property access is not allowed yet in ....

В принципе, можно обрабатывать эти случаи с помощью специального обработчика ошибок или просто подавлять предупреждения / ошибки, т.е. is_object($mysqliqresult) && @$mysqliqresult->free()

В качестве альтернативы используйте mysqli- statements через метод prepare, вместо непосредственного запуска запроса mysqlidblink->, как показано ниже:

$query = "SELECT heptagon,hexagon FROM pentagon ORDER BY hexagon";
$stmt = $dblink->prepare($query);
$stmt->execute();
!$stmt->field_count() && $stmt->free_result();

Предложение Джастина тоже хорошо.

0 голосов
/ 22 декабря 2009

Это то, что я использую. Если в заявлении есть какие-либо результаты, я знаю, что должен освободить результат:

if($stmt->num_rows() != 0)
{
    $stmt->free_result();

    return FALSE;
}
0 голосов
/ 19 декабря 2009

Вы можете использовать RAII или фабричный класс + подсчет ссылок для управления операторами. Таким образом, вам не нужно явно проверять, когда пора что-либо закрывать. Не видя деталей того, как вы используете свою обертку, трудно вдаваться в детали. Также может пригодиться шаблон доступа Objective-C, который будет выглядеть примерно так:

private function unsetStatement() {
    if (isset($this->_stmt)) {
        $this->_stmt->close();
        unset($this->_stmt);
    }
}
function getStatement() {
    return $this->_stmt;
}
function setStatement($stmt) {
    $this->unsetStatement();
    $this->_stmt = $stmt;
}

Вы бы когда-либо могли получить доступ к полю члена оператора только через указанные функции, даже внутри класса. На самом деле это выглядит как:

-(Statement *)statement {
    return stmt_;
}
-(void)setStatement:(Statement *)stmt {
    [stmt_ release];
    stmt = [stmt retain];
}
0 голосов
/ 19 декабря 2009

Вы можете установить его на null после того, как закроете его и проверить на ноль в деструкторе, прежде чем закрыть его там.

Очевидно, что вы захотите обнулить подготовленное утверждение только тогда, когда вы уверены, что вы его закончили.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...