2011-03-06 9 views
5

MySQL'e bağlanan ve tüm PDO kodunu tamamlayan bir PHP veritabanı sınıfım var ve veritabanını sorgulamak için kullanıyorum.

$db = new Database($dbConfig); 

Sonra ben hazırlanmış bir sorgu kullanarak gibi veritabanından veri alabilir: Temelde sayfa denetleyicisi ben yeni bir nesne yapmak

$params = array('username' => $username); 
$result = $db->preparedSelect('select password, salt from users where username = :username', $params); 

hangisi yeni doç içine kopyalar PDO deyimi sonuçları dizi ve arama sonuçları sadece veritabanı sonuçlarını döndürür. Öyle gibi basit bir foreach ile onların aracılığıyla yineleme:

foreach ($result as $key => $val) 
{ 
    $password = $val['password']; 
    $salt = $val['salt']; 
} 

Tamam bu yüzden yöntemlerin bazılarında veritabanına erişebilmek başka sınıf benim $ db nesneyi kullanmak istiyorum diyelim. Şu anda diğer sınıf şuna benzer:

yapıcı gibi görünmelidir ama eğer merak ediyorum iyi çalışıyor
class General 
{ 
    // Database object 
    private $db; 

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

:

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

ben bunu geçiyorum anlamına gelmelidir Yani referans yoluyla ve nesneyi diğer sınıfa kopyalamayın. Sınıf içindeki $ db nesnesinin bir kopyasını istemiyorum, varolan veritabanı nesnesini kullanmasını istiyorum, böylece belleğin kullanımıyla ilgili çok sayıda kopyası yok.

$ db veya & $ db olarak iletilmesi arasında PHP5'te bir fark var mı? Bazı okuma yapmaktan, PHP5 varsayılan olarak nesneler referans ile geçer ve şimdi söyleyen diğer insanlar bu Java yolu yapar ve bazıları & kullanarak her ne olursa olsun bir sabit bağlantı yapar. Kafam karıştı. Bunu yapmanın en iyi yolu nedir?

Çok teşekkürler!

cevap

8

Bir fark var, ama gerçekten düşünebileceğiniz bir fark değil.

PHP5'te, bir nesneyi tutan "$ db" temel olarak C veya C++'daki "Foo *" ya eşdeğerdir. Diğer bir deyişle, $ db tüm nesneyi saklamaz, sadece kodun nesneyi gerektiğinde bulmasını sağlayan küçük bir jetonu depolar. Bu jetonu değer olarak ilettiğinizde, tüm nesnenin bir kopyası yerine tamsayı değerinden geçme kadar hızlıdır. Ancak, $ db atarsanız, arayandaki değeri değiştirmezsiniz çünkü yerel değişkeninizi jetonu farklı bir belirteç içerecek şekilde değiştirirsiniz.

İşlevi "& $ db" alırsa, temel olarak "Foo **" yi C'ye geçirme eşdeğeri veya daha doğrusu C++ 'da "Foo * &" alan bir işlevdir. Çağrı, aynı boyutta olduğu kadar hızlıdır, ancak $ db'ye atanırsanız, işlevin içinde $ db değerini değiştirecektir, çünkü "referansa göre geçirme" değişkeni belleğe işaret eder. Arayandaki belirteci tutan konum.

Bunu yapmanın en iyi yolu, ne yaptığınızı ve neden bunu yaptığınızı bilmedikçe ("&" kullanmayın) değere göre geçmektir.

+2

Yani, eğer _construct ($ db) yaparsam ve $ db nesnesinin içindeki bir değeri değiştirirseniz, ör. $ db-> testvar = 1 Hafızada iki $ db nesneye sahip olacağım, orijinal ve testvarın bir '1' içerdiği yeni olan. Bu doğru mu? Eğer _construct (& $ db) yaparsam, $ db-> testvar = 1 atayım, orijinal nesneyi etkilemeli ve bellekte yalnızca bir $ db nesne örneği var. Bu doğru mu? – zuallauz

+5

Hayır, her iki durumda da değiştirilen değerle tek bir nesneye sahip olacaksınız; İlk işlevde, eğer $ db = null 'yaparsanız, arayan kişi hala orijinal $ db değerine sahip olurken, ikinci fonksiyonda arayan artık orijinal $ db'ye sahip olmayacaktır. – Anomie

3

Bu güzel bir soru.

Her zaman bir $ db tutamacını açıp, bir işleve geçirerek ve aynı nesne olduklarından emin olmak için bunları === işleciyle kontrol ederek bir sınama yapabilirsiniz.

+1

: Yani yapmanız gerekir hepsi veritabanına çağrı yapmak istediğiniz diğer sınıflarında

class DB { private static $db = FALSE: public static function init($dbConfig) { if(! self:$db) { self::$db = new Database($dbConfig); } } public static function preparedSelect($sql, $params) { if(! self::$db) { die("call the init method first"); } // db stuff, where you would call $this->db call self::$db } } 

. Bence orijinal $ db nesnesinin bir kopyasını yapmak için $ db klonunu kullanmalısınız. Aksi takdirde, $ db nesnesine başka bir sınıfın içinden yaptığınız değişiklikler, orijinali de güncelleyecektir. – zuallauz

3

Bu, statik yöntemler için iyi bir iş olabilir. Bu, birçok çerçevenin aynı görevi gerçekleştirmesidir. Bir test yaptık ve onlar tam olarak aynı nesne gibi görünen

class General 
{ 
    public function __construct() 
    { 
     DB::init($dbConfig); 
    } 

    public function someMethod() 
    { 
     $params = array('username' => $username); 
     $result = DB::preparedSelect('select password, salt from users where username = :username', $params); 

    } 
} 
+1

Bunun için Statik yöntemleri kullanmak üzereydim, ancak araştırmadan sonra Genel sınıfınızdaki (şu anda DB) olan bağımlılıkların hemen fark edilmediğini ve çizgide karışıklığa neden olabileceğini gösterdi. Statik yöntemler/singletonlar bu şekilde kullanılmamalıdır - bunun yerine * Bağımlılık Enjeksiyonu * kullanılmalıdır/değişkeni yapıcıya açıkça aktarmalıdır, böylece sınıflara bağlı olarak tam olarak görülebilir :) – Jimbo

İlgili konular