PHP bir fonksiyon içine veritabanı bağlantısı / nesnesini almak için en iyi yöntemi nedir?

6 Cevap php

Seçeneklerin bir çift vardır:

$connection = {my db connection/object};

function PassedIn($connection) { ... }

function PassedByReference(&$connection) { ... }

function UsingGlobal() {
    global $connection;
    ...
}

Yani, referans olarak geçti, geçti, ya da küresel kullanarak. Ben yalnızca 1 veritabanı bağlantısı olacak 1 projesi kapsamında kullanılan fonksiyonları düşünüyorum. Birden fazla bağlantı varsa, kesinlikle geçirilen ya da referans olarak geçti.

Ben referans olarak geçti thining ediyorum bir nesne kullanarak PHP5'ta olduğunda gerekli, böylece daha sonra veya global kullan geçmedi 2 olasılık vardır.

Ben her zaman benim fonksiyon parametreleri içine $ bağlantı koyarak yorgun alıyorum çünkü ben soruyorum nedenidir.

6 Cevap

Ben bütün bir uygulaması aracılığıyla DB bağlantıları ve yapılandırma ayarları gibi şeyler işlemek için bir Singleton ResourceManager sınıfını kullanın:

class ResourceManager {
	private static $DB;
	private static $Config;

	public static function get($resource, $options = false) {
		if (property_exists('ResourceManager', $resource)) {
			if (empty(self::$$resource)) {
				self::_init_resource($resource, $options);
			}
			if (!empty(self::$$resource)) {
				return self::$$resource;
			}
		}
		return null;
	}

	private static function _init_resource($resource, $options = null) {
		if ($resource == 'DB') {
			$dsn = 'mysql:host=localhost';
			$username = 'my_username';
			$password = 'p4ssw0rd';
			try {
				self::$DB = new PDO($dsn, $username, $password);
			} catch (PDOException $e) {
				echo 'Connection failed: ' . $e->getMessage();
			}
		} elseif (class_exists($resource) && property_exists('ResourceManager', $resource)) {
			self::$$resource = new $resource($options);
		}
	}
}

Ve sonra fonksiyonlar / nesneleri / nereye kadar:

function doDBThingy() {
	$db = ResourceManager::get('DB');
	if ($db) {
		$stmt = $db->prepare('SELET * FROM `table`');
		etc...
	}
}

Ben iletileri, hata mesajları ve uyarıları, yanı sıra küresel değişkenleri saklamak için kullanabilirsiniz. Ilginç bir soru here aslında sınıfının bu tip kullanmak için ne zaman var.

Nesne yönelimli bir şekilde kodunuzu tasarımı deneyin. Veritabanını kullanacak yöntemler bir sınıf gruplandırılmış olmalı ve sınıf örneği bir sınıf değişkeni olarak veritabanı bağlantısı içermelidir. Bu şekilde veritabanı bağlantısı ihtiyacınız fonksiyonları için kullanılabilir, ancak küresel değil.

class MyClass {
  protected $_db;

  public function __construct($db)
  {
    $this->_db = $db;
  }

  public function doSomething()
  {
    $this->_db->query(...);
  }
}

Ben bir sürü insan statik değişken çeşit önerdi görüyoruz.

Esasen, bir global değişken ve statik bir değişken arasında çok az fark var. Sözdizimi hariç, onlar tam olarak aynı özelliklere sahip. Gibi, statik bir değişken ile global bir değişken yerine, hiçbir şey kazanıyor. Çoğu örneklerde, statik değişken doğrudan sevk değil, statik bir metod (Örn. bir tekil veya statik kayıt) aracılığıyla olmadığını katlanarak bir seviye var. Biraz daha iyi olsa da, bu hala küresel bir kapsam sorunları var. Hiç uygulamasında birden fazla veritabanı bağlantısı kullanmanız gerekiyorsa, mahvolduk. Hiç kod parçaları yan etkileri vardır bilmek istiyorsanız, elle uygulanmasını incelemek gerekir. Bu yapmak veya uygulamayı kıracak şeyler değil, ama onu korumak için daha zor hale getirecektir.

Sana biri arasında tercih öneriyorum:

  • Ihtiyacı fonksiyonlara argüman olarak örneğini geçmek. Bu kadar basit ve dar kapsamın tüm faydaları vardır, ama oldukça hantal alabilirsiniz. Kodunuzun bazı parçaları bir aracı haline sona erebilir, çünkü Ayrıca bağımlılıkları tanıtmak için bir kaynaktır. Eğer bu gerçekleşirse, geçin ..

  • Ihtiyacı yöntemi vardır nesnenin kapsamında örneğini koydu. Örn. yöntemi Foo->doStuff(), bir veritabanı bağlantısı gerekiyorsa, Foo 'nin kurucu içinde geçmesi ve Foo korumalı bir örnek değişken olarak ayarlayın. Hala yöntemi geçen bazı problemleri ile sona erebilir, ama genellikle yöntemleri ile daha hantal kurucular ile daha az sorun var. Uygulama yeterince büyük alırsa, bu otomatikleştirmek için bir bağımlılık enjeksiyon kap kullanabilirsiniz.

Benim tavsiyem kod toplu olarak küresel önlemek için - bu sizi takip etmek ve ısıracak zor, tehlikeli.

Bunu yapardım yolu ya bir yapıcı enjeksiyon ya da ortak bir sınıf içinde statik yoluyla sınıf düzeyinde olabilir getDB adında bir function () sahip olmaktır.

Yani kod olur

class SomeClass
{
    protected $dbc;

    public function __construct($db)
    {
    $this->dbc = $db;
    }

    public function getDB()
    {
         return $this->dbc;
    }

    function read_something()
    {
        $db = getDB();
        $db->query();
    }
}

ya da ortak paylaşılan sınıfını kullanarak.

function read_something()
{
    $db = System::getDB();
    $db->query();
}

Olursa olsun ne kadar çok zarif sistem tasarımı, orada (örneğin DB, Oturum, Yapılandırması gibi) kapsamı zorunlu küresel bir kaç öğe her zaman vardır ve benim System bu gibi statik yöntemler tutmayı tercih sınıf.

Her sınıf olan en iyi I en güvenilir ve izole demek yapıcısı aracılığıyla bir bağlantı Bunu yapmanın en iyi yolu gerektirir.

Ancak bunu yapmak için bir ortak paylaşılan sınıfını kullanarak bunu kullanarak tamamen nesneleri izole etmek için yetenek ve aynı zamanda bu nesneler üzerinde birim testleri yapmak için yeteneği üzerinde etkisi olabilir unutmayın.

Yukarıdakilerin hiçbiri.

Bütün mysql fonksiyonlar veritabanı bağlantısı argüman alabilir optionally. Bu argümana dışarı bırakırsanız, mysql_connect () tarafından son bağlantı varsayılır.

function usingFunc() {
  $connection = getConnection();
  ...
}

function getConnection() {
  static $connectionObject = null;
  if ($connectionObject == null) {
    $connectionObject = connectFoo("whatever","connection","method","you","choose");
  }
  return $connectionObject;
}

Bu şekilde, statik $ connectionObject getConnection çağrıları arasında korunur.