이 wrapper for PDO'좋은 코드'?이 있는 모든 잠재적인 문제가 있습니까?

StackOverflow https://stackoverflow.com/questions/617646

  •  03-07-2019
  •  | 
  •  

문제

나는 이 클래스는 작업 PDO 을 만들기 위해,SQL 쿼리'쉽'고 적은 걱정 없습니다.

여기에는 나의 생각을

  • 그것이 더 좋아 등 DB 확장 PDO?
  • 쿼리 방법을 너무 큰?그것으로 분할할인 방법이라고 하는..이것이 알려진 것으로 느슨한 커플링?
  • 내 방법을 검출하는 선택을 쿼리가 너무 못생긴 그 자체에 대한 좋은?
  • 다른 어떤 문제가 분명하다?으로 나는 일종의 학습으로 나-이동,거래가 성사될 수 있다고 확신이 간과 많은 문제가 발생할 수 있습니다.

감사

`

 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;

    }
 }
도움이 되었습니까?

해결책

그것은 나쁘지 않다고 말했다 그것은 도움이 될 수 있는 작은 응용 프로그램이지만 그것은 대부분이 아주 얇은 추상화에 또 다른 추상화입니다.그것은 데리고 다른 사람의 많은 기능입니다.

무언가를 고려할 수 있는 다른 것들 사이에서,:

  • 이 PHP5 코드,사용 예외trigger_errorset_exception_handler 때까지 필요한 경우 예외는 더 널리 퍼져있지만,그것은 확실히 깨끗하고 미래의 증거입니다.
  • 당신이 사용하는 단일,그것은 나쁜 것은 아니지만 반드시 그러나 이 경우에는,예를 들어,하나의 단점이 될 것입니다 당신만을 처리할 수 있는 하나의 연결하는 하나의 데이터베이스.
  • 내가 알지 못하는 경우에 당신의 저장된 절차에,하지만 저장 프로시저 할 수 있는 결과를 반환트 을 통해 query() 방법은 너무입니다.
  • 당신은 두 가지 세미콜론(;;)의 끝에 new PDO 라인입니다.

그는 말했다,나는 생각하지 않는 쿼리에는 방법이 너무 크고 많은 될 수 있는 리콜의 다른 곳에서 있습니다.하지만 빨리 당신이 보는 바와 같이 두 개 또는 세 개의 라인에서 호출될 수 있습니다 또 다른 기능,분리습니다.는 좋은 방법 .

다른 팁

예, 아니요.

간단하고 빠르고 더러운 응용 프로그램을위한 좋은 코드입니다.

더 복잡한 구조화 된 응용 프로그램에서 이것을 사용할 때 문제가 발생합니다. 실행중인 SQL에 따라 오류 처리가 다른 경우.

또한 999가 슈퍼 듀퍼 루틴에있는 "999 라인의 문제"유형 오류로 표시되며 특정 SQL 요청으로 다시 추적하는 데 어려움이 있습니다.

나는 작은 프로젝트에서 항상 이런 종류의 일을한다고 말했습니다.

내가 사용한 내용은 다음과 같습니다 (zzz_config에 대한 참조를 $ globals [ 'db_conf'] 또는 무언가로 바꾸는 것만으로도 :

/**
 * 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];
    }
}

사용량은 다음과 같습니다.

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

목표는 DB 구성을 *.ini 파일 (비 코더로 편집 가능)으로 유지하는 것입니다.

나는 다른 방향으로 가서 PDO를 주변에 래퍼 기능으로 확장하는 수업을 만들었습니다. prepare()/execute(), 그리고 내장 기능보다 훨씬 더 좋습니다 (약간 주관적이지만 ...).

또 하나의 것 : 당신은 설정해야합니다 PDO::ATTR_EMULATE_PREPARES 에게 false 정말 오래된 버전의 MySQL을 사용하지 않는 한 (<= 4.0). 기본값 true, 이것은 큰 두통이며 모호한 방식으로 물건을 깰 수 있습니다 ... 내가 추측하는 것은 당신이 거대한 포장지를 가지고있는 이유입니다. bindParam() 처음에.

귀하의 질문에 답하기 위해, 좋은 코드인지 여부는 스스로에게 물어보십시오.
PDO를 직접 사용하는 것과 비교하여 내 코드의 부가 가치는 얼마입니까?

좋은 답변을 찾으면 코드를 사용하십시오. 그렇지 않다면 PDO를 고수 할 것입니다.

또한 구현을 고려해보십시오 Zend 프레임 워크자체적으로 작동하고 PDO를 지원하는 DB 클래스.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top