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: "{{route('api-news')}}",
list: [
],
paginatedList: [
],
},
Image of my list object (where list should be an array instead):
How would I be able to force $allPosts
to return as an array?