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

Gra*_*eme 2 php laravel vue.js laravel-5

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

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

如果我直接从 eloquent using 加载我的文章get(),这工作正常并且是一个数组,但是因为我需要将多个 eloquent 查询合并在一起,我被迫使用一个集合merge()并将 4 个 eloquent 查询合并到一个大集合中。这就是我认为迫使集合始终作为对象返回的原因。

以下是我的控制器功能:

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

}
Run Code Online (Sandbox Code Playgroud)

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

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

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

这是用户单击“加载更多”按钮时调用的方法的片段

        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
            ]))
        },
Run Code Online (Sandbox Code Playgroud)

因为响应是一个对象,所以 usingthis.list.push()不起作用并抛出错误,因为this.list应该是一个数组。

此外,这是我的 Vue 数据对象的片段

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

            ],
            paginatedList: [

            ],
},
Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明

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

Pet*_*ter 7

我会尝试加入通话values() 之前paginate(),而不是之后。

$allPosts = $allPosts->sortByDesc('created_at')->values()->paginate(15);
return response()->json($allPosts);
Run Code Online (Sandbox Code Playgroud)

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

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

更新:

根据您的评论,上述解决方案仅适用于结果的第一页,而不适用于其他结果,我怀疑该paginate()方法也在维护原始密钥。所以第一个块的键从 0 开始,但第二个块的键从 15 开始。您可能需要覆盖它,以便每个块都重新索引为 0。

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

  • 这几乎解决了问题。第一页没问题,并且 `data` 作为数组返回,但是第二页 `data` 仍然作为对象返回。 (2认同)

Kik*_*ksy 6

正如@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);
Run Code Online (Sandbox Code Playgroud)