Zend Framework 2 Db\Adapter\Adapter query resultse

2020-06-03 06:07发布

Just need a hand understanding some simple database queries in ZF2. In ZF1 I have simple methods like this:

public function recordset()
{
// listing of all records 
$db = Zend_Registry::get('db');
$sql = "SELECT " . $this->_selectlist() .
    " from customer c";
$r = $db->fetchAll($sql);
return $r;
}

In ZF2, how would I do the same? I have tried the following, but this just returns what looks like a "Result" object, but all I want is an array like ZF1 did with fetchAll. If I have to iterate the result object only to provide the array later, which then must be iterated over again, it just seems like some duplication of effort.

Anyway, here's what I have in ZF2 so far:

//above the controller start I have: use Zend\Db\Adapter\Adapter as DbAdapter;

public function blaAction()
{
    $db = new DbAdapter(
        array(
            'driver'        => 'Pdo',
            'dsn'            => 'mysql:dbname=mydb;host=localhost',
            'username'       => 'root',
            'password'       => '',
            )
    );
    $sql = 'select * from customer';
    $stmt = $db->query($sql);
    $results = $stmt->execute();
    $this->view->data = $results;
    return $this->view;
}

In the output, I get this:

object(Zend\Db\Adapter\Driver\Pdo\Result)#197 (8) { 
     ["statementMode":protected]=> string(7) "forward" ["resource":protected]=> object(PDOStatement)#195 (1) { 
        ["queryString"]=> string(22) "select * from customer" 
  } ["options":protected]=> NULL ["currentComplete":protected]=> bool(false) ["currentData":protected]=> NULL ["position":protected]=> int(-1) ["generatedValue":protected]=> string(1) "0" ["rowCount":protected]=> NULL 
}

However, if I change $results to $results->count(); I do indeed see a record count. How do I get to the data though as an array? (a full recordset)

At one point I did see something like: $results->current() But that only returned a single record.

Just a side note. I do see all the table abstract classes I could use, but at this point in my learning, I don't want to do that. I just want some simple on-demand queries that return arrays like they did in ZF1. In ZF2, there's seems to be way too much "wiring up" of things in configs and stuff that just seem like overkill. But, as a framework, I like the flexibility and the main app I am working on in ZF1 could really benefit from the modularity of ZF2. (otherwise I'd probably go with other framework)

Please forgive my ignorance, and thanks very much for any help!

5条回答
爷的心禁止访问
2楼-- · 2020-06-03 06:15

My English is very rotten
I also encountered this problem,$returnType Defined in Zend\Db\ResultSet\ResultSet
we can give third argument for Zend\Db\Adapter\Adapter,like this

$adapter = new Zend\Db\Adapter\Adapter($db_config,null,new Zend\Db\ResultSet\ResultSet('array'));
$re = $adapter->query('select * from mooncake', $adapter::QUERY_MODE_EXECUTE);
$s = $re->current();
var_dump($s);

now,$s is array

查看更多
放荡不羁爱自由
3楼-- · 2020-06-03 06:20

From http://framework.zend.com/manual/2.0/en/modules/zend.db.result-set.html:

Zend\Db\ResultSet is a sub-component of Zend\Db for abstracting the iteration of rowset producing queries.

So you can do the following:

$statement = $db -> query($sql);

/** @var $results Zend\Db\ResultSet\ResultSet */
$results = $statement -> execute();

$returnArray = array();
// iterate through the rows
foreach ($results as $result) {
    $returnArray[] = $result;
}

Now you can send it to the view:

return new ViewModel(array('results' => $returnArray));
查看更多
神经病院院长
4楼-- · 2020-06-03 06:24

You can avoid the foreach loop by doing the following:

$statement = $db->query($sql);

/** @var $results Zend\Db\ResultSet\ResultSet */
$results = $statement->execute();

$data = $result->getResource()->fetchAll();
// Now data is an array
查看更多
ゆ 、 Hurt°
5楼-- · 2020-06-03 06:35

Ok, I think I've got it. At least this will do the job for the time being. Basically, you have to add one extra step and feed the result object into a ResultSet object which has a toArray convenience method. I suppose this could be done a million other ways, but... this works.

Keep in mind, I wouldn't do this in a controller, or even in this exact way, but its only a test at this point. There's times when I want this available, and this is how ZF2 can do it, if one desired. (never minding good/bad habits)

In the top of the Controller add/use the ResultSet:

use Zend\Db\ResultSet\ResultSet;

Here's the working test action:

public function blaAction()
{
    $db = new DbAdapter(
        array(
            'driver'        => 'Pdo',
            'dsn'            => 'mysql:dbname=mydb;host=localhost',
            'username'       => 'root',
            'password'       => '',
            )
    );
    $sql = 'select * from customer 
        where cust_nbr > ? and cust_nbr < ?';
    $sql_result = $db->createStatement($sql, array(125000, 125200))->execute();
    if($sql_result->count() > 0){
        $results = new ResultSet();
        $this->view->data = $results->initialize($sql_result)->toArray();
    }
    return $this->view;
}

toArray is just doing a foreach loop for you, so, I guess its still adding extra array loops I wanted to avoid, but not having looked at ZF1 version of their code, maybe its doing the same anyway.

What I will probably do is create a simple db wrapper class for Zend\Db that replaces my Zend_Registry statement from ZF1 and adds a fetchAll and fetchOne method, that way I can quickly port over a bunch of ZF1 code to ZF2 much easier.

Thanks for your input in the comments, I appreciate it. :)

Oh, I also wanted to mention. I ran into this bridge class someone created, which might also be helpful: https://github.com/fballiano/zfbridge

EDIT: So the adapter results returned are iterable it turns out. I am not sure what steps I took that led to my confusion, but the results in $db->query are returned as a Pdo\Result object and that can be looped in foreach easy enough. What messed me up was the fact that if you var_dump it,it doesn't show the array data, just the object. That led me down a totally confusing path.

Now, even though the above works, this is better IMO, because we can take that object, send it where we want for iteration later. (rather than loop over the whole thing to create an array first, only to iterate another loop, waste of time that way)

Here's a working example I like better. you just loop the object, and there's your data! duh! Not sure how I miss the simple things sometimes. :)

public function blaAction()
{
    $db = new DbAdapter(
        array(
            'driver'        => 'Pdo',
            'dsn'            => 'mysql:dbname=gwdb;host=localhost',
            'username'       => 'root',
            'password'       => '',
            )
    );
    $sql = 'select * from customer 
        where cust_nbr > ? and cust_nbr < ?';

    $rs = $db->query($sql)->execute(array(125000, 125200));
    // Source of confusion: this doesn't dump the array!!!
    // It dumps the object properties for Pdo\Result
    Debug::dump($rs);
    // but it is still able to iterate records directly
    // without toArray
    foreach ($rs as $row){
        Debug::dump($row);
    }

    return $this->view;
} 
查看更多
等我变得足够好
6楼-- · 2020-06-03 06:38

After long search I handel my SQL Query in ZF2 that way

 $sql = new \Zend\Db\Sql\Sql($this->tableGateway->getAdapter());
    $select = $sql->select();
    $select->from('table'); 
    $select->columns(array('*'));
    $select->join("join table", "table.id = join table.id", array("*"), "left");
    $statement = $sql->prepareStatementForSqlObject($select);
    $results = $statement->execute();
    return iterator_to_array($results));

The trick is the PHP function iterator_to_array

查看更多
登录 后发表回答