PHP OOP ikilem: Bir sınıf nesnesi 'içinde' bir veritabanı bağlantısı tutmak nasıl?

5 Cevap php

Ve burada ben yine buradayım! ;)

Im (iyi, im hala planlama aşamasında) i diğer geliştirici (CMS yapar, drupal, joomla, vb) şekilde theyr kendi eklentileri / modülleri yazmak imkanı verecek bir web uygulaması geliştirme.

Benim sorunum i birçok nedenden (ilk veri bütünlüğü) için, veri tabanları ile etkileşim için yazdığı yöntemleri kullanmak için force geliştiriciler zorunda olmasıdır. Ben gizli veritabanı yapısını korumak için dansçılara gerek yok, ama bu çok mümkün olmadığını, takdir olduğunu.

Yani, kısacası, benim hedeftir:

  1. Keep 'protected' and not accessible from outskimlike my classes the database connection;
  2. Mümkünse (ama 1 noktasında bir sonucu olmalı) gerçek bir veritabanı yapısı gizli tutmak;

Eklentileri / modules davranış Drupal kanca gibi uygulanacaktır.

Yani, benim şimdiki durumun bir kısa örnek:

<?php
    // File dbclass.php
class DbHandler{
    /*
    * As simply as i could ;)
    */
    private $dbLink;
    public function __construct(){
        $this->dbLink = pg_connect("host=127.0.0.1 user=myuser password=mypassword dbname=mydatabase");
    }
    public function __destruct(){
        pg_close($this->dbLink);
        unset($this->dbLink);
    }
}
?>

ve modül çağrı:

<?php
// An general situation
require('dbclass.php');
/*
* The DbHandler consctruct function open a database connection.
*/
$init = new DbHandler();
/*
* [..i'll do something here..]
*/
/*
* Lets say this is inskimlike a function/hook of an enabled module;
* This is the behavior i want to avokimlik!
* How to keep the database connection 'within' my
* DbHandler object's instance?
* p.s: in real life i do use prepared stmt
*/
$qrUsers = pg_query('SELECT * FROM users');
if(pg_num_rows($qrUsers) != 0){
    echo '<h2>Query success!</h2>';
    //do something
}else{
    echo '<h2>Query Fail!</h2>';
}
//Actual Output: Query Success! [...]
//Deskimlikered output: Warning: pg_query() [function.pg-query]: No PostgreSQL link opened yet in /var/www-lighttpd/dbtest.php on line xx Query Fail!
?>

Ben geliştirici doğrudan bir sorguyu yürütmek için çalışırsanız, başarısız olur, ve ben yayınlanmıştır örnekte, o (örneğin) gibi bir yöntemi kullanmak zorunda olduğunu istiyorum

$users = new User();
$users -> get_all();

Im postgresql üzerinde çalışan, ama sorun Mysql aynı olduğunu varsayalım.

Bildiğim kadarıyla ben düşünce olarak, ben bunu yapabilirim only yolu bağlantısını before tüm modülleri kanca arayın ve sonra bir kanca CRUD gerekir her zaman yenkimliken ve tekrar kapatılabilecek kapatmak için veritabanı. Ama gerçekten bu çözümü sevmediğim, alışkanlık verimli olabilir.

Birisi betters fikirleri varsa, bunları benimle paylaşın lütfen!

ps: benim ingilizce kötü, ben soru açıktır umuyoruz.

EDIT: the Oddthinking solution seem to be the best for me: the opening and immediately closing the ghost connection will prevent every next pg_* or mysql_* function call. This solution, in couple with renaming the pg_* or mysql_* functions with runkit / apd with custom names will (i think) definitely avokimlik any uncontrolled access to the DB by the modules/plugins.

5 Cevap

Bir kesmek biraz, ama:

Eğer pg_connect arama yapmak hemen sonra, bazı dandik parametreler ile pg_connect diyebiliriz. Bu başarısız, ama aynı zamanda pg_dbname bunu kullanmasını engellemek için varsayılan bağlantı geçersiz kılar göreceksiniz ..

EDIT: Bu dandik parametrelerle pg_connect'i çağırarak varsayılan bağlantı geçersiz DEĞİLDİR ki (yorumlara bakınız) çıkıyor.

Burada Plan B (denenmemiş) olan:

$this->dbLink = pg_connect("host=127.0.0.1 user=myuser password=mypassword dbname=mydatabase");
$junkConnection = pg_connect("host=127.0.0.1 user=myuser password=mypassword dbname=mydatabase");
pg_close($junkConnection);

Bu veritabanına ikinci bir bağlantı oluşturur, ama hemen kapatır. Ben ciddiye ilk bağlantı dönmeden varsayılan parametreleri bırakacaktı şüpheliyim.

Iki seçenek akla gelmektedir:

  1. (Bu durum için yetersiz gibi geliyor?) Kodu yerine dokümantasyon / standartlarında bu zorla

  2. PDO pgsql yerine pg_* API kullanın.

Son çare olarak bu açılması / kukla DB bağlantıları kapatılıyor gibi kesmek çalışacaktır ama ben düşünecektim.

Eğer sisteminizde kalitesini ve eklentileri temin etmek istiyorum gibi geliyor. Ben bu kesmek bu amacı yenilgi düşünüyorum. Hiç şüphe yok ki ben burada bazı varsayımlar yapıyorum, ama genel konuşmak gerekirse, ben en iyi yolu, yazar ve iyi belgelerine plug-in katı örnekler / standartları sunmak olduğunu düşünüyorum. Eğer eklentileri için bir yetkili depo sahipliği yapacak olursa, o zaman da bu gibi ihlaller için kendi kodunu taramak ve bakıcılarına bunları düzeltmek olduğunu hatırlatıyoruz.

Belki de sizin ihtiyaçlarınıza uygun olabilir, decorator pattern duydum. Bu fikir aslında tam olarak gerçek veritabanı gibi davranır veritabanı nesnesinin bir vekil örneğini oluşturmak için var. Bu nedenle, gerçek bir veritabanı diğerlerine gizlidir ve sadece decorater nesne nerede gerçek veritabanı bulmak için bilir.

Hm, belki DB düzeyinde bu çözebilir?

Sen db üzerinde iki kullanıcı hesaplarını olabilir. Eğer denilen sıfır ayrıcalıklar vardır biri ile-ve bağlandığınız app-main falan denir uygun ayrıcalıklar, vardır bir app-plugin. Daha sonra, bu gibi eklenti diyebiliriz:

pg_query("SET ROLE app-plugin;"); //precaution--use low-privilege-user
$plugin->doStuff();
pg_query("SET ROLE NONE;"); //Reset role back to default

Bu geçerli oturum için app-plugin-kullanıcı o indirdi ayrıcalıklar olurdu. Tabii ki, eklenti tekrar kendini ayrıcalıklarını yükseltmek için "SET ROLE NONE;" diyebiliriz, bu nedenle "güvenli" değil. Bu sadece bir önlem gibi olurdu. Ama bağlantısı en az yaşatılması olacağını ve normal sorgular başarısız olur. (Eklenti bir oturumu sırasında 50 kere falan denir alırsa Tabii ki kim bilir .. performansını etkileyebilir?)

Anyway, I have never tried this mysqlf so I don't know anything about this, really..

Docs:
http://www.postgresql.org/docs/8.4/interactive/sql-set-role.html

Ben bir şey ama as long as users can read your code they can copy & paste the information needed to make their own connection eksik olabilir. Eğer gerçekten kullanıcıların veritabanına bağlanmak için izin var mı?!

Bu, etkin bir modülün bir fonksiyonu / kanca içeride olduğunu söylüyorlar sağlar;

Bu i kaçınmak istediğiniz davranış!

SEÇİN * ...

Bu senin sorunun değil. Benim tahminim kullanıcıların kendi çevre / veritabanı (ler) deki app ev sahipliği yapacak edildiği, bunun için daha iyi alternatifler sağlanan zaman kötü uygulama hasar alıyor.