Laravel集合总是返回一个对象而不是一个数组

时间:2018-12-17 16:41:42

标签: php laravel laravel-5 vue.js

我有一个新闻页面,Vue和Vue Isotope正在加载该新闻页面。 Vue同位素要求我的数据是一个数组,以便当用户单击“加载更多”按钮时,可以在同位素上添加更多文章。这种工作方式是,当用户单击Laravel的分页功能,“加载更多”时,我可以将下一次加载的文章附加到Vue实例中现有的文章数组中。

我遇到的问题是,即使我使用toArray(),我的Laravel集合也总是返回对象而不是数组。

如果我使用get()直接从雄辩的语言加载文章,则可以正常工作并且是一个数组,但是,由于我需要将多个雄辩的查询合并在一起,因此不得不使用集合和merge()将4个雄辩的查询合并为一个大集合。我认为这是强迫集合始终作为对象返回的原因。

以下是我从控制器执行的功能:

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);

}

我能获得的最接近的方法是在->values()的末尾添加$allPosts,但这会删除下一页的分页链接,而仅检索实际的帖子,因此我无法使用它。

这是一个小片段,用于将初始$allPosts数据检索到Vue中

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

下面是用户单击“加载更多”按钮时调用的方法的代码段

        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
            ]))
        },

由于响应是一个对象,因此使用this.list.push()不起作用,并且由于this.list应该是一个数组而引发错误。

另外,这是我的Vue数据对象的一个​​片段

        data: {
            page: "{{route('api-news')}}",
            list: [ 

            ],
            paginatedList: [

            ],
},

我的列表对象的图像(其中list应该是一个数组):

enter image description here

我如何能够强制$allPosts作为数组返回?

2 个答案:

答案 0 :(得分:3)

我会尝试在values()之前而不是之后将呼叫添加到paginate()

$allPosts = $allPosts->sortByDesc('created_at')->values()->paginate(15);
return response()->json($allPosts);

Vue通过查看键确定数组是否被视为对象的数组:如果它们是数字,零索引和顺序键,则将其视为数组,否则,将其视为对象。

在您的情况下,sortByDesc()收集方法将保留原始键,因此Vue可以看到非顺序键并将其作为对象来处理。通过values()运行排序的集合,您应该获得正确索引的集合以传递给Vue。

更新

基于您的评论,以上解决方案仅适用于结果的第一页,而不适用于其他结果,我怀疑paginate()方法也正在维护原始键。因此,第一个块的键从0开始,而第二个块的键从15开始。您可能需要重写它,以便每个块都重新索引为0。

在将结果推送到模型之前,您还可以在Vue代码中执行此操作。像response.data.list.filter(item => item)之类的东西可能有用。

答案 1 :(得分:0)

也遇到此问题,如@Graeme指出的那样,此方法在第一页上有效,但在第二页上无效。最后,我最终手动覆盖了LengthAwarePaginator中的项目并重置了数组索引。

        $collect = $Products->get()->values();
        
        $ProductsPaginated = ProductResource::collection($collect)->paginate(12);
        $items = $ProductsPaginated->items();
        
        $decodeFix = json_decode($ProductsPaginated->toJson());
        $decodeFix->data = array_values($items);

        return json_encode($decodeFix);