PDO kapatma bağlantısı


121

MySQLi ile karşılaştırıldığında PDO ile ilgili oldukça basit bir soru.

MySQLi ile bağlantıyı kapatmak için şunları yapabilirsiniz:

$this->connection->close();

Ancak PDO ile bağlantıyı aşağıdakileri kullanarak açtığınızı belirtir:

$this->connection = new PDO();

ancak bağlantıyı kapatmak için ayarladınız null.

$this->connection = null;

Bu doğru mu ve bu aslında PDO bağlantısını serbest bırakacak mı? ( nullAyarlandığı gibi yaptığını biliyorum .) Yani MySQLi ile closebağlantıyı kapatmak için bir işlev ( ) çağırmalısınız . PDO, = nullbağlantıyı kesmek kadar kolay mı ? Yoksa bağlantıyı kapatmak için bir işlev var mı?


11
Sormamın nedeni, bağlantıyı düzgün bir şekilde kapattığımdan emin değilim. ama gerçekten merak
uyandırmadı

2
PHP betiğiniz çalışmayı durdurduğunda veritabanı bağlantısı otomatik olarak kapatılır.
Martin Bean

3
Eğer onu kullanmayı bitirdiyseniz, o zaman neden devam etmiyorsunuz ve sonlandırmıyorsunuz, özellikle de veri tabanıyla etkileşimi bitirdikten sonra biraz zaman alan kod varsa. Yine de, betiğin bitmesini beklemeyle ilgili sorunu gerçekten görmüyorum (DB sunucusuna olan bağlantıları azaltmak dışında)
Kieran

3
github.com/php/php-src/blob/master/ext/pdo/pdo_dbh.c Nasıl çalıştığını kendiniz öğrenin: P
Flosculus

23
Tüm php betikleri kısa ömürlü değildir. Orada php daemonları var. Kişisel olarak açıklığa kavuşturmak için harika bir şey olduğunu düşünüyorum.
datUser

Yanıtlar:


146

Belgelere göre haklısınız ( http://php.net/manual/en/pdo.connections.php ):

Bağlantı , bu PDO nesnesinin ömrü boyunca aktif kalır . Bağlantıyı kapatmak için , nesneye geri kalan tüm referansların silinmesini sağlayarak nesneyi yok etmeniz gerekir - bunu, nesneyi tutan değişkene NULL atayarak yaparsınız. Bunu açıkça yapmazsanız, PHP betiğiniz bittiğinde bağlantıyı otomatik olarak kapatır .

PDO nesnesini kalıcı bir bağlantı olarak başlatırsanız, bağlantıyı otomatik olarak kapatmayacağını unutmayın.


4
Ya bitmeyen bir sürecim varsa? örneğin websocket. Kalıcı bağlantıyı kullanmamanın bir yolu var mı?
Rafael Moni

1
Uzun süre çalışan bir komut dosyasındaki kalıcı bağlantılar için, zaman aşımıyla (örn. My.ini'de) veya başka birkaç nedenden ötürü kasıtlı olarak (veya yanlışlıkla) bağlantıların kesilmesini sağlayabilirsiniz. Bir sorguyu bağlarken veya çalıştırırken, herhangi bir hatayı yakalayın ve "MySQL kayboldu" ise, tekrar bağlanmayı deneyin veya sorguyu ikinci kez çalıştırın.
Frank Forte

1
Note that if you initialise the PDO object as a persistent connection it will not automatically close the connectionAncak bir bağlantı kalıcıysa ve betiği bitmeden önce açıkça NULL çağırırsam, kalıcı olsa bile kapatılacak, değil mi?
tonix

1
@tonix Hayır, yayınlanmalı (başka bir komut dosyası için kullanılabilir hale getirilmelidir), ancak kapatılmamalıdır.
Benjamin

2
@tonix Ben öyle düşünüyorum, evet. Kalıcı bağlantılar hakkında PHP kılavuzundan alıntı : " Uyarı Kalıcı bağlantılar kullanırken akılda tutulması gereken birkaç ek uyarı vardır. Biri, kalıcı bir bağlantıda tablo kilitlemeyi kullanırken, komut dosyası herhangi bir nedenle kilidi açamazsa, daha sonra aynı bağlantıyı kullanan sonraki komut dosyaları süresiz olarak engellenir ve httpd sunucusunu veya veritabanı sunucusunu yeniden başlatmanızı gerektirebilir. "
Benjamin

46
$conn=new PDO("mysql:host=$host;dbname=$dbname",$user,$pass);
    // If this is your connection then you have to assign null
    // to your connection variable as follows:
$conn=null;
    // By this way you can close connection in PDO.

11
IMHO Bunun çok kötü bir model olduğunu düşünüyorum, özellikle bir geliştirici pdo referansının birkaç kopyasını saklayabildiğinde. $ a = yeni PDO (...); $ b = $ a; $ a = boş; Orada, PDO nesneniz sonsuza kadar açık kalacaktır (daemon benzeri bir php programında). Bu, özellikle PDO referansı işlevler ve nesne özellikleri arasında dolaşırken doğrudur ve bunların tümünü boş bırakmayacağınızdan asla emin olamazsınız.
Gabriel

33
PDO'da bir -> close () yöntemi olmalıdır.
Gabriel

5
PDO'yu sevmemek için başka bir neden.
José Carlos PHP

6
@Gabriel - "Birkaç kopya saklamanın" daha da kötü bir model olduğunu düşünüyorum.
Rick James

4
Bu iki satır arasında bir PDOStatement nesnesi oluşturduysanız (yani, her pratik durumda) bu işe yaramaz. Bağlantıyı kapatmak için hem PDO nesnesini HEM DE PDOStatement nesnesini null olarak ayarlamalısınız. Buraya bakın: php.net/manual/en/pdo.connections.php#114822
Ilmari

8

Bağlantıyı null olarak ayarlamaktan daha fazlası. Belgelerin söylediği bu olabilir, ancak bu mysql için doğru değil. Bağlantı biraz daha uzun süre kalacak (60'ları duydum ama hiç test etmedim)

Burada tam açıklamayı istiyorsanız bağlantılarla ilgili bu yoruma bakın https://www.php.net/manual/en/pdo.connections.php#114822

Bağlantıyı kapatmaya zorlamak için şunun gibi bir şey yapmanız gerekir:

$this->connection = new PDO();
$this->connection->query('KILL CONNECTION_ID()');
$this->connection = null;

Cevabınız için teşekkür ederim. Soru uzun zaman önceydi ama bağlantı konusunda haklısın.
Liam Sorsby

PHP üzerinden TCP bağlantısı ile uğraşmanın iyi bir fikir olduğuna aslında katılmıyorum. Tüm düşük seviyeli TCP bağlantı işlemleri soyutlanmıştır, böylece çalışma zamanı sırasında sadece yüksek seviyeli sınıf ve nesnelerle uğraşmamız gerekir. PHP, istek tabanlı bir dildir (muhtemelen bildiğiniz gibi), bu nedenle dB ile potansiyel olarak kalıcı bir bağlantıyı kesmek, kullanıcılar için muhtemelen beklenmeyen hatalara / sorunlara neden olacaktır. Bağlandığınız kullanım durumu büyük olasılıkla sürücünün kalıcı bağlantıyı başka bir istek tarafından kullanılmak üzere açık tutmasıyla sonuçlanır, bu nedenle bunun beklenen davranış olacağını düşünmüştüm.
Liam Sorsby

Aslında mysql'deki işlemler listesine bakarsanız, bağlantıyı hala orada gösterecektir. TCP bağlantısıyla bu şekilde uğraşmamalısınız ve bağlantıyı düzgün bir şekilde kesmenin bir yolu olmalı. Ama durum bu değil. Yani, gerçekten sunucuyla bağlantınızı kesmek istiyorsanız, bunun gibi bir şey yapmanız gerekecek. Bağlantının null olarak ayarlanması, belgelerin söylediklerinin aksine bağlantıyı kesmez.
Cidde

Bu bir açıklaması buldum: stackoverflow.com/a/18277327/1315873
Fil

7

"$ Conn = null;" yerine daha fazla kendi kendini belgeleyen bir talimata sahip olmak için türetilmiş bir sınıf oluşturdum.

class CMyPDO extends PDO {
    public function __construct($dsn, $username = null, $password = null, array $options = null) {
        parent::__construct($dsn, $username, $password, $options);
    }

    static function getNewConnection() {
        $conn=null;
        try {
            $conn = new CMyPDO("mysql:host=$host;dbname=$dbname",$user,$pass);
        }
        catch (PDOException $exc) {
            echo $exc->getMessage();
        }
        return $conn;
    }

    static function closeConnection(&$conn) {
        $conn=null;
    }
}

Böylece kodumu şunlar arasında arayabilirim:

$conn=CMyPDO::getNewConnection();
// my code
CMyPDO::closeConnection($conn);

1
CMyPDO :: __ construct () yöntemini özel yapabilir ve burada tekli kalıp kullanabilirsiniz ..
Aditya Hajare

Evet, mümkündür. Aynı anda birden fazla veritabanı kullanıyorsanız, bağlantı bilgilerini başka bir yöntemle de atamanız gerekir. Fark minimumdur, sadece örnek yöntemlerini çağırmak için biraz daha uzun talimatınız vardır.
Fil

@AdityaHajare Bir alt
sınıfta

@nickdnk, haklısın. Kastettiğim, tek başına bir CMyPDO sınıfı oluşturmaktı (PDO'yu genişletmeden) ve sonra özel bir CMyPDO yapıcısı içinde bir veritabanı örneği oluşturmaktı (yeni PDO ($ dsn, $ dbuser, $ dbpass);) sınıfın yalnızca bir tane olduğundan emin olmak örnek uygulama boyunca mevcuttur (Singleton Design Pattern).
Aditya Hajare

1
@Fil Ancak "dıştaki" kod closeConnection, nesneyi atamak yerine değişkene referansı kopyalaması gerektiğinin farkında olmamalıdır. Başka bir deyişle, yakın bir PDO işlevini kodlamayı deneme yolunuzun kötü yan etkileri vardır ve bu da onu güvenilmez kılar. Bunu yapmanın tek yolu closeConnection, kodda PDO nesnesine kaç referans bulunduğunu kontrol etmek ve 1'den fazla olması durumunda fırlatmaktır.
Xenos

-1
<?php if(!class_exists('PDO2')) {
    class PDO2 {
        private static $_instance;
        public static function getInstance() {
            if (!isset(self::$_instance)) {
                try {
                    self::$_instance = new PDO(
                        'mysql:host=***;dbname=***',
                        '***',
                        '***',
                        array(
                            PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_general_ci",
                            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION
                        )
                    );
                } catch (PDOException $e) {
                    throw new PDOException($e->getMessage(), (int) $e->getCode());
                }
            }
            return self::$_instance;
        }
        public static function closeInstance() {
            return self::$_instance = null;
        }
    }
}
$req = PDO2::getInstance()->prepare('SELECT * FROM table');
$req->execute();
$count = $req->rowCount();
$results = $req->fetchAll(PDO::FETCH_ASSOC);
$req->closeCursor();
// Do other requests maybe
// And close connection
PDO2::closeInstance();
// print output

Özel sınıf PDO2 ile tam örnek.


1
Lütfen kodunuzdan try catch'i kaldırın veya burada gösterildiği gibi içeriye yeni bir atış ekleyin . Şu anda kodunuz hem istisnaları hem de genel olarak hata raporlamasını kötüye kullanıyor
Your Common Sense
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.