2013-02-23 6 views
2

Как я могу изменить класс оболочки PDO, так что если я ожидаю, что результат одной строки с моим запросом использует fetch(), и если он ожидает несколько результатов, он использует fetchAll().Как использовать и fetch() и fetchAll() в классе-оболочке PDO?

Прямо сейчас, если у меня есть только один результат, мне все равно придется перебирать массив результатов, и это кажется мне практически невыполнимым.

запросов в модели:

public function doccEdit() { 

    $id = mysql_real_escape_string($_GET['id']); 

    $this->result = $GLOBALS['db']->select("creditcards", "id = ?", $id); 

    print_r($this->result); 

} 

В классе обертке:

public function run($sql, $bind="") { 
    $this->sql = trim($sql); 
    $this->bind = $this->cleanup($bind); 
    $this->error = ""; 

    try { 
     $pdostmt = $this->prepare($this->sql); 
     if($pdostmt->execute($this->bind) !== false) { 
      if(preg_match("/^(" . implode("|", array("select", "describe", "pragma")) . ") /i", $this->sql)) 
       return $pdostmt->fetchall(PDO::FETCH_OBJ); 
      elseif(preg_match("/^(" . implode("|", array("delete", "insert", "update")) . ") /i", $this->sql)) 
       return $pdostmt->rowCount(); 
     } 
    } catch (PDOException $e) { 
     $this->error = $e->getMessage();  
     $this->debug(); 
     return false; 
    } 
} 
+1

Почему бы вам не просто fetchall()? Если есть только одна строка, вы получите один ... – Ben

+0

Потому что я думал, что могу избежать цикла. С fetchall я должен использовать цикл, даже если есть только один результат. –

+0

что здесь делает mysql_real_escape_string? вы правильно форматируете «creditcards»? –

ответ

2

НЕ ПОПЫТАТЬСЯ автоматизировать все

Чем меньше магии в вашем коде, тем легче поддержки и менее болезненных неприятностей.
Не пытайтесь использовать всю логику в одном методе. Это класс! Вы можете создать столько методов, сколько вам нужно.

Когда вам нужно rowCount() - выберите это явно! Это не так сложно.
Но когда вы натыкаетесь на этот код через пару месяцев, вы будете знать, что означает это значение.

Если вам нужна одна строка - используйте метод для получения одной строки. Когда вам нужно много строк - используйте метод, чтобы получить много строк.
Это просто и очень однозначно!

Когда вы включаете обратно в свой код после 2-х месяцев, вы будете иметь абсолютно никаких идей, что делали вы ожидали. Итак - всегда пишите это явно.

Вот отрывок из моей mysqli wrapper class, чтобы дать вам идею:

public function query() 
{ 
    return $this->rawQuery($this->prepareQuery(func_get_args())); 
} 
/** 
* Helper function to get scalar value right out of query and optional arguments 
* 
* Examples: 
* $name = $db->getOne("SELECT name FROM table WHERE id=1"); 
* $name = $db->getOne("SELECT name FROM table WHERE id=?i", $id); 
* 
* @param string $query - an SQL query with placeholders 
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query 
* @return string|FALSE either first column of the first row of resultset or FALSE if none found 
*/ 
public function getOne() 
{ 
    $query = $this->prepareQuery(func_get_args()); 
    if ($res = $this->rawQuery($query)) 
    { 
     $row = $this->fetch($res); 
     if (is_array($row)) { 
      return reset($row); 
     } 
     $this->free($res); 
    } 
    return FALSE; 
} 

/** 
* Helper function to get single row right out of query and optional arguments 
* 
* Examples: 
* $data = $db->getRow("SELECT * FROM table WHERE id=1"); 
* $data = $db->getOne("SELECT * FROM table WHERE id=?i", $id); 
* 
* @param string $query - an SQL query with placeholders 
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query 
* @return array|FALSE either associative array contains first row of resultset or FALSE if none found 
*/ 
public function getRow() 
{ 
    $query = $this->prepareQuery(func_get_args()); 
    if ($res = $this->rawQuery($query)) { 
     $ret = $this->fetch($res); 
     $this->free($res); 
     return $ret; 
    } 
    return FALSE; 
} 

/** 
* Helper function to get single column right out of query and optional arguments 
* 
* Examples: 
* $ids = $db->getCol("SELECT id FROM table WHERE cat=1"); 
* $ids = $db->getCol("SELECT id FROM tags WHERE tagname = ?s", $tag); 
* 
* @param string $query - an SQL query with placeholders 
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query 
* @return array|FALSE either enumerated array of first fields of all rows of resultset or FALSE if none found 
*/ 
public function getCol() 
{ 
    $ret = array(); 
    $query = $this->prepareQuery(func_get_args()); 
    if ($res = $this->rawQuery($query)) 
    { 
     while($row = $this->fetch($res)) 
     { 
      $ret[] = reset($row); 
     } 
     $this->free($res); 
    } 
    return $ret; 
} 

/** 
* Helper function to get all the rows of resultset right out of query and optional arguments 
* 
* Examples: 
* $data = $db->getAll("SELECT * FROM table"); 
* $data = $db->getAll("SELECT * FROM table LIMIT ?i,?i", $start, $rows); 
* 
* @param string $query - an SQL query with placeholders 
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query 
* @return array enumerated 2d array contains the resultset. Empty if no rows found. 
*/ 
public function getAll() 
{ 
    $ret = array(); 
    $query = $this->prepareQuery(func_get_args()); 
    if ($res = $this->rawQuery($query)) 
    { 
     while($row = $this->fetch($res)) 
     { 
      $ret[] = $row; 
     } 
     $this->free($res); 
    } 
    return $ret; 
} 

Look - от имени функции вы всегда можете сказать, результат которой ожидать:

$name = $db->getOne('SELECT name FROM table WHERE id = ?i',$_GET['id']); 
$data = $db->getAll("SELECT * FROM ?n WHERE mod=?s LIMIT ?i",$table,$mod,$limit); 

Не одурачить такой ловушкой, как количество возвращенных строк.
В наборе результатов может быть честный один ряд, который вы намереваетесь заполнить fetchAll. Таким образом, он будет возвращать одномерный массив вместо многомерного, и на вашей странице будет много видеоэффектов.

-1

Поскольку вы не отметили ответ как принятый. Я думал, что отвечу тебе на вопрос. Я нашел это, ища ответ сам. Я согласен с «вашим здравым смыслом» в том, что они должны быть двумя отдельными функциями. Тем не менее, в прямой ответ на ваш вопрос, это то, что я имел (пример PDO вместо MySQLi):

function select($sql,$params=NULL,$fetchType=NULL){ 
    try{ 
     $qry = $this->db->prepare($sql); 
     $qry->execute($params); 
     if($qry->rowCount() > 1){ 
      if($fetchType == 'OBJ'){//returns object 
       $results = $qry->fetchAll(PDO::FETCH_OBJ); 
      }elseif($fetchType == 'NUM'){//-numerical array 
       $results = $qry->fetchAll(PDO::FETCH_NUM); 
      }else{//default - associative array 
       $results = $qry->fetchAll(PDO::FETCH_ASSOC); 
      } 
     } 
     else{ 
      if($fetchType == 'OBJ'){//returns object 
       $results = $qry->fetch(PDO::FETCH_OBJ); 
      }elseif($fetchType == 'NUM'){//-numerical array 
       $results = $qry->fetch(PDO::FETCH_NUM); 
      }else{//default - associative array 
       $results = $qry->fetch(PDO::FETCH_ASSOC); 
      } 
     } 

     if($results){ 
      return $results; 
     }else{ 
      return NULL; 
     } 
    } 
    catch(PDOException $err){ 
     $this->logError($err); 
    } 
} 

Однако я обнаружил, что если переспросила я все строки в таблице, но там была только одна строка в таблице он возвратил бы 1-й массив вместо 2-мерного массива. Мой код для обработки результата не будет работать для обоих типов массивов. Я могу справиться с этим каждый раз, но мне было проще, как было сказано выше, разделить их на разные функции, поэтому, если бы я знал, что будет только один ответ, я мог бы назвать соответствующую функцию.Это то, что у меня есть сейчас:

function select($sql,$params=NULL,$fetchType=NULL){ 
    try{ 
     $qry = $this->db->prepare($sql); 
     $qry->execute($params); 

     if($fetchType == 'OBJ'){//returns object 
      $results = $qry->fetch(PDO::FETCH_OBJ); 
     }elseif($fetchType == 'NUM'){//-numerical array 
      $results = $qry->fetch(PDO::FETCH_NUM); 
     }else{//default - associative array 
      $results = $qry->fetch(PDO::FETCH_ASSOC); 
     } 

     if($results){ 
      return $results; 
     }else{ 
      return NULL; 
     } 
    } 
    catch(PDOException $err){ 
     $this->logError($err); 
    } 
} 

function selectAll($sql,$params=NULL,$fetchType=NULL){ 
    try{ 
     $qry = $this->db->prepare($sql); 
     $qry->execute($params); 

     if($fetchType == 'OBJ'){//returns object 
      $results = $qry->fetchAll(PDO::FETCH_OBJ); 
     }elseif($fetchType == 'NUM'){//-numerical array 
      $results = $qry->fetchAll(PDO::FETCH_NUM); 
     }else{//default - associative array 
      $results = $qry->fetchAll(PDO::FETCH_ASSOC); 
     } 

     if($results){ 
      return $results; 
     }else{ 
      return NULL; 
     } 
    } 
    catch(PDOException $err){ 
     $this->logError($err); 
    } 
} 
+0

Я просто терпеть не могу много повторяющегося кода. Вам определенно нужно научиться использовать функции. –

+0

Есть ли способ сохранить имя функции в переменной? (swap "fetch" с "fetchAll")? – Joao

+0

нет никакой причины делать это –