2016-01-12 80 views
0

使用Zend Framework 2可以從tablegateway對象獲得一個SQL字符串,像這樣:MySQL查詢字符串SQL對象

public function test(){ 
    $sql = $this->tableGateway->getSql(); 
    $select = $sql->select(); 
    $select->where(array('title' => 'abracadabra')); 
    $select->where 
    ->NEST-> 
      equalTo('id', 1) 
       ->OR-> 
      equalTo('artist', 'Tony') 
    ->UNNEST; 

    $select->limit(1); 

    return $this->tableGateway->selectWith($select); 
} 

//code ignored here// 

echo $sql->getSqlstringForSqlObject($select); 

我想知道是否有可能有可能反其道而行之,基本上設置一個查詢字符串,然後找回一個tableGateway對象,其原因是有時需要動態地設置where子句,而不必知道在哪裏放置/附加它,例如:

在單個查詢上:

$sql = "select * from tbl_test"; 

if($isDynamic) 
    $sql .= ' where test_id=1'; 

但在更復雜的查詢:

$sql = "select * from tbl_test inner join (select * from tbl_test 1) x on 1=1 where test_id is not null group by test_id"; 

//OF COURSE IT WILL FAIL. 
if($isDynamic) 
    $sql .= ' where test_id=1'; 

使用ZF2我可能會做這樣的事情

  • 設置查詢字符串到SQL對象。
  • 然後只需做$ obj-> where(array('test_id'=> 1));

回答

1

爲了解決這個問題,我重載了方法Zend \ Db \ Sql \ Select

爲了您的複雜查詢的例子,我的步驟如下:

Your query : select * from tbl_test inner join (select * from tbl_test 1) x on 1=1 where test_id is not null group by test_id 
My query : SELECT * FROM (select * from tbl_test inner join (select * from tbl_test 1) x on 1=1 where test_id is not null group by test_id) tmp WHERE test_id=1; 

如果你的複雜查詢使用別名TMP則在該方法renderTable()改變。 下面是我的類用於(更改命名空間是必要):

use SbmPdf\Model\Db\Sql\Select; 
$sql = "select * from tbl_test inner join (select * from tbl_test 1) x on 1=1 where test_id is not null group by test_id"; 
$select = new Select($sql); 
$select->where(array('id' => 1)); 

這裏是我的課(更改命名空間是必要):

/** 
* Surcharge de la classe Zend\Db\Sql\Select pour exécuter une requête complexe basée sur une chaine SQL 
* 
* On a ajouté la méthode setRecordSource qui permet de passer une chaine SQL complète comme source de donnée. 
* 
* Lorsque la chaine SQL recordSource est donnée (constructeur ou setter), elle remplace la table indiquée dans FROM. 
* En définitive, la méthode from() sera ignorée si la méthode recordSource() est appelée. 
* Par contre, si on n'appelle pas cette nouvelle méthode, la classe aura un comportement normal (à condition de ne 
* rien passer au constructeur). 
* 
* Ensuite, pour exécuter la requête, il faut pratiquer de la façon suivante : 
* $sqlString = $select->getSqlString($dbAdapter->getPlatform()); 
* $rowset = $dbAdapter->query($sqlString, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE); 
* 
* @project sbm 
* @package SbmPdf/Model/Db/Sql 
* @filesource Select.php 
* @encodage UTF-8 
* @author DAFAP Informatique - Alain Pomirol ([email protected]) 
* @date 19 août 2015 
* @version 2015-1 
*/ 
namespace SbmPdf\Model\Db\Sql; 

use Zend\Db\Adapter\Driver\DriverInterface; 
use Zend\Db\Adapter\ParameterContainer; 
use Zend\Db\Adapter\Platform\PlatformInterface; 
use Zend\Db\Sql\Select as ZendSelect; 

class Select extends ZendSelect 
{ 

    private $recordSource; 

    /** 
    * On passe le recordSource (sql string) par le constructeur. On ne peut plus passer la table. 
    * 
    * @param string $recordSource    
    */ 
    public function __construct($recordSource = null) 
    { 
    parent::__construct(); 
    $this->recordSource = $recordSource; 
    } 

    /** 
    * On peut aussi le passer par le setter 
    * 
    * @param string $recordSource    
    * @return \SbmPdf\Model\Db\Sql\Select 
    */ 
    public function setRecordSource($recordSource) 
    { 
    $this->recordSource = $recordSource; 
    return $this; 
    } 

    /** 
    * Surcharge de la méthode 
    * 
    * (non-PHPdoc) 
    * 
    * @see \Zend\Db\Sql\Select::processSelect() 
    */ 
    protected function processSelect(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) 
    { 
    $expr = 1; 
    if (empty($this->recordSource)) { 
     list ($table, $fromTable) = parent::resolveTable($this->table, $platform, $driver, $parameterContainer); 
    } else { 
     list ($table, $fromTable) = $this->resolveTable($this->recordSource, $platform); 
    } 
    // process table columns 
    $columns = array(); 
    foreach ($this->columns as $columnIndexOrAs => $column) { 
     if ($column === self::SQL_STAR) { 
      $columns[] = array(
       $fromTable . self::SQL_STAR 
      ); 
      continue; 
     } 

     $columnName = $this->resolveColumnValue(array(
      'column' => $column, 
      'fromTable' => $fromTable, 
      'isIdentifier' => true 
     ), $platform, $driver, $parameterContainer, (is_string($columnIndexOrAs) ? $columnIndexOrAs : 'column')); 
     // process As portion 
     if (is_string($columnIndexOrAs)) { 
      $columnAs = $platform->quoteIdentifier($columnIndexOrAs); 
     } elseif (stripos($columnName, ' as ') === false) { 
      $columnAs = (is_string($column)) ? $platform->quoteIdentifier($column) : 'Expression' . $expr ++; 
     } 
     $columns[] = (isset($columnAs)) ? array(
      $columnName, 
      $columnAs 
     ) : array(
      $columnName 
     ); 
     } 

     // process join columns 
     foreach ($this->joins as $join) { 
     $joinName = (is_array($join['name'])) ? key($join['name']) : $join['name']; 
     $joinName = parent::resolveTable($joinName, $platform, $driver, $parameterContainer); 

     foreach ($join['columns'] as $jKey => $jColumn) { 
      $jColumns = array(); 
      $jFromTable = is_scalar($jColumn) ? $joinName . $platform->getIdentifierSeparator() : ''; 
      $jColumns[] = $this->resolveColumnValue(array(
       'column' => $jColumn, 
       'fromTable' => $jFromTable, 
       'isIdentifier' => true 
      ), $platform, $driver, $parameterContainer, (is_string($jKey) ? $jKey : 'column')); 
      if (is_string($jKey)) { 
       $jColumns[] = $platform->quoteIdentifier($jKey); 
      } elseif ($jColumn !== self::SQL_STAR) { 
       $jColumns[] = $platform->quoteIdentifier($jColumn); 
      } 
      $columns[] = $jColumns; 
     } 
    } 

    if ($this->quantifier) { 
     $quantifier = ($this->quantifier instanceof ExpressionInterface) ? $this->processExpression($this->quantifier, $platform, $driver, $parameterContainer, 'quantifier') : $this->quantifier; 
    } 

    if (! isset($table)) { 
     return array(
      $columns 
     ); 
    } elseif (isset($quantifier)) { 
     return array(
      $quantifier, 
      $columns, 
      $table 
     ); 
    } else { 
     return array(
      $columns, 
      $table 
     ); 
    } 
    } 

    protected function resolveTable($table, PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) 
    { 
    $alias = null; 

    if (is_array($table)) { 
     $alias = key($table); 
     $table = current($table); 
    } else { 
     $alias = 'tmp'; 
    } 
    $fromTable = $platform->quoteIdentifier($alias); 
    $table = $this->renderTable($table, $fromTable, false); 
    if ($alias) {} else { 
     $fromTable = $table; 
    } 

    if ($this->prefixColumnsWithTable && $fromTable) { 
     $fromTable .= $platform->getIdentifierSeparator(); 
    } else { 
     $fromTable = ''; 
    } 

    return array(
     $table, 
     $fromTable 
    ); 
    } 

    protected function renderTable($table, $alias = null, $parent = true) 
    { 
    if ($parent) { 
     return parent::renderTable($table, $alias); 
    } else { 
     if (empty($alias)) { 
      $alias = 'tmp'; 
     } 
     return "($table) AS $alias"; 
    } 
    } 
} 
+0

感謝阿蘭SQL,這就是我一直在尋找,只是想知道這是否是能夠解析任何一種選擇查詢或只是特定情況下? – peterpeterson

+0

我將它用於許多應用程序來創建自定義的PDF文檔。但要說它解析任何種類的選擇查詢...一個必須小心,並嘗試! –

0

您可以直接where子句中使用您的盤帶。

public function test(){ 
$sql = $this->tableGateway->getSql(); 
$select = $sql->select(); 
$select->where(array('title' => 'abracadabra')); 
$select->where 
->NEST-> 
     equalTo('id', 1) 
      ->OR-> 
     equalTo('artist', 'Tony') 
->UNNEST; 

if($isDynamic){ 
    $select->where(array('test_id' => '1')); 
} 

$select->limit(1); 

return $this->tableGateway->selectWith($select); 
} 

您可以像使用this

+0

那不是我在找什麼,我知道是誰用tableGateway創建查詢 – peterpeterson