Feature Request #3024

A method to convert Database_Result object to an array of arrays

Added by Human Internals about 4 years ago. Updated over 2 years ago.

Status:ClosedStart date:06/28/2010
Priority:NormalDue date:
Assignee:Woody Gilk% Done:

0%

Category:Modules:Database
Target version:v3.0.9
Resolution:wontfix Points:

Description

I want to propose a method on the Database_Result class that'll allow to get an array of rows, where each row is an array by itself. This is useful when you need to encode multiple rows stored in Database_Result to JSON and such.

This is the row_as_array() method I currently use to achieve that, would be nice to have something similar to it built-in to Kohana.

abstract class Database_Result extends Kohana_Database_Result {
    // not only transforms the ArrayAccess/Iterator to a real array,
    // but also transforms every row to an array (using as_array()), instead of returning an array of ORM objects
    public function row_as_array() {
        $array = $this->as_array();
        foreach ($array as $key=>$row) {
            $array[$key] = $row->as_array();
        }
        return $array;
    }
}

I think etting a "pure" array representation of multiple rows stored in Database_Result could be a nice addition.


Related issues

Related to Kohana v3.x - Bug Report #2860: Database_Result::as_array inconsistent with ORM::as_array Closed 05/11/2010
Duplicated by ORM - Feature Request #3713: Support context variables in Database_Result:::as_array() Closed 02/09/2011

History

#1 Updated by Dmitry T. about 4 years ago

Database already has such function called as_array(). It returns exactly what you need - the array of arrays. Or you're talking about ORM?

#2 Updated by Human Internals about 4 years ago

Maybe I should've made it clearer that I'm talking about cases where Database_Result objects has _as_object property set to some Model_Foobar, which is the always the case when you're getting an Database_Result via the ORM class.

When you ORM::factory('user')->find_all() you get an Database_Result iterator. The current() method of Database_Result returns every row as an instance of Model_User (the ORM passes it to Database_Result->_as_array).

the Database_Result::as_array() method does that (when no parameter are passed):

foreach ($this as $row)
{
    $results[] = $row;
}

When _as_objec is set, $row is returned from current() as an instance of Model_User, and not a plain array.

In cases like that, you have to apply another foreach() on the return value of as_array() to normalize the rows to a "pure" array representation. I eventually written that row_as_array() method to have a more continent way of doing so, as it became very common when I'm JSON encoding multiple rows or my View is expecting an array in some cases.

#3 Updated by Woody Gilk about 4 years ago

  • Category set to Modules:Database
  • Status changed from New to Closed
  • Assignee set to Woody Gilk
  • Target version set to v3.0.7
  • Resolution set to duplicate

You can already do this with:

$result = $result->cached()->as_array();

This was done in #2297.

#4 Updated by Human Internals about 4 years ago

  • Status changed from Closed to Feedback

I'm sorry if I misunderstood something or misused your code, but cached()->as_array() does not return an array of arrays.

This script:

print_r(ORM::factory('user')->where('id','in',array(1,6))->find_all()->cached()->as_array());

Is showing that the return value is an array of ORM objects:
Array
(
    [0] => Model_User Object
        (
            [_ignored_columns:protected] => Array
                (
                    [password_confirm] => password_confirm
                )
                .....
        )

    [1] => Model_User Object
        (
            [_ignored_columns:protected] => Array
                (
                    [password_confirm] => password_confirm
                )
                .....
        )

)

What I'm trying to get is (that row_as_array() method is what I wrote above in the description)

print_r(ORM::factory('user')->where('id','in',array(1,6))->find_all()->row_as_array());

Which outputs:

Array
(
    [0] => Array
        (
            [id] => 1
            [account_type] => ...
            [username] => shesek
            [password] => ...
            [email] => shesek@....com
            [session] => 
        )

    [1] => Array
        (
            [id] => 6
            [account_type] => ...
            [username] => nadav
            [password] => ...
            [email] => nadav@...com
            [session] => ...
        )

)

Am I missing something? cached() is returning an serializable object, but as far as I see calling as_array() on it is not an "pure" array representation that's suitable for JSON encoding multiple rows, passing to Views that are expecting arrays or any other usage that might require an array of arrays.

Have I done something wrong?

#5 Updated by Woody Gilk about 4 years ago

  • Status changed from Feedback to Closed
  • Resolution changed from duplicate to wontfix

You can already control how the results are returned by setting the Database_Query::$as_object = FALSE.

#6 Updated by Human Internals about 4 years ago

  • Status changed from Closed to Feedback

I'm sorry I keep re-opening this issue, but what you're suggesting is simply impossible when working with the ORM, as the ORM creates the Database_Result and gives me no control over as_object. There isn't even a setter for it.

Once it get an Database_Result via something like ORM::factory('user')->find_all(), I have no way to set the as_object property on it. To get an array representation I have to call Database_Result::as_array() than foreach on the result set and call as_array on every element (instances of ORM) again.

Getting an array representation of multiple rows is quite a common operation and I think there should a be an easy method for doing that. It seems odd that it isn't supported and I have to manually do it every time or implement this functionally myself.

#7 Updated by Woody Gilk about 4 years ago

  • Status changed from Feedback to Closed

Then maybe you shouldn't be using ORM.

#8 Updated by Dmitry T. about 4 years ago

Woody Gilk wrote:

Then maybe you shouldn't be using ORM.

Or maybe you should extend ORM?

#9 Updated by Jeremy Bush about 4 years ago

Woody Gilk wrote:

Then maybe you shouldn't be using ORM.

I think has nothing to do with ORM, and it's a problem in how the database library works. as_object() and as_array() should be methods of the result object, like they are in kohana2. It doesn't make any sense to have them be set before the fact. All it does is restrict how useful the class is.

#10 Updated by Human Internals about 4 years ago

  • Status changed from Closed to Feedback

Woody Gilk wrote:

Then maybe you shouldn't be using ORM.

So basically you're saying that if one wants to get an array of arrays representing multiple rows, he must work directly with the Database layer? seriously?

Dmitry T. wrote:

Or maybe you should extend ORM?

That's what I did - I added that row_as_array() method (the one I wrote with the issue description) that lets me do that. I still believe its something that should be a part of Kohana's core.

#11 Updated by Kiall Mac Innes about 4 years ago

I have to agree - This FR makes perfect sense to me, and is something I routinely add at the beginning of each project!

#12 Updated by Woody Gilk about 4 years ago

  • Target version changed from v3.0.7 to v3.0.8

#13 Updated by Chris Bandy almost 4 years ago

The limitation in the Database library is well-founded.

Many PHP database drivers have seekable result sets, while most allow some kind of rewind. PDO support for either is terrible. The truth is that forward-only results are the fastest and are guaranteed to be available in any driver, native or PDO. This means, however, that we should expect only one pass through a result set.

PHP object fetching is magic and cannot be reproduced in user-space. Object fetching must be done during the single available pass over the result set.

Multiple iterations (further, seekable results) can be reproduced in user-space, but only with one fetch-type. This is how our PDO result works.


Some evidence of support for multiple iteration or seekable results:

#14 Updated by Woody Gilk almost 4 years ago

  • Target version changed from v3.0.8 to v3.0.9

#15 Updated by Woody Gilk almost 4 years ago

  • Status changed from Feedback to Closed

Still not going to fix this. If you want to be able to change the $as_object setting of a database result, open an issue for that. This issue simply makes no sense at all.

#16 Updated by Yahasana . over 2 years ago

Add a perfect path, PR here

Also available in: Atom PDF