Yiiがpdo_をサポートしていない場合mysqlのサーバー
http://www.rritw.com/a/shujuku/Mysql/20140329/442735.html
これは本当にうっとうしいことです.プロジェクトのサブプロジェクト(cms)の中で擬静的かつ迅速に完成するためにYiiを選択しました.
各方面に用意されています.ルート規則、inx rewrite、mysql slaave…しかし、サーバーにpdoがありません.mysql駆動、その時はびっくりしました.プロジェクトはすでにオンラインになりました.再コンパイルはもうあまり実際的ではありません.ファイルを考えるしかないです.つまり、YiiはPDO接続方式を提供しているだけです.時間が迫っています.その時に思いつきました解決方法:他のサーバからphp_をコピーします.mysql.so sql処理ロジックを書き換え、mysqli実現(Yiiを捨てたDAO)に変更する. mysqliシミュレーションpdoを使用する. 最初の方法は一番簡単ですが、そうしなかったです.php-fpmを再起動する必要があります.成功と安定性を保証するのは難しいです.
二つ目は同僚の勧めで、コードの量はとても大きいです.それに、こうすれば後戻りが難しくなります.もう一度テストしなければなりません.
第三のは悪くない解決策です.そしてYiiは指定pdoClassを支持しています.フレームと既存のコードに侵入性がなく、短期間でも実現できます.だからこれにします.
データベース読み取り専用なので、あまり多く考えず、すべての方法を実現するつもりもなく、YiiのDAO処理部分を読んで、この二つのクラスを簡単に書きました.
最後に、偽静的な問題を提起します.フレームのルートの方式に対して、インゲンの設定pathinfoはサポートしています.面倒なだけではなく、一定のリスクがあります.実は、必要ないです.rewriteでいいです.
PS: stackoverflowは本当にいいところです.たくさんの問題を解決しました.例えば、このrefValuesの方法です.
これは本当にうっとうしいことです.プロジェクトのサブプロジェクト(cms)の中で擬静的かつ迅速に完成するためにYiiを選択しました.
各方面に用意されています.ルート規則、inx rewrite、mysql slaave…しかし、サーバーにpdoがありません.mysql駆動、その時はびっくりしました.プロジェクトはすでにオンラインになりました.再コンパイルはもうあまり実際的ではありません.ファイルを考えるしかないです.つまり、YiiはPDO接続方式を提供しているだけです.時間が迫っています.その時に思いつきました解決方法:
二つ目は同僚の勧めで、コードの量はとても大きいです.それに、こうすれば後戻りが難しくなります.もう一度テストしなければなりません.
第三のは悪くない解決策です.そしてYiiは指定pdoClassを支持しています.フレームと既存のコードに侵入性がなく、短期間でも実現できます.だからこれにします.
データベース読み取り専用なので、あまり多く考えず、すべての方法を実現するつもりもなく、YiiのDAO処理部分を読んで、この二つのクラスを簡単に書きました.
<?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で2行追加しました./**
* pdo_mysql , , , components ;
* PDO_Mysql ,
*/
if(!in_array('mysql', PDO::getAvailableDrivers())){
$config = require($config);
$config['components']['db']['pdoClass'] = 'PDO_Mysql';
}
途中で言わなければならない問題がありました.YiiのCDbDataReaderはIteratorインターフェースを実現しました.foreachを使って全期間を使います.PDOSTtement:fetch()は入手できない時にブートに戻らなければなりません.NULLに戻るのは死のサイクルです.最後に、偽静的な問題を提起します.フレームのルートの方式に対して、インゲンの設定pathinfoはサポートしています.面倒なだけではなく、一定のリスクがあります.実は、必要ないです.rewriteでいいです.
rewrite ^/html/(.*)$ /html/index.php?r=$1;
他の関連コードと配置は共有できません.PS: stackoverflowは本当にいいところです.たくさんの問題を解決しました.例えば、このrefValuesの方法です.