ssuhat
ssuhat

Reputation: 7656

Laravel Remove [data] from collection

I've tried to query using eloquent and fractal

 $lists = Category::all();

 $result = Fractal::collection($lists, new CategoryTransformer())->getArray();

and return it

 return response()->json((['code' => "200", 'results' => $result]));

the json result is this:

{"code":"200","results":{"data":[{"id":"1","name":"Cafe","logo":null,"cover":""},{"id":"2","name":"SPA","logo":null,"cover":""},{"id":"3","name":"Hotel","logo":null,"cover":""}]}}

How to remove "data" after result?. So i can just get the array without "data".

I've tried:

 $result = Fractal::collection($lists, new CategoryTransformer(), 'results')->getArray();

 return (['code' => "200", $result]);

it return me :

   {"code":"200","0":{"results":[{"id":"1","name":"Cafe","logo":"","cover":""},{"id":"2","name":"SPA","logo":"","cover":""},{"id":"3","name":"Hotel","logo":"","cover":""}]}}

There is leading '0' before results. how can i remove it?

Thanks

Upvotes: 1

Views: 2086

Answers (3)

kmuenkel
kmuenkel

Reputation: 2789

Put these Collection Macros in your AppServiceProvider::boot() method:

/**
 * Remove the unnecessary nested 'data' keys
 *
 * @param string $case For consistency, define the type of keys that should be returned
 */
Collection::macro('fractal', function ($case = 'snake_case') {
    //Handle this as a nested function to block access to the $depth flag.
    //It's purpose is to indicate how deep the recursion is, and,
    //more importantly, when it's handling the top-level instance
    $recursion = function ($case = 'snake_case', array $items = [], $depth = 0) use (&$recursion) {
        //If the array has only one element in it, and it's keyed off 'data', remove the wrapper.
        //However, if it has a sibling element, such as 'meta', leave it alone
        if (array_key_exists('data', $items) && count($items) == 1) {
            $items = $items['data'];
        }

        $items = (new static($items))->mapWithKeys_v2(function ($item, $key) use (
            $case,
            $recursion,
            $depth
        ) {
            $key = $case ? $case($key) : $key;

            //If the nested item is itself an array, recursively perform the same transformation
            return is_array($item) ?
                [$key => $recursion($case, $item, ++$depth)] : [$key => $item];
        })->toArray();

        //Maintain the top-level 'data' wrapper.
        //This can easily be removed later in the controller if that's not needed either
        $items = (!$depth && !array_key_exists('data', $items)) ?
            ['data' => $items] : $items;

        return $items;
    };

    //Return the results in the form of an instance of Collection
    return new static($recursion($case, $this->items));
});

/**
 * Maintain non-sequential numeric keys when performing
 * \Illuminate\Support\Collection::mapWithKeys() functionality
 *
 * Source: https://github.com/laravel/framework/issues/15409#issuecomment-247083776
 */
collect()->macro('mapWithKeys_v2', function ($callback) {
    $result = [];
    foreach ($this->items as $key => $value) {
        $assoc = $callback($value, $key);
        foreach ($assoc as $mapKey => $mapValue) {
            $result[$mapKey] = $mapValue;
        }
    }
    return new static($result);
});

Then run your Fractal results through it: $results = collect($fractalResults)->fractal('camel_case')->get('data', []);

Upvotes: 0

cre8
cre8

Reputation: 13562

Try this:

return (['code' => "200", "results" => $result['results']);

I think the array method can't deal with a given array.

An other solution would be to add your results:

$result['code'] = 200;
return $result;

Upvotes: 1

haitran
haitran

Reputation: 735

The data is just the key, I think it won't make any issues. If you still need to remove it, update getArray() function.

Upvotes: 0

Related Questions