ZF2/PHP - 如何从查询中提取标量记录并将其用作第二个查询的 Where 子句的参数?

ZF2/PHP - How to extract Scalar Record from a Query and use as Parameter of Where Clause of Second Query?

信息

我有一个应用程序,我想在其中查询一个 table 以便能够找出具有最小 ID 的记录。为了简化我的理解,我用两种 table 方法组成了两个查询。

我能够使用硬编码标量查询数据库,但无法基于另一个查询中查询的标量进行查询。

问题

如何从 Zend Framework 2 中的查询中提取标量值并将该值用作另一个(主)查询的 where 子句的输入?

代码

   public function getMinActionItemID()
    {
        $select = new Select();
        $select->from('actionitems', array('MinActionItemID'))->columns(array('MinActionItemID' => new Expression('min(ActionItemID)')));
        $resultSet = $this->tableGateway->selectWith($select);
        $resultSet->buffer();
        return $resultSet;
    }

public function getFirstActionItem()
{       
    var_dump($this->getMinActionItemID());
    $select = new Select();
    $select->from('actionitems')->where(array('ActionItemID' => $this->getMinActionItemID()));
    $row = $this->tableGateway->selectWith($select);        

    if (!$row) {
        throw new Exception("Action Item Not Found");
    }

    return $row;

}

我能够从查询中获取以下内容,但无法从下面的对象中获取标量值,该对象从 getFirstActionItemID() 返回并传递到 getFirstActionItem() 的 where 子句中方法。

  object(Zend\Db\ResultSet\ResultSet)[288]
  protected 'count' => int 1
  protected 'dataSource' => 
    object(Zend\Db\Adapter\Driver\Pdo\Result)[266]
      protected 'statementMode' => string 'forward' (length=7)
      protected 'fetchMode' => int 2
      protected 'resource' => 
        object(PDOStatement)[267]
          public 'queryString' => string 'SELECT min(ActionItemID) AS `MinActionItemID` FROM `actionitems`' (length=64)
      protected 'options' => null
      protected 'currentComplete' => boolean true
      protected 'currentData' => 
        array (size=1)
          'MinActionItemID' => string '1' (length=1)
      protected 'position' => int 0
      protected 'generatedValue' => string '0' (length=1)
      protected 'rowCount' => int 1
  protected 'fieldCount' => int 1
  protected 'position' => int 0

编辑

我最终放弃了我的方法并使用了提供的答案。我还保留了 getMinActionItemID(),这样当我导航到第一条和最后一条记录并尝试在我的应用程序中转到下一条或上一条时,我将使用它进行边界检查。

通过智能感知进行一些调查,我终于找到了一种获取所需标量的方法。事后看来,我找到了答案和这段代码来解决我的导航问题(一次一条记录)。

如何从查询中获取标量

回答

use Zend\Db\Adapter\Driver\Pdo\Result;

/* @var $resultSet ResultSet */
    /* @var $dataSource Result */
    public function getMinActionItemID()
    {
        $select = new Select();
        $select->from('actionitems', array('MinActionItemID'))->columns(array('MinActionItemID' => new Expression('min(ActionItemID)')));
        $resultSet = $this->tableGateway->selectWith($select);
        $dataSource = $resultSet->getDataSource();
        return $dataSource->getResource()->fetchAll()[0]['MinActionItemID'];
    }

用法

public function getNextActionItem($id)
{

    if ($id == $this->getMaxActionItemID())
    {
        return $this->getActionItem($id);
    }

    $select = new Select();
    $select->from('actionitems')
           ->where("ActionItemID > $id")
           ->order('ActionItemID')
           ->limit(1);
    $row = $this->tableGateway->selectWith($select);

    if (!$row) {
        throw new Exception ("Action Item Not Found");
    }

    return $row;
}

我认为,如果您想要 select 具有最小 ActionItemID 的行,您可以使用 ActionItemID 进行排序并将限制设置为 1。

public function getFirstActionItem()
{
    $select = $this->tableGateway->getSql()->select();
    $select->order('ActionItemID');
    $select->limit(1);

    $row = $this->tableGateway->selectWith($select)->current();

    if (!$row) {
        throw new Exception('Action Item Not Found');
    }

    return $row;
}

您应该在一个查询中执行此操作,方法如下(假设 $table 是您的 table 网关的一个实例):

    use Zend\Db\Sql\Expression;
    use Zend\Db\Sql\Select;

    ...

    $set   = $table->select( function( Select $s ){

        $sub = new Select('actionitems');
        $sub->columns( [ 'min_id' => new Expression( 'MIN(ActionItemID)') ] );

        $s->columns(['*'])
            ->where([ 'ActionItemID' => $sub ])
                ->limit( 1 );
    });

    var_dump( $set->current() );

如何分两步从 $resultSet 的任意查询中提取标量。

 $dataSource = $resultSet->getDataSource();
 $minActionItemID =  $dataSource->getResource()->fetchAll()[0]['MinActionItemID'];  //Note: [0] is the first record and ['MinActionItemID'] is the field name of the custom query