If you want it done every time you fetch results, go to your database.php config file (config/database.php) and under fetch options put: "FETCH_ASSOC".
Eloquent results as array instead of object
Is it possible to return a collection of arrays rather than objects from Eloquent query?
I am performing a raw query and for performance reasons would like the results not to be hydrated into objects (huge amounts of data being parsed) but returned as arrays inside the collection. So far I couldn't find a way around this, even with raw query it always returns instances of StdObject.
You can use ->toArrayl() method: https://laravel.com/docs/5.4/collections#method-toarray
Also there's a cast operator: (array) #your_object
As @cipas said convert your result in array using
$resultArr = ModelObject->toArray() .
If you want to avail the benefits of collection simply use collect($resultArr) method to convert array in to collection.
@Mittensoff , It's more of a unique case this one so I probably wouldn't want this to be the default. Is it possible to set it on runtime?
@cipsas , toArray() on collection only converts the collection, not underlying objects.
I could use (array) conversion on every object, but it doesn't really solve the performance problem as it is still being hydrated as an object in the first place, so it's just an additional step on top. I should probably point out that I'm handling hundreds of thousands of results at once.
Add ->all() after your query (even after ->get()) so it fetches the results for the current query in an array.
edit: If you're getting so many results at once and considering the fact that you won't need the object (StdClass or Collection) type that often, just edit the config file as I specified in my previous post.
@Nospoon then you can encode to json and decode it back to array:
$array = json_decode(json_encode($object), true);
@cipsas this solution worked, but it will crash if the result is too big to get allocated in ram. There should be a better solution.
@Nospoon, probably this will help you
This works for me (with Lumen 5.4.*).
Imagine that you do something like:
Model::query()->select(['a', 'b', 'c'])->where('created_at', '>', '2000-01-01')->limit(1000)->get();
Then, if you want the result without the model hydrate, you can do:
Model::query()->select(['a', 'b', 'c'])->where('created_at', '>', '2000-01-01')->limit(1000)
->getQuery()->get();
Which will collect the results from the Database Query Builder instead of the Eloquent Query Builder.
If you want to apply scopes, you can do it like:
Model::query()->select(['a', 'b', 'c'])->where('created_at', '>', '2000-01-01')->limit(1000)
->applyScopes()->getQuery()->get();
Hope it helps.
Try some think like this
$query = DB::connection()->getPdo()->query("select * from users");
$data = $query->fetchAll(PDO::FETCH_ASSOC);
dd($data);
And for next row set
$array = [];
$query = DB::connection()->getPdo()->query("select * from users");
do {
$data = $query->fetchAll(PDO::FETCH_ASSOC);
if ($data) {
array_push($array, $data);
}
} while ($pdoData->nextRowset());
You could use a higher order map function to convert all objects to associative arrays:
MyModel::all()->map->toArray()
Add an extra toArray() if you also want to convert the collection
You can use this
Model::get()->toArray();
If you don't have a collection of Models (but a collection of regular stdClass objects) you can convert to arrays with get_object_vars:
DB::table('some_table')
->get()
->map(fn ($row) => get_object_vars($row))
->toArray();
The problem isn't related to get an array as final result (using "toArray()" method), but to avoid the performance issues due to create a collection and then again convert it to an array. It's a useless behavior in some cases. This should be the way "$query->fetchAll(PDO::FETCH_ASSOC)"
In Laravel 10.* get() @ \vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php contain next code:
/**
* Execute the query as a "select" statement.
*
* @param array|string $columns
* @return \Illuminate\Database\Eloquent\Collection|static[]
*/
public function get($columns = ['*'])
{
$builder = $this->applyScopes();
// If we actually found models we will also eager load any relationships that
// have been specified as needing to be eager loaded, which will solve the
// n+1 query issue for the developers to avoid running a lot of queries.
if (count($models = $builder->getModels($columns)) > 0) {
$models = $builder->eagerLoadRelations($models);
}
return $builder->getModel()->newCollection($models);
}
applyScopes() and getModels() are public methods.
dump(Comment::where('author', '=', '1')->get()->all());
dump(Comment::where('author', '=', '1')->applyScopes()->getModels());
dump(Comment::where('author', '=', '1')->get());
First and second expressions return arrays, third - collection. It works fine in my test case. So can we use it?
if you want to get result as array of array you can use this
DB::table('...')
->select(DB::raw('select * from ...'))
->get()->map(function($item) {return (array) $item;});
A very old post, but I got here Googling for the same problem... Most of the answers are converting Collections of models to arrays. What OP is asking is results, without the overhead of hydrating models, etc. Because I didn't find my answer here, here is how I ended up doing it:
$query = MyModel::select(['columns'])->where('some_column', '>', 500); // notice NO get() or whatsoever, just building the query
$results = DB::select($query->toSql(), $query->getBindings()); // results is an array with row objects, so no hydrated models
$first_row = DB::select($query->toSql(), $query->getBindings()); // results is an array with the first result-set object
Hope this helps someone in the future (or the past ;))
If you don't need all of the features of the Query Builder (e.g. different read/write DBs, beforeExecutingCallbacks, reconnectIfMissingConnection, pretending, retry on lost connection, logQuery) then you can use this simpler method that uses Query Builder to bulid the query and PDO to execute it:
$query = \Illuminate\Support\Facades\DB::table("myTable")
->where('myColumn', 'myValue');
// Prepare A PDO Statement using the Query Builder
// see \Illuminate\Database\Query\Builder::runSelect
$statement = $query->connection->getPdo()->prepare($query->toSql());
// Bind Values see \Illuminate\Database\Connection::select
$query->connection->bindValues(
$statement,
$query->connection->prepareBindings($query->getBindings())
);
// Execute the Statement
$statement->execute();
// Fetch the results
$myArrayOfArrays = $statement->fetchAll(\PDO::FETCH_ASSOC);
If you need the full features of the Query Builder, then you have to use reflection to change the protected $query->connection->fetchMode. Warning: this changes fetch more for all queries unless reset. I don't recommend this method because protected members are usually protected for a reason.:
// Build A Query
$query = \Illuminate\Support\Facades\DB::table("myTable")
->where('myColumn', 'myValue');
// Change the connection's protected fetchMode, so we can get a collection of Arrays
$reflectionProperty = (new ReflectionObject($query->connection))
->getProperty('fetchMode');
$originalFetchMode = $reflectionProperty->getValue($query->connection);
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($query->connection, \PDO::FETCH_ASSOC);
// Run they query
$myCollectionOfArrays = $query->get();
// Reset the fetch mode back to the original so other queries still return
// objects as expected.
$reflectionProperty->setValue($query->connection, $originalFetchMode);
Whilst we are topping up this question
App\Models\User::get()->map->only(['id','email','name']);
returns an array of array
or, often helpful
$users = App\Models\User::get()->map->only(['id','email','name'])->keyBy('id');
By keying by the id you can access a member of the arrays like $users[15] rather than having to search the array.
Please or to participate in this conversation.