2013-08-21 75 views
0

我在Repository類中編寫了這個函數以接收來自Doctrine的簡單鍵值。在Doctrine中沒有構建函數來做到這一點? (我找不到)。或者也許代碼可以改進。從Doctrine獲取關鍵值列表

這裏是我的功能:

public function getListBy($criteria=null, $key, $value) { 
    $dql = "SELECT i.".$key." as k, 
        i.".$value." as v 
       FROM MbFooBundle:Input i"; 

    if (isset($criteria) && is_array($criteria)) { 
     foreach($criteria as $cKey => $cValue) { 
      if (!isset($where)) 
       $where = " WHERE "; 
      else 
       $where .= " AND "; 

      $where .= "i.".$cKey." = ".(is_numeric($cValue) ? $cValue : "'".$cValue."'"); 
     } 

     $dql .= $where; 
    } 

    $query = $this->getEntityManager() 
     ->createQuery($dql); 

    $result = $query->getArrayResult(); 
    $list = array(); 

    if (count($result)) { 
     foreach($result as $data) { 
      $list[$data['k']] = $data['v']; 
     } 
    } 

    return $list; 
} 
+1

['注意,當使用默認的argum ents,任何默認值都應該在任何非默認參數的右邊;否則,事情將無法按預期工作。]](http://php.net/manual/en/functions.arguments.php) – cheesemacfly

+0

你是對的,在這種情況下設置默認值是無用的。 – rolandow

回答

2

我不會這麼做。然而,這個代碼容易受到SQL Injection的影響,但它也破壞了一些standards

這是我的思維方式。
我想創建將操縱結果的方法的標準學說的findBy

/** 
* Data Manipulator 
*/ 
class DataManipulator 
{ 
    /** 
    * Associates any traversable input into its key and value 
    * 
    * @param mixed $input A Traversable input 
    * @param string $key Key to associate 
    * @param string $value Value to associate 
    * @return array Associated array 
    * 
    * @throws InvalidArgumentException When Input is not traversable 
    */ 
    public function associate($input, $key, $value) 
    { 
     if (!is_array($input) && !($input instanceof Traversable)) { 
      throw new InvalidArgumentException("Expected traversable"); 
     } 

     $out = array(); 

     foreach ($input as $row) { 
      $out[$this->getInput($row, $key)] = $this->getInput($row, $value); 
     } 

     return $out; 
    } 

    /** 
    * Fetches the input of a given property 
    * 
    * @param mixed $row An array or an object 
    * @param string $find Property to find 
    * @return mixed Property's value 
    * 
    * @throws UnexpectedValueException When no matching with $find where found 
    */ 
    protected function getInput($row, $find) 
    { 
     if (is_array($row) && array_key_exists($find, $row)) { 
      return $row[$find]; 
     } 

     if (is_object($row)) { 
      if (isset($row->$find)) { 
       return $row->$find; 
      } 

      $method = sprintf("get%s", $find); 

      if (method_exists($row, $method)) { 
       return $row->$method(); 
      } 
     } 

     throw new UnexpectedValueException("Could not find any method to resolve"); 
    } 
} 

然後你可以使用它

$em  = $this->getDoctrine()->getManager(); 
$results = $em->getRepository('AcmeFooBundle:Input') 
       ->findBy(array('category' => 'foo')); 

$manipulator = new DataManipulator; 
$filtered = $manipulator->associate($results, 'key', 'value'); 

可以see it working


如果您需要只選擇部分對象,你應該在你的存儲庫01中創建一個方法這將獲取您的部分輸入。
此函數必須只有獲取該對象,而不是關聯其內容。

public function findPartialBy(array $values, array $criterias = array()) 
{ 
    $qb = $this->createQueryBuilder('i'); 
    $qb->select($values); 

    foreach ($criterias as $key => $value) { 
     $qb->andWhere(sprintf("i.%s", $key), sprintf(":%s", $key)) 
     $qb->setParameter(sprintf(":%s", $key), $value); 
    } 

    return $qb->getQuery()->getResult(); 
} 

然後你可以使用它

$fetch = array('key', 'value'); 
$em  = $this->getDoctrine()->getManager(); 
$results = $em->getRepository('AcmeFooBundle:Input') 
       ->findPartialBy($fetch, array('category' => 'foo')); 

$manipulator = new DataManipulator; 
$filtered = $manipulator->associate($results, 'key', 'value'); 
+0

我喜歡這種方法,但我認爲它的缺點是它會加載完整的Input對象,而我只需要對象的兩個屬性。特別是對於大對象,這可以使用更多的內存。 – rolandow

+0

@rolandow更新,查看部分對象的版本 – Touki