mysql - 使用 Zend Framework 2 TableGateway 加入子查询

标签 mysql sql zend-framework2

我正在尝试使用 Zend Framework 2 进行查询,其中我在 JOIN 语句中有一个 SELECT。到目前为止,这是我尝试过的方法,但是将 SELECT 对象注入(inject)到 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 标准的

  1. 创建一个小界面来管理数据库连接
  2. 将其实现为一个小类以获取连接 PDO 对象 你的数据库
  3. 执行你的任意查询

代码示例

// 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();
}

实现接口(interface)的类。它创建并提供 PDO 连接。 注意:它需要额外的代码来关闭连接和执行安全管理... 它对其进行测试并且功能齐全。 代码:

// 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);

如果成功,你会得到一个成对的结果集 columnName => value

关于mysql - 使用 Zend Framework 2 TableGateway 加入子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18995600/

相关文章:

python - 有人可以给我关于这个优化策略的两分钱吗

mysql - TypeError : app. post(...).then 不是一个函数

mysql - 限制每个月的行数?

sql - 在不更改排序规则的情况下更改列

mysql - 程序+插入

php - 你如何在 MySQL/PHP 中存储和搜索数字间隔?

sql - Oracle分层查询中如何使用WHERE-CLAUSE

php - ZF2+Doctrine2 - 在 Mac 上突然出现错误 : "Doctrine\ORM\EntityManager"; no instance returned

php - 如何在 ZF2 的控制台 Controller 中创建 URL?

php - 在 Zend Framework 2 中无法正确解析包含特殊字符的路由