web-dev-qa-db-fra.com

Comment puis-je paginer une collection fusionnée dans Laravel 5?

Je crée un flux qui contient deux types d'objets, BluePerson et RedPerson. Pour créer le flux, je récupère tous les deux objets, puis je les fusionne dans une collection. Après cela, il me faut les paginer, mais paginer concerne des modèles éloquents et des requêtes de base de données, et non des collections, semble-t-il. J'ai souvent entendu parler de la création manuelle d'un paginateur, mais la documentation, en particulier dans l'API, est rare (je n'arrive même pas à trouver les arguments acceptés par la classe Paginator.) 

Comment puis-je paginer les résultats de la fusion de mes collections?

public function index()
{
    $bluePerson = BluePerson::all();
    $redPerson = RedPerson::all();

    $people = $bluePerson->merge($redPerson)->sortByDesc('created_at');


    return view('stream.index')->with('people', $people);
}
16
KinsDotNet

cependant, paginer concerne des modèles éloquents et des requêtes de base de données, et non des collections, semble-t-il.

Tu as raison. mais il existe une fonction pagination pour les collections. forPage

Syntaxe:

Collection forPage(int $page, int $perPage)

Exemple:

Le repos est simple. 

public function foo()
{
    $collection = collect([1,2,3,4,5,6,7,8,9,0]);
    $items = $collection->forPage($_GET['page'], 5); //Filter the page var
    dd($items);
}
17
itachi

Si vous souhaitez utiliser LengthAwarePaginator, instanciez-en simplement un. Comme mentionné dans les commentaires d'une réponse précédente, vous devrez définir le chemin pour cela. Vous devrez également vous assurer de résoudre le "currentPage" et de définir les éléments à renvoyer avant d'instancier le paginateur. Tout cela peut être fait avant/sur l'instanciation. Donc, une fonction peut ressembler à quelque chose comme:

function paginateCollection($collection, $perPage, $pageName = 'page', $fragment = null)
{
    $currentPage = \Illuminate\Pagination\LengthAwarePaginator::resolveCurrentPage($pageName);
    $currentPageItems = $collection->slice(($currentPage - 1) * $perPage, $perPage);
    parse_str(request()->getQueryString(), $query);
    unset($query[$pageName]);
    $paginator = new \Illuminate\Pagination\LengthAwarePaginator(
        $currentPageItems,
        $collection->count(),
        $perPage,
        $currentPage,
        [
            'pageName' => $pageName,
            'path' => \Illuminate\Pagination\LengthAwarePaginator::resolveCurrentPath(),
            'query' => $query,
            'fragment' => $fragment
        ]
    );

    return $paginator;
}
25
Michael Holland

Vous pouvez essayer de paginer les deux ensembles et de les fusionner. Vous trouverez plus d'informations sur la pagination dans docs et api . Voici un exemple de création manuelle de votre propre paginateur ...

$perPage = 20;
$blue = BluePerson::paginate($perPage / 2);
$red = RedPerson::paginate($perPage - count($blue));
$people = PaginationMerger::merge($blue, $red);

J'ai inclus la classe PaginationMerger ci-dessous.

use Illuminate\Pagination\LengthAwarePaginator;

class PaginationMerger
{
    /**
     * Merges two pagination instances
     *
     * @param  Illuminate\Pagination\LengthAwarePaginator $collection1
     * @param  Illuminate\Pagination\LengthAwarePaginator $collection2
     * @return Illuminate\Pagination\LengthAwarePaginator
     */
    static public function merge(LengthAwarePaginator $collection1, LengthAwarePaginator $collection2)
    {
        $total = $collection1->total() + $collection2->total();

        $perPage = $collection1->perPage() + $collection2->perPage();

        $items = array_merge($collection1->items(), $collection2->items());

        $paginator = new LengthAwarePaginator($items, $total, $perPage);

        return $paginator;
    }
}
6
Kelt

Essayez de suivre.

$arr = $pets->toArray();
$paginator->make($arr, count($arr), $perPage);
1

Vous pouvez ajouter le code suivant pour Collection dans Providers/AppServiceProvider

    // Enable pagination
    if (!Collection::hasMacro('paginate')) {

        Collection::macro('paginate', 
            function ($perPage = 15, $page = null, $options = []) {
            $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
            return (new LengthAwarePaginator(
                $this->forPage($page, $perPage)->values()->all(), $this->count(), $perPage, $page, $options))
                ->withPath('');
        });
    }

Ensuite, vous pouvez appeler paginer depuis une collection, comme un modèle Eloquent. Par exemple

$pages = collect([1, 2, 3, 4, 5, 6, 7, 8, 9])->paginate(5);
1
dushoda