PDO 'iyi kod' için bu sarıcı?

5 Cevap php

Ben SQL sorguları 'kolay' ve endişelenecek daha az yapmak için, PDO ile çalışmak için bu sınıf inşa.

İşte benim düşüncelerim

  • Daha sınıfı gibi DB PDO'yu uzanır olmalıdır?
  • Sorgu yöntemi çok büyük? O adlandırılan özel yöntemine bölünmüş olmalı .. Bu loose coupling olarak bilinen nedir?
  • O kendi iyiliği için çok çirkin bir SELECT sorgusu tespit benim yolu var mı?
  • Başka ne gibi sorunlar belirgindir? I-go öğrenme-gibi-ben tür olduğum gibi, ben olası sorunları bir çok gözden kaçan olabilir eminim.

Teşekkür ederim

`

 class Db
 {
    private static $_instance = NULL;


    private function __construct() {

    	// can not call me
    }

    private function __clone() {

    	// no!
    }

    public static function getInstance() {

    	if (!self::$_instance)
    	{

    		try {

    			self::$_instance = new PDO('mysql:host=' . CONFIG_MYSQL_SERVER . ';dbname=' . CONFIG_MYSQL_DATABASE, CONFIG_MYSQL_USERNAME, CONFIG_MYSQL_PASSWORD);;
    			self::$_instance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    		} catch(PDOException $e) {

    			trigger_error($e->getMessage());

    		}

    	}

    	return self::$_instance;


    }



    public static function query($query /*string*/, $bindings = NULL)
    {

    	$queryPortion = substr($query,0, 6);

    	try {

    		if ($bindings) {

    				$prepared = self::getInstance()->prepare($query);

    				foreach($bindings as $binding=>$data) { // defaults to string

    					if (!is_array($data)) {
    						$prepared->bindParam($binding, $data); 

    					} else {

    						switch(count($data)) {

    							case 1:
    								$prepared->bindParam($binding, $data['value']);
    								break;							

    							case 2:
    								$prepared->bindParam($binding, $data['value'], $data['dataType']);
    								break;

    							case 3:
    								$prepared->bindParam($binding, $data['value'], $data['dataType'], (int)$data['length']);
    								break;							

    							default:
    								trigger_error('An error has occured with the prepared statement bindings.');
    								return false;
    								break;
    						}
    					}

    				}

    				$prepared->execute();

    				return $prepared->fetchAll(PDO::FETCH_ASSOC);


    		} else if (String::match($queryPortion, 'select')) { // if this is a select query

    			$rows = self::getInstance()->query($query);

    			return $rows->fetchAll(PDO::FETCH_ASSOC);

    		} else {

    			return self::getInstance()->exec($query);

    		}


    	} 
    	catch(PDOException $e)
    	{
    		trigger_error($e->getMessage());
    	}


    }

    public static function getLastInsertId()
    {
    	try {
    		self::getInstance()->lastInsertId();
    	  }
    	catch(PDOException $e)
    	{
    		trigger_error($e->getMessage());
    	}

    }

    public static function disconnect()
    {
    	// kill PDO object
    	self::$_instance = NULL;

    }
 }

5 Cevap

Bu kötü değil ve söylenir gibi çoğunlukla başka bir soyutlama üzerinde çok ince bir soyutlama rağmen küçük uygulamalar için yardımcı olabilir. Başkalarının işlevleri bir sürü getiren değil.

Diğer şeyler arasında, düşünebilirsiniz şey:

Söyleniyor, ben senin sorgu yöntemi çok büyük ve şu anda başka Oradan hatırlanmalıdır ki orada değil çok sanmıyorum. Rağmen kısa sürede başka bir işlevinden denebilecek iki ya da üç satır görmek gibi, bölünmüş. İşte DRY için iyi bir yoldur.

Hayır ve evet

Bu basit, hızlı ve kirli bir uygulama için iyi bir koddur.

The problem comes when you use this in a more complex structured application. Where the error handling will vary depending on which sql you are executing.

Also any severe errors will show up as "problem at line 999" type errors where 999 is in your super duper routine and you will have difficulty tracing it back to a particular sql request.

Ben küçük projeler üzerinde kendimi her zaman bu tür bir şey yapmak olduğunu söyledi sahip.

İşte (sadece $ GLOBALS ['db_conf'] ya da bir şey ile Zzz_Config için başvurular yerine) kullanılan buydu:

/**
 * Extended PDO with databse connection (instance) storage by name.
 */
class Zzz_Db extends PDO
{
    /**
     * Named connection instances.
     *
     * @var array
     */
    static private $_instances;

    /**
     * Retrieves (or instantiates) a connection by name.
     *
     * @param  string $name  Connection name (config item key).
     * @return Zzz_Db        Named connection.
     */
    static public function getInstance($name = null)
    {
        $name = $name === null ? 'db' : "db.$name";
        if (!isset(self::$_instances[$name])) {
            if (!$config = Zzz_Config::get($name)) {
                throw new RuntimeException("No such database config item: $name");
            }
            if (!isset($config['dsn'])) {
                if (!isset($config['database'])) {
                    throw new RuntimeException('Invalid db config');
                }
                $config['dsn'] = sprintf('%s:host=%s;dbname=%s',
                    isset($config['adapter']) ? $config['adapter'] : 'mysql',
                    isset($config['host']) ? $config['host'] : 'localhost',
                    $config['database']);
            }

            $db = self::$_instances[$name] = new self(
                $config['dsn'],
                isset($config['username']) ? $config['username'] : null,
                isset($config['password']) ? $config['password'] : null);
            $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            //$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'Zzz_Db_Statement');

            if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') {
                $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
                $db->exec('SET CHARACTER SET utf8');
            }
        }

        return self::$_instances[$name];
    }
}

Kullanımı olmak whould:

$db = Zzz_Db::getInstance(); // or Zzz_Db::getInstance('some_named_db')
$stmt = $db->prepare('SELECT ...

Amaç fbt db yapılandırmayı tutmaktır. (Olmayan bir kodlayıcı tarafından düzenlenebilir) ini dosyası.

Ben başka bir yol gitti ve çevresinde prepare() / execute() sarıcı işlevleri bir grup ile PDO genişleten bir sınıf yaptı ve fonksiyonları inşa (daha çok güzel olduğunu biraz öznel olsa ...).

Bir başka şey: Eğer mysql gerçekten eski sürümü (<= 4.0) kullandığınız sürece size PDO::ATTR_EMULATE_PREPARES false olarak ayarlamanız gerekir. Bu true, varsayılan büyük bir baş ağrısı olduğunu ve şeyler ben size büyük bir sarıcı var nedeni çevresindeki bindParam() tahmin ediyorum ... karanlık yollardan kırmaya neden ilk etapta.

To answer your question, if it is a good code or not, ask yourself:
What is the added value of my code compared to using PDO directly?

Eğer iyi bir cevap bulursanız, sizin kodu kullanarak için gidin. Eğer değilse, ben PDO sopa ile olur.

Ayrıca kendi başına çalışır ve PDO destekler Zend Framework 'nin DB sınıf uygulama düşünüyor deneyin.