我正在尝试使用 Zend Framework 2 进行查询,其中 JOIN 语句中有一个 SELECT 。到目前为止,这是我尝试过的,但是将 SELECT 对象注入 join() 的第一个参数似乎不起作用。我采用了这种方法,因为在进行任何分组之前我需要先对结果进行排序。关于如何让它发挥作用有什么想法吗?
public function getSearchKeyword($keyword, $limit)
{
$select = $this->keywords->getSql()->select();
$subquery = $this->pages->getSql()->select();
$subWhere = new \Zend\Db\Sql\Where();
$subWhere->equalTo('delete_flag', 'n')
->equalTo('published_flag', 'y');
$subquery->where($subWhere);
$where = new \Zend\Db\Sql\Where();
$where->like('keyword', '%' . $keyword . '%')
->equalTo('delete_flag', 'n');
$select->columns(array('display' => 'keyword', 'url'))
->join(array('sub' => $subquery), 'sub.page_id = keywords.page_id', array())
->where($where)
->group(array('keywords.page_id', 'keywords.keyword'))
->order(array('rank', 'keyword'))
->limit($limit);
$row = $this->tableGateway->selectWith($select);
return $row;
}
我想写的查询如下:
SELECT keywords.keyword AS display, keywords.url
FROM keywords
INNER JOIN
(
SELECT * FROM pages WHERE published_flag = 'y' AND delete_flag = 'n' ORDER BY page_id DESC
) pages
ON pages.page_id = keywords.page_id
WHERE published_flag = 'y'
AND delete_flag = 'n'
AND keywords.keyword LIKE '%?%'
GROUP BY display, page_id;
我正在解决同样的问题,但没有找到解决它的标准方法。所以我得到了一个可以工作但不是 zf2 标准的
代码示例
// Filename: /module/MyTools/src/MyTools/Service/DbModelServiceInterface.php
namespace MyTools\Service;
interface DbModelServiceInterface
{
/**
* Will return the result of querying the curret database
*
* @param type $query
* @result mixed
*/
public function dbQuery($query);
/**
* Will return a connection object that links to curret database
*
* @result mixed
*/
public function getConnection();
}
实现接口的类。它创建并提供 PDO 连接。 注意:它需要额外的代码来关闭 conns 并执行安全管理... 对其进行了测试并且功能齐全。 代码:
// Filename: /module/MyTools/src/MyTools/Service/DbModelServiceMySql.php
namespace MyTools\Service;
use MyTools\Service\DbModelServiceInterface;
use PDO;
class DbModelServiceMySql implements DbModelServiceInterface
{
protected $driverConfig;
protected $connection;
protected $isconnected = FALSE;
protected $dbname = '';
/**
* Creates a connection to main database
*/
public function __construct()
{
$driverConfig = self::getDriverDef();
$this->driverConfig = $driverConfig; // new PDO($driverConfig['dsn'], $driverConfig['username'], $driverConfig['password']);
$this->_connect();
}
protected function _connect(){
$dsn = (isset($this->driverConfig['dsn'])) ? $this->driverConfig['dsn'] : '';
$username = (isset($this->driverConfig['username'])) ? $this->driverConfig['username'] : '';
$password = (isset($this->driverConfig['password'])) ? $this->driverConfig['password'] : '';
if( ($dsn) && ($username) && ($password)){
$options = [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', ];
try {
$this->connection = new PDO($dsn, $username, $password, $options);
$this->isconnected = TRUE;
$this->_setdbname($dsn);
} catch (Exception $ex) {
throw new RuntimeException('YOUR ERROR MESSAGE.');
}
}
return $this->isconnected;
}
protected function _setdbname($dsn){
if($dsn){
$chunks = explode(';', ''.$dsn);
foreach($chunks as $chunk){
if(strpos('***'.$chunk, 'dbname') > 2){
$nombre = explode('=', $chunk);
$this->dbname = $nombre[1];
break;
}
}
}
}
/**
* {@inheritDoc}
*/
public function dbQuery($query) {
if($this->connection){
$resultset = $this->connection->query($query);
if($resultset){
return $resultset->fetchAll(PDO::FETCH_ASSOC);
}else{
return ['Error' => 'YOUR CUSTOM ERROR MESSAGE.'];
}
}else{
return ['Error' => 'OTHER CUSTOM ERROR MESSAGE'];
}
}
public static function getDriverDef()
{
$autoloadDir = __DIR__ . '../../../../../../config/autoload/';
$credentialsdb = include $autoloadDir . 'local.php';
$globaldb = include $autoloadDir . 'global.php';
$def = (isset($globaldb['db'])) ? $globaldb['db'] : array();
$credentials = (isset($credentialsdb['db'])) ? $credentialsdb['db'] : $credentialsdb;
return array_merge($def, $credentials);
}
/**
* {@inheritDoc}
*/
public function getConnection() {
if($this->connection){
return $this->connection;
}else{
return 'Error: YOUR CUSTOM ERROR MESSAGE';
}
}
/**
* {@inheritDoc}
*/
public function getDbName(){
return $this->dbname;
}
}
现在您有了一个可以在其他地方实例化的类来执行您需要的查询。
使用: 代码:
$myQuery = 'the very very complex query you need to execute'
$myDbConn = new MyTools\Service\DbModelServiceMySql();
$result = $myDbConn->dbQuery($myQuery);
如果成功,您将获得一个结果集数组,其中列名称=>值对
你可以试试这个。
$select->columns(array('display' => 'keyword', 'url'))
->join(array('sub' => 'pages'), 'sub.page_id = keywords.page_id',
array(), $select::JOIN_INNER)
->where($where)
->group(array('keywords.page_id', 'keywords.keyword'))
->order(array('rank', 'keyword'))
->limit($limit);
在您的代码中,您将获取 page_id 位于子 page_id 中的所有关键字,其中 delete_flag = 'n' 且published_flag = 'y'。
join(..., 'sub.page_id = keywords.page_id', array())
当不需要页表的任何列时,可以使用 IN 代替 JOIN。
例如当你需要知道哪些关键字在哪些页面中时,你应该使用JOIN,但是当你需要知道哪些键盘在任何页面中时,你可以使用IN语句。
无论如何:
ZF2 中没有标准方法,但您可以尝试以下代码。
public function getSearchKeyword($keyword, $limit)
{
$select = $this->keywords->getSql()->select();
$subquery = $this->pages->getSql()->select();
$subWhere = new \Zend\Db\Sql\Where();
$subWhere->equalTo('delete_flag', 'n')
->equalTo('published_flag', 'y');
$subquery->columns(array('page_id'))
->where($subWhere);
$where = new \Zend\Db\Sql\Where();
$where->like('keyword', '%' . $keyword . '%')
->equalTo('delete_flag', 'n')
->in('keywords.page_id', $subquery);
$select->columns(array('display' => 'keyword', 'url'))
->where($where)
->group(array('keywords.page_id', 'keywords.keyword'))
->order(array('rank', 'keyword'))
->limit($limit);
$row = $this->tableGateway->selectWith($select);
return $row;
}
我也遇到过类似的问题。由于 FROM
table
和子查询的 FROM table
不同,我收到了错误。
我的解决方法是提取 SQL 并创建一条语句。
$sql = $select->getSqlString(new \Zend\Db\Adapter\Platform\Mysql());
$stmt = $this->getAdapter()->createStatement($sql);
$stmt->prepare($sql);
$result = $stmt->execute();
$resultSet = new ResultSet(); \\ Class Zend\Db\ResultSet\ResultSet
$resultSet->initialize($result);