2

I have this code:

 $response['data'] = DB::table('customers')
                ->select(DB::raw('name,email,address1,address2,postalcode,state_region,country_code,phone,created_at'))
                ->where('user_id',"=",Auth::user()->id)
                ->where('name','like',"%$search_value%")
                ->orWhere('address1',"%$search_value%")
                ->orWhere('email','like',"%$search_value%")
                ->orWhere('address2','like',"%$search_value%")
                ->orWhere('city','like',"%$search_value%")
                ->orWhere('postalcode','like',"%$search_value%")
                ->orWhere('state_region','like',"%$search_value%")
                ->orWhere('country_code','like',"%$search_value%")
                ->orWhere('phone','like',"%$search_value%")
                ->orderBy('name', $order)
                ->limit($length)
                ->offset($start)
                ->get()->toArray();

The result of this one is this:

'data' => 
    array (size=10)
      0 => 
        object(stdClass)[194]
          public 'name' => string '|Barbara User' (length=13)
          public 'email' => string '[email protected]' (length=16)
          public 'address1' => string 'address aaddress' (length=17)
          public 'address2' => null
          public 'postalcode' => string '00000000' (length=10)
          public 'state_region' => string 'GA' (length=2)
          public 'country_code' => string 'US' (length=2)
          public 'phone' => string '12312312312' (length=10)
          public 'created_at' => string '2017-01-02 15:20:20' (length=19)
      1 => 
        object(stdClass)[201]
            public 'name' => string '|Barbara User' (length=13)
          public 'email' => string '[email protected]' (length=16)
          public 'address1' => string 'address aaddress' (length=17)
          public 'address2' => null
          public 'postalcode' => string '00000000' (length=10)
          public 'state_region' => string 'GA' (length=2)
          public 'country_code' => string 'US' (length=2)
          public 'phone' => string '12312312312' (length=10)
          public 'created_at' => string '2017-01-02 15:20:20' (length=19)
    ....

As you can see, there is still an object in the result even if I already did a toArray().

What seems to be the problem here?

Your help will be greatly appreciated! Thanks!

4 Answers 4

23

When you call toArray() on a Collection, if the underlying items implement the Illuminate\Contracts\Support\Arrayable interface, the collection will attempt to call toArray() on each item. However, when you use the query builder, the result will be a Collection of stdClass objects, and stdClass objects are plain objects that do not implement that interface and do not have a toArray() method. Therefore, when you call toArray() on a Collection of stdClass objects, you will just get a plain array of the stdClass objects back.

If you instead use Eloquent, define a Customer model, and use that model to perform the query, your result will be a Collection of Customer models, and those models do implement the Arrayable interface. So, when you call toArray() on this Collection, it will call toArray() on each item in the Collection, and your result will be an array of arrays.

If, for some reason, you don't want to use Eloquent, you will need to manually convert the items from objects to arrays. You can do this easily with the map or transform methods on the Collection. Use map if you want to return a new Collection and leave the original one alone, or use transform if you just want to modify the original Collection.

$response['data'] = DB::table('customers')  
    // query conditions, etc
    ->get()
    ->map(function ($item, $key) {
        return (array) $item;
    })
    ->all();
Sign up to request clarification or add additional context in comments.

1 Comment

This is best answer hands down. I didn't know the collection attempts to call toArray() on each item.
3

You are converting the collection to array, not each model specifically.

You could do something like this using Laravel's collection ->transform() method:

    $response['data'] = DB::table('customers')
            ->select(DB::raw('name,email,address1,address2,postalcode,state_region,country_code,phone,created_at'))
            ->where('user_id',"=",Auth::user()->id)
            ->where('name','like',"%$search_value%")
            ->orWhere('address1',"%$search_value%")
            ->orWhere('email','like',"%$search_value%")
            ->orWhere('address2','like',"%$search_value%")
            ->orWhere('city','like',"%$search_value%")
            ->orWhere('postalcode','like',"%$search_value%")
            ->orWhere('state_region','like',"%$search_value%")
            ->orWhere('country_code','like',"%$search_value%")
            ->orWhere('phone','like',"%$search_value%")
            ->orderBy('name', $order)
            ->limit($length)
            ->offset($start)
            ->get();

    $response['data']->transform(function ($item) {
        // return $item->toArray(); // You could do this if you called the query with model
        return (array)$item; // This should work in your case 
    });

This way $response['data'] will be a collection (not array) of arrays. You could additionally do this:

$response['data']->toArray();

To convert the collection to array as well.

3 Comments

I am getting a Call to undefined method stdClass::toArray() in your $item->toArray();
That is interesting. I tested similar code (called with Model instead of \DB::table()) and it worked. Then I assume Amit Gupta's answer should work.
If the query was performed using an Eloquent Model, there wouldn't be any need for this. Models implement the Arrayable interface, so calling toArray() on the Collection would automatically call toArray() on the individual items.
1

You can type cast each object in the collection to an array as:

$response['data']->transform(function($x) {
   return (array) $x; 
})->toArray();

And the toArray gets you from the collection back to an array.

Comments

0

toArray is changing the collection of objects into an array of objects, like it should. If you want the objects inside the collection to also be arrays, you need to first convert each object:

$users = DB::table('users')->where([...])->take(1)->get();

$array = $users->map(function($obj){
    return (array) $obj;
})->toArray();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.