PHP PDO закрывает соединение с нулевым значением, но возвращает оператор - PullRequest
0 голосов
/ 30 января 2019

Я создал класс, который подключается к БД.Все остальные классы могут затем использовать функцию соединения в этом классе, чтобы открыть соединение с БД.В конце функции я возвращаю результаты.Итак, как мне закрыть соединение после того, как я вернул результаты?

<?php

class DbhPdo {
  private $servername;
  private $username;
  private $pwd;
  private $dbname;

  protected function connect() {
    $this->servername = "localhost";
    $this->username = "someUser";
    $this->pwd = "somePswd";
    $this->dbname = "someDB";
    $this->charset = "utf8mb4";

    try{
      $dsn = "mysql:host=" . $this->servername . ";dbname=" . $this->dbname . ";charset=" . $this->charset;
      $pdo = new PDO($dsn, $this->username, $this->pwd);
      $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      return $pdo;
    } catch(PDOException $e) {
      echo "Message: " . $e->getMessage();
    }
  }
}

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

$pdo = null;

Или PDO автоматически закрывает это соединение, потому что оно выполняет команды после - return $ pdo?

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

Следующееэто класс, который расширяет вышеупомянутый класс, но я также возвращаю результаты в этом классе, поэтому я не могу установить здесь также значение stmt, равное нулю:

<?php

require_once('dbh.pdo.inc.php');

class LoginPdo extends DbhPdo {
  public $name;
  public $pass1;
  public $hashed;
  public $salted;


  protected function getSomething($name) {
    try{
      $stmt = $this->connect()->query("select something from table where name ='" . $name . "'");
      return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }catch (PDOException $e){
      echo 'Message: ' . $e->getMessage();
    }
  }
}

, что оставляет исходный класс, который начал это:

  try{
    $this->result = $this->getSomething($this->name);
    echo json_encode($this->result);
    $this->result = null;
  }catch (PDOException $e){
    echo 'Message: ' . $e->getMessage();
  }

Будет ли установка $ this-> result = null закрывать соединение?Если это так, то я не понимаю.Может кто-нибудь объяснить это мне?Или я правильно понимаю, что при установке $ pdo = null мне нужно закрыть соединение?

Если это так, то как я могу установить значение null после выполнения возвращаемого $ pdo?

Заранее спасибо

Обновление: На всякий случай, если кто-то еще хочет иметь возможность проверить, было ли закрыто соединение, это были шаги, которые я предпринял, чтобы подтвердить @ Don'tPanicкомментарии к хвостовым файлам общего журнала:

mysql -u root -p
show variables like '%log%';
set global general_log=ON;

tail -f /usr/local/mysql/data/<your log file's name>.log

, которые затем показали соединение, так как я использовал PostMan для публикации следующего запроса, были открыты и закрыты мгновенно:

190130 11:00:17  2581 Query show variables like '%log%'
190130 11:02:14  2582 Connect   root@localhost on <table name>
    2582 Query  select * from something where name ='whatever'
    2582 Quit

Это было выполненоследуя ответу @ Don'tPanic, чтобы добавить новую функцию в класс DbhPdo:

protected function disconnect() {
  $this->pdo = null;
}

Затем я добавил $ this-> pdo = null;после эха json_encode ($ this-> result);

Спасибо за все комментарии

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Установка результата в null не устанавливает соединение в null.

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

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

По сути, вместо того, чтобы просто возвращать соединение, вы проверяете длясуществующее соединение и верните его, либо создайте новое соединение, если оно еще не было установлено, но важной частью является то, что вы устанавливаете свойство $this->pdo вместо использования переменной $pdo, которая существует только в области действия функции соединения.

// ...
private $pdo;

protected function connect() {
    // I suggest setting these in the constructor rather than hard coding them here
    // $this->servername = "localhost";
    // $this->username = "someUser";
    // $this->pwd = "somePswd";
    // $this->dbname = "someDB";
    // $this->charset = "utf8mb4";

    if ($this->pdo) {
        return $this->pdo;
    else {
        try{
            $dsn = "mysql:host=" . $this->servername . ";dbname=" . $this->dbname . ";charset=" . $this->charset;
            $this->pdo = new PDO($dsn, $this->username, $this->pwd);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return $this->pdo;
        } catch(PDOException $e) {
            echo "Message: " . $e->getMessage();
        }
    }
}

Установка $this->pdo вместо использования локальной переменной в функции соединения даст вам то, что вы можете установить на ноль для отключения.

protected function disconnect() {
    $this->pdo = null;
}

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

0 голосов
/ 30 января 2019

Ваш экземпляр API PDO возвращается из $this->connect().Это единственный экземпляр, который вы используете.Если вы хотите сохранить состояние для последующего использования или закрыть его, вы можете использовать:

$stmt = ($con =& $this->connect())->query(...);
$con  = null; # Or use the instance else where
return $stmt->fetchAll(PDO::FETCH_ASSOC);

Если PDOPrepareStatement использует экземпляр PDO по ссылке, вы можете использовать clone для копирования экземпляравместо записи в него.

$stmt = ($con =& clone $this->connect())->query(...);

Ваша переменная $stmt является PDOPrepareStatement, поскольку PDO::query не возвращает экземпляр PDO, поэтому вы уже устанавливаете его в null.

Обратите внимание: вам следует подумать о разработке одноэлементного подхода, если вы хотите создавать модели.Вы можете взглянуть на пример, который я сделал для Laravel

trait Singleton
{
    private static $instance;

    public static function getInstance()
    {
        return self::$instance ?? (self::$instance = new self());
    }

    //
}

Затем вы можете создать свою супер модель:

class Model
{
    use Singleton;

    protected $pdo;

    public function __construct()
    {
        // instance your PDO
    }

    public function select()
    {
        // super method all models can use
    }
}

Тогда просто создайте свои модели!

class UserModel extends Model
{
    public function find($id)
    {
        return $this->select(...)->fetch();
    }
}

Вы можете использовать его так:

UserModel::getInstance()
    ->find(1);
...