Yii 가 만나면 pdo 지원 하지 않 음mysql 서버

12784 단어 yiipdo
http://www.rritw.com/a/shujuku/Mysql/20140329/442735.html
이것 은 정말 답답 한 일이 다. 프로젝트 의 하위 프로젝트 (cms) 에서 위 정적 을 실현 하고 신속하게 완성 하기 위해 Yii 를 선택 했다.
    모든 면 에서 준비 되 어 있 습 니 다. 경로 규칙, nginx rewrite, my sql slave... 하지만 서버 에 Pdo 가 없습니다.my sql 구동, 그때 놀 랐 어!프로젝트 가 이미 출시 되 었 고 재 컴 파일 은 그다지 현실 적 이지 않 아서 파일 을 해결 하 는 것 을 생각 할 수 밖 에 없다. 즉, 이때 서 야 Yii 가 PDO 연결 방식 만 제공 한 것 을 발견 했다.시간 이 급 해서 그때 생각 한 해결 방법:
  • 다른 서버 에서 php 복사mysql.so;
  • sql 처리 논 리 를 다시 쓰 고 my sql 실현 (Yii 를 버 린 DAO) 으로 바 꿉 니 다.
  • mysql 시 뮬 레이 션 pdo 사용 하기;

  • 첫 번 째 방식 은 가장 간단 하지만 이렇게 하지 않 았 습 니 다. phop - fpm 를 다시 시작 해 야 하기 때문에 성공 과 안정성 을 보장 하기 어렵 습 니 다.
    두 번 째 는 동료 가 추천 한 것 입 니 다. 코드 의 양 이 많 고 이렇게 하면 돌 이 키 기 어렵 고 다시 테스트 해 야 합 니 다.
    세 번 째 는 좋 은 해결 방안 입 니 다. 그리고 Yii 는 PdoClass 를 지정 하 는 것 을 지원 합 니 다. 프레임 워 크 와 기 존 코드 에 대한 침입 성 이 없고 짧 은 시간 안에 실현 할 수 있 기 때문에 이것 입 니 다.
    데이터 베 이 스 를 읽 기만 하기 때문에 많은 고려 도 하지 않 았 고 모든 방법 을 실현 할 생각 도 없 었 기 때문에 Yii 의 DAO 처리 부분 을 읽 고 이 두 class 를 간단하게 썼 습 니 다.
    <?php
    /**
     *   mysqli  PDO           PDO_mysql -_-||
     * @author xl
     * create on 2014-3-26
     */
    class PDO_Mysql{//extends PDO
        
        private $handle = NULL;
        
        private $tmpParams = array();
        
        const MYSQL_ATTR_USE_BUFFERED_QUERY = 1000;
        const MYSQL_ATTR_LOCAL_INFILE       = 1001;
        const MYSQL_ATTR_INIT_COMMAND       = 1002;
        const MYSQL_ATTR_READ_DEFAULT_FILE  = 1003;
        const MYSQL_ATTR_READ_DEFAULT_GROUP = 1004;
        const MYSQL_ATTR_MAX_BUFFER_SIZE    = 1005;
        const MYSQL_ATTR_DIRECT_QUERY       = 1006;
    
        public function __construct($connectionString,$username,$password,$options=array()){ 
            //    
            preg_match('/host=([\w\.]+);dbname=(\w+)/i', $connectionString,$matches);
            if(count($matches)<3){
                throw new PDOException('connectionString is invalid');
            }
            $this->handle = new mysqli($matches[1],$username,$password,$matches[2]);
            //$options
        }
        
        public function beginTransaction(){
            return $this->handle->autocommit(FALSE);
        }
        
        public function commit(){
            return $this->handle->commit();
        }
        
        public function rollBack(){
            return $this->handle->rollback();
        }
    
        public function errorCode(){
            return $this->handle->errno;
        }
        
        public function errorInfo(){
            return array_values($this->handle->error_list);
        }
        
        public function setAttribute($attribute, $value, &$source = null)
        {
            switch($attribute)
            {
                case PDO::ATTR_AUTOCOMMIT:
                    $value = $value ? 1 : 0;
                    if(!$this->handle->autocommit($value))
                    {
                        throw  new PDOException('set autocommit faild');
                    }
                    
                    return true;
                case PDO::ATTR_TIMEOUT:
                    $value = intval($value);
                    if($value > 1 && $this->handle->options( MYSQLI_OPT_CONNECT_TIMEOUT, $value))
                    {
                        $source[PDO::ATTR_TIMEOUT] = $value;
                        return true;
                    }
                break;
                
                case self::MYSQL_ATTR_LOCAL_INFILE:
                    $value = $value ? true : false;
                    if($this->handle->options(MYSQLI_OPT_LOCAL_INFILE, $value))
                    {
                        $source[self::MYSQL_ATTR_LOCAL_INFILE] = $value;
                        return true;
                    }
                break;
                
                case self::MYSQL_ATTR_INIT_COMMAND:
                    if($value && $this->handle->options( MYSQLI_INIT_COMMAND, $value))
                    {
                        $source[self::MYSQL_ATTR_INIT_COMMAND] = $value;
                        return true;
                    }
                break;
                
                case self::MYSQL_ATTR_READ_DEFAULT_FILE:
                    $value = $value ? true : false;
                    if($this->handle->options(MYSQLI_READ_DEFAULT_FILE, $value))
                    {
                        $source[self::MYSQL_ATTR_READ_DEFAULT_FILE] = $value;
                        return true;
                    }
                break;
                
                case self::MYSQL_ATTR_READ_DEFAULT_GROUP:
                    $value = $value ? true : false;
                    if($this->handle->options(MYSQLI_READ_DEFAULT_GROUP, $value))
                    {
                        $source[self::MYSQL_ATTR_READ_DEFAULT_GROUP] = $value;
                        return true;
                    }
                break;    
            }
            
            return false;
        }
        
        public function getAttribute($attribute){
            if(PDO::ATTR_DRIVER_NAME == $attribute){
                return 'mysql';
            }
        }
    
        public function exec($statement){
            $result = $this->handle->query($statement);
            if(is_object($result)){
                mysqli_free_result($result);
                return 0;
            }
            return $this->handle->affected_rows;
        }
    
    
        public static function getAvailableDrivers(){
            return array('mysql');
        }
        
        public function prepare($statement){
            $this->tmpParams = array();
            $newstatement = preg_replace_callback('/(:\w+)/i', function($matches){
                $this->tmpParams[] = $matches[1];
                return '?';
            }, $statement);
            $s = $this->handle->prepare($newstatement);
            if($s==false) {
                throw new PDOException($this->handle->error);
            }
            $ostatement = new PDO_Mysql_Statement($s, $this);
            $ostatement->setPrepareParams($this->tmpParams);
            $ostatement->setStateSql($statement);
            return $ostatement;
        }
    
        public function lastInsertId(){
            return $this->handle->insert_id;
        }
        
        public function quote($param,$parameter_type=-1){
            switch($parameter_type)
            {
                case PDO::PARAM_BOOL:return $param ? 1 : 0;
                case PDO::PARAM_NULL:return 'NULL'; 
                case PDO::PARAM_INT: return is_null($param) ? 'NULL' : (is_int($param) ? $param : (float)$param); 
                default:return '\'' . $this->handle->real_escape_string($param) . '\'';
            }
        }
        
        public function close(){
            $this->handle->close();
        }
        
        public function disconnect(){
            $this->close();
        }
        
        public function __destruct() {
            $this->close();
        }
    }
    
    class PDO_Mysql_Statement {
        
        private $_statement = NULL;
        
        private $_connnection = NULL;
        
        private $_pql = 'unknow';
        
        private $_typeMap = array(
            'i'=>PDO::PARAM_INT,
            's'=>PDO::PARAM_STR,
            'd'=>PDO::PARAM_STR
        );   
       
    
        private $prepareParams =array();//
        
        private $readyTypes = array();
        
        private $readyValues = array();
        
        private $_result = NULL;
        
        private $_mode = MYSQL_BOTH;
    
        public function __construct($_statement,$connnection){
            $this->_statement = $_statement;
            $this->_connnection = $connnection;
        }
        
        public function bindParam($parameter,$value,$type){
            $type = array_search($type, $this->_typeMap);
            $key = array_search($parameter, $this->prepareParams);
            if($key!==false and $type!==false){
                $this->readyTypes[$key] = $type;
                $this->readyValues[$key] = $value;
                return true;
            }else{
                return false;
            }
        }
        
        public function bindValue($parameter,$value,$type){
            return $this->bindParam($parameter, $value, $type);
        }
        
        public function setStateSql($sql){
            $this->_pql = $sql;
        }
    
    
        public function execute($options=array()){
            if(!empty($this->readyTypes)){
                $params =$this->readyValues;
                ksort($params);
                array_unshift($params,implode($this->readyTypes));
                $tempstatement = $this->_statement;
                call_user_func_array(array($tempstatement,'bind_param'),$this->refValues($params));
            }
            $this->_statement->execute();        
        }
        
        public function rowCount(){
            return $this->_statement->num_rows();
        }
        
        public function setFetchMode($mode){
            $mode = $this->transformFetchMode($mode);
            if($mode === false){
                return false;
            }
            $this->_mode = $mode;
            return true;
        }
        
        
        public function closeCursor(){
            //$this->_result = NULL;
            $this->prepareParams =array();
            $this->readyTypes = array();
            $this->readyValues = array();
            $this->_pql = 'unknow';
            $this->_mode = MYSQL_BOTH;
            
            if(!empty($this->_result)){
               $this->_result->free();
            }
            $this->_result = NULL;
           
            //$this->_connnection->close();
           return $this->_statement->reset();
        }
        
        public function columnCount(){
            return $this->_statement->field_count;
        }
        
        public function debugDumpParams(){
            echo $this->_pql;
        }
        
        public function errorCode(){
            return $this->_statement->errno;
        }
        
        public function errorInfo(){
            return array_values($this->_statement->error_list);
        }
        
        public function setPrepareParams($params){
            $this->prepareParams = $params;
        }
        
        public function fetch($mode=NULL){ 
            if($this->_result==NULL){
                $this->_result = $this->_statement->get_result(); 
            }
            if(empty($this->_result)){
                throw new PDOException($this->_statement->error);
            }
           
            $_mode = $this->_mode;
            if(!empty($mode) and ($mode = $this->transformFetchMode($mode))!=false){
                $_mode = $mode;
            }
            $result = $this->_result->fetch_array($_mode);
            return $result === NULL ? false : $result;
        }
        
        public function fetchColumn($column_number=0){
            $column = $this->fetch(PDO::FETCH_NUM);
            return $column[$column_number];
        }
        
        public function fetchAll($mode=NULL){
            if($this->_result==NULL){
                $this->_result = $this->_statement->get_result(); 
            }
            if(empty($this->_result)){
                throw new PDOException($this->_statement->error);
            }
            $_mode = $this->_mode;
            if(!empty($mode) and ($mode = $this->transformFetchMode($mode))!=false){
                $_mode = $mode;
            }
            $result = $this->_result->fetch_all($_mode);
            return $result === NULL ? false : $result;
        }
        
        public function fetchObject(){
            throw new PDOException('Not supported yet');
        }
        
        private function transformFetchMode($mode){
            switch ($mode){
                case PDO::FETCH_ASSOC : return MYSQLI_ASSOC;
                case PDO::FETCH_BOTH  : return MYSQLI_BOTH;
                case PDO::FETCH_NUM   : return MYSQLI_NUM;
                default : return false;
            }        
        }
        
        private function refValues($arr){
            $refs = array();
            foreach($arr as $key => $value){
                if($key!=0){
                    $refs[$key] = &$arr[$key];
                }else{
                    $refs[$key] = $value;
                }
            }
            return $refs;
        }
        
        public function __destruct(){
           if(!empty($this->_result)) {
               $this->_result->free();
           }
           if(!empty($this->_statement)){
               $this->_statement->close();
           }
        }
        
        
                
    }

    모두 PDO 의 방법 입 니 다. 주석 을 달 지 않 고 index. php 에 두 줄 을 추 가 했 습 니 다.
    /**
     *         pdo_mysql    ,     ,       ,   components    ;
     *       PDO_Mysql  ,  
     */
    if(!in_array('mysql', PDO::getAvailableDrivers())){ 
        $config = require($config);
        $config['components']['db']['pdoClass'] = 'PDO_Mysql';
    }

    중간 에 할 수 없 는 질문 이 하나 더 있 습 니 다. Yii 의 CDbdataReader 는 Iterator 인 터 페 이 스 를 실 현 했 습 니 다. foreach 를 사용 하여 반복 할 때 PDOStatement: fetch () 는 줄 을 얻 지 못 할 때 boolean 으로 돌아 가 야 합 니 다. NULL 로 돌아 가 는 것 은 순환 입 니 다.
    마지막 으로 위 정적 인 문 제 를 제기 합 니 다. 프레임 경로 의 방식 에 대해 nginx 설정 pathinfo 지원 은 번 거 로 울 뿐만 아니 라 일정한 위험 도 있 습 니 다. 사실은 크게 필요 하지 않 습 니 다. rewrite 하면 됩 니 다.
    rewrite ^/html/(.*)$ /html/index.php?r=$1;

    다른 관련 코드 와 설정 은 공유 하기 가 불편 합 니 다.
    PS: stackoverflow 는 정말 좋 은 곳 입 니 다. 저 에 게 많은 문 제 를 해결 해 주 었 습 니 다. 예 를 들 어 이 refValues 방법 입 니 다.

    좋은 웹페이지 즐겨찾기