Коллекция Laravel всегда возвращает объект вместо массива - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть страница новостей, которая загружается Vue и Vue Isotope.Vue isotope требует, чтобы мои данные были массивом, чтобы я мог добавлять больше статей к изотопу, когда пользователь нажимает кнопку «Загрузить еще».Это работает так: когда пользователь нажимает «загрузить больше», используя функцию разбиения на страницы Laravel, я могу просто добавить следующую загрузку статей в мой существующий массив статей в моем экземпляре Vue.

Проблема, с которой я столкнулся, заключается в том, что моя коллекция Laravel всегда возвращает объект, а не массив, даже когда я использую toArray().

Если я загружаю свои статьи прямо из eloquent, используя 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: [

            ],
},

Изображение моего объекта списка (вместо которого список должен быть массивом):

enter image description here

Как мне заставить $allPosts возвращаться как массив?

1 Ответ

0 голосов
/ 18 декабря 2018

Я бы попытался добавить вызов к 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) может работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...