lundi 17 décembre 2018

Laravel collection always returns an object instead of an array

I have a news page which is being loaded by Vue and Vue Isotope. Vue isotope requires that my data is an array so that I can append more articles to the isotope when the user clicks the "Load more" button. The way this works is, when the user clicks "load more", using Laravel's pagination function, I can simply append the next load of articles to my existing array of articles in my Vue instance.

The issue I am having is that my Laravel collection always returns an object instead of an array, even when I use toArray().

If I load my articles straight from eloquent using get(), this works fine and is an array, however because I need to merge multiple eloquent queries together, I am forced to use a collection and merge() to merge 4 eloquent queries into one large collection. This is what I believe is forcing the collection to always return as an object.

Below is my function from the controller:

public function apiIndex()
{
    $articles = Article::latest('featuredArticle')->latest()->published()->get();
    $twitterPosts = TwitterPost::where('published', 'published')->get();
    $facebookPosts = FacebookPost::where('published', 'published')->get();
    $vimeoPosts = VimeoPost::where('published', 'published')->get();

    $articles->map(function ($post) {
        $post['type'] = 'Article';
        return $post;
    });

    $twitterPosts->map(function ($post) {
        $post['type'] = 'Twitter';
        return $post;
    });

    $facebookPosts->map(function ($post) {
        $post['type'] = 'Facebook';
        return $post;
    });

    $vimeoPosts->map(function ($post) {
        $post['type'] = 'Vimeo';
        return $post;
    });

    $allPosts = collect();

    $allPosts = $allPosts->merge($articles);
    $allPosts = $allPosts->merge($twitterPosts);
    $allPosts = $allPosts->merge($facebookPosts);
    $allPosts = $allPosts->merge($vimeoPosts);

    $allPosts = $allPosts->sortByDesc('created_at')->paginate(15);

    return response()->json($allPosts);

}

The closest I have been able to get is by adding ->values() to the end of $allPosts however this removes the pagination link for the next page and only retrieves the actual posts so I cannot use this.

Here is a small snippet for retrieving the initial $allPosts data into Vue

    mounted () {
        axios.get(this.page)
        .then(response => ([
            this.list = response.data.data,
            this.page = response.data.next_page_url
        ]))
    },

Here is a snippet of what method is called when the user clicks the "Load more" button

        loadMore: function() {
            axios.get(this.page)
            .then(response => ([
                this.paginatedList = response.data.data,
                this.list.push(this.list, this.paginatedList),
                this.page = response.data.next_page_url
            ]))
        },

Because the response is an object, using this.list.push() does not work and throws an error because this.list should be an array.

Additionally, here is a snippet of my Vue data object

        data: {
            page: "",
            list: [ 

            ],
            paginatedList: [

            ],
},

How would I be able to force $allPosts to return as an array?



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire