0

I need to implement something with joins on top of Zend_Db_Table. It has come to my attention that Zend_Db_Table provides no easy method of doing joins by itself. As a result, I have decided to simply write queries and then fetch the results using Zend_Db_Adapter::fetchAll.

However, I still somehow need to get the results as a Zend_Db_Table_Rowset so that other code expecting a rowset still operates correctly. I therefore need to take the array I get from Zend_Db_Adapter and turn that into a Zend_Db_Table_Rowset manually.

How can I do that?

Community
  • 1
  • 1
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • 1
    possible duplicate of [How to use Join in Zend Framework](http://stackoverflow.com/questions/2311481/how-to-use-join-in-zend-framework) though that wont allow you to use `Zend_Db_Rowset` anymore. If that doesnt answer your question, consider using an ORM (like Doctrine, which Zend_Db_* simply isnt good at) – Gordon Oct 10 '11 at 15:10
  • @Gordon: This has nothing to do with errors thrown by `Zend_Db_Table_Select`. I've got the query working just fine, but I only have the results as an array. I need to expose that as a Rowset though. – Billy ONeal Oct 10 '11 at 15:13
  • 1
    I mainly linked that to show you the easy way to do joins with Zend_Db_Table. But well, yeah, as the accepted answer in that question says: "Because Zend_Db_Table provides row gateway functions, which don't work if you join on other tables, …" - hence my suggestion to use Doctrine (ORM) instead of TableDataGateway and RowDataGateway pattern. If you do a join, the result is not a row anymore. – Gordon Oct 10 '11 at 15:15
  • @Gordon: That's not related to my question at all. I can't depend on something like Doctrine for a one or two queries -- that'd be insane. My question is "I have the query working, how do I expose that as a rowset". Your linked question is "I can't write the query in the first place" – Billy ONeal Oct 10 '11 at 15:20
  • 1
    see my namesake's answer. Sums it up nicely. If that is not what you are asking, please update the question because apparently there is already two people not getting what you are asking. – Gordon Oct 10 '11 at 15:21
  • @Gordon: Namesake's answer says absolutely nothing about `Zend_Db_Table_Rowset`. – Billy ONeal Oct 10 '11 at 16:22

4 Answers4

4

It's not a documented feature, but you can instantiate a Rowset object with any arbitrary array of arrays of data. This is what Zend_Db_Table does in its find() and fetchall() methods.

<?php

// this can be the result of any Zend_Db_Statement::fetchAll()
$query_result = array(
  array('id'=>123, 'foo'=>'bar'),
  array('id'=>456, 'foo'=>'baz')
);

$rowset = new Zend_Db_Table_Rowset(
  array(
    'readonly' => true,
    'data'     => $query_result
  )
);

foreach ($rowset as $row) {
  print "id  = " . $row->id . "\n";
  print "foo = " . $row->foo . "\n";
}

Note that this is not a "live" rowset. You can't change fields and save() them to the base tables in the database. There's no information stored in the rowset or rows about which base tables contain the columns corresponding to the fields of your Row objects. Some columns of your original SQL query may be expressions or aggregations, so there would be no deterministic way to save() them anyway.

So this is basically no improvement over using PDO::FETCH_OBJ to fetch result sets as objects instead of hash arrays.


Re comments:

Yes, you can use setTable() just like with a deserialized Rowset object. But Zend_Db_Table_Row does not have any idea which table each column belongs to. So it will try to generate an UPDATE or INSERT query based on the fields of the Row object. This will fail if the result set from which you make your Row object includes columns from more than one joined tables.

It's up to you to make sure the Row object contains fields only from a single table, and that the primary key column(s) are included, and that the Row is unambiguously mapped from a single row in the table.

Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
0

Zend_Db_Table as its name suggests abstracts a database table. You can load data, change it and save the results. However, this means you're restricted to the table that your instance is abstracting.

You can update the object's select statement by calling select() on it. You can then join() on additional tables and then fetchall(select) to get data from the joined table. However, as zend_db_table abstracts a single table, it wont allow you to.

You can get around this by doing a setIntegrityCheck(false) on the select, and this will allow you to join. However this means you'll only be able to read data through this object. Writing will be disabled.

Alternatively, you could use a zend_db_select object instead, which doesn't map to a particular table.

GordonM
  • 31,179
  • 15
  • 87
  • 129
  • 1
    +1 because it answers what I understand from the written question – Gordon Oct 10 '11 at 15:32
  • 1
    You asked how to do a join on a zend_db_select. I told you how. How is that not remotely answering the question? – GordonM Oct 10 '11 at 15:38
  • @Gordon: No, I asked now to take the **result** of a `Zend_Db_Select` and put that into a `Zend_Db_Table_Rowset`. – Billy ONeal Oct 10 '11 at 16:22
  • 2
    You might have wanted to make that a bit mroe clear in your original question then, as from reading the comments I certainly wasn't the only one to misunderstand what you were asking. – GordonM Oct 10 '11 at 16:35
0

I've been stymied by this before, too. I don't think you can return a zend_db_table_rowset unless you write the implementation yourself. Try looking into the rowset abstract to see how the structure works. A zend_db_table_rowset is a collection of zend_db_table_row objects. What you're getting back from zend_db_adapter just isn't compatible*. What you might need to do is somehow convert your results into zend_db_table_rows and then add them to a new zend_db_table_rowset to gain access to all of the members of those classes.

* this describes what can be returned from Zend_Db_Adapter, and I don't see Zend_Db_Table/Rowset/Row as an option: http://framework.zend.com/manual/en/zend.db.adapter.html#zend.db.adapter.select.fetch-mode

tjb1982
  • 2,257
  • 2
  • 26
  • 39
0
  $table = new Zend_Db_Table('tableName');

    $myRowset = $table->fetchAll();

Lastly Zend_Db provices excellent way of joining table through Zend_Db_Select .

Mr Coder
  • 8,169
  • 5
  • 45
  • 74