Laravel - Membuat paginasi catatan acak

Bagaimana kita bisa membuat paginasi melalui catatan acak di laravel? Misalnya:

$products = Product::all()->orderBy(DB::raw('RAND()'));
$products->paginate(4);
$products->setPath('products');

Di atas akan berakhir dengan catatan duplikat, karena urutan acak. Bagaimana saya bisa mempertahankan objek $products sehingga, ketika permintaan halaman baru dibuat, ia harus memfilter kumpulan catatan acak yang sama/tetap?


person dang    schedule 31.05.2016    source sumber
comment
Tolong beri tahu kami apa yang sudah Anda coba dan apa yang tidak berhasil   -  person Alexandre Cartapanis    schedule 31.05.2016
comment
@AlexandreCartapanis - pagination memberikan catatan duplikat. Kami menggunakan kode di atas.   -  person dang    schedule 31.05.2016


Jawaban (3)


Saat Anda mendalami dokumentasimysql dan cari fungsionalitas RAND() Anda akan melihat Anda dapat menggunakan "seed".

Dengan menggunakan seed Anda akan selalu mendapatkan hasil yang sama yaitu secara acak.

Contoh:

$products = Product

    ::all()

    ->orderBy(DB::raw('RAND(1234)'))

    ->paginate(4);

Anda dapat membuat benih Anda sendiri dan menyimpannya dalam satu sesi atau sesuatu untuk diingat.

Perbarui

Pembuat kueri Laravel kini memiliki fungsi yang melakukan hal yang sama sama:

$products = Product

    ::all()

    ->inRandomOrder('1234')

    ->paginate(4);
person Thomas Van der Veen    schedule 31.05.2016
comment
+1. Karena saya tidak menggunakan Eloquent, saya merasa beruntung telah menemukan bahwa ternyata fungsi pembantu pengocokan Koleksi juga mengizinkan parameter seed, yang berguna jika Anda menggunakan penomoran halaman dan ingin mencegah duplikat pada langkah selanjutnya. halaman: github.com/illuminate/support/blob/5.6/Collection. php#L1380 - person Ryan; 24.06.2018

Solusi dengan Laravel + Eloquent

Sebelum kueri Eloquent, atur variabel sesi. Saya menggunakan time() untuk nilai sesi, sehingga saya dapat mempertahankan urutan yang sama untuk jangka waktu tertentu. Misalnya 3600 detik (1 jam).

if ($request->session()->has('session_rand')) {

    if((time() - $request->session()->get('session_rand')) > 3600){
        $request->session()->put('session_rand', time());
    }
}else{
    $request->session()->put('session_rand', time());
}

Tambahkan ->orderBy() ke kueri Eloquent menggunakan DB::raw() dan variabel sesi yang kita atur di atas:

->orderBy(DB::raw('RAND('.$request->session()->get('session_rand').')'))
person Darren Murphy    schedule 14.09.2018

Solusi Ajax + potongan + sesi + pemuatan lambat + penomoran halaman + fasih + blade

dapatkan semua produk, atur jumlah item untuk setiap potongan (seperti paginasi) dan simpan ke dalam sesi (kami menyimpan potongan ke dalam sesi sehingga ketika permintaan ajax masuk, ia tidak akan memanggil $products = Product::inRandomOrder()->get(); lagi), potongan pertama akan menjadi pagination pertama

ketika ajax meminta lebih banyak produk, ia akan mendapatkan produk dari sesi dan mendapatkan potongan produk yang benar berdasarkan nomor halaman yang diminta ajax.

jika tidak ada potongan lagi, kembalikan saja tanpa produk apa pun

    if(!$request->ajax()){

        $products = Product::inRandomOrder()->get();
        $chunks = $products->chunk(4);

        \Session::put('chunks',$chunks);
        $products = $chunks[0];
    }else{
        $page = $request->all()['page'];                
        $chunks = \Session::get('chunks');

        if(count($chunks)<$page){
            \Session::forget('chunks');
            return;
        }else{
            $products = $chunks[$page-1];
        }
    }

   if ($request->ajax()) {
        $view =  view('product_lazyLoad',compact('products'))->render();
        return response()->json(['html'=>$view]);
   }

   return view('products',compact('products'));

produk.blade.php : halaman utama

@if($products)
    <ul class="row" id="productLists">
        @include('product_lazyLoad')
    </ul>
@endif

<!-- load records -->

<div class="col-12 ajax-load text-center" style="display:none">
    <p><img src="/images/loader.gif">Loading More Products</p>
</div>

product_lazyload.blade.php : menampilkan produk

@foreach($products as $product)
    <div>
        <p>Display your products here</p>
    </div>
@endforeach

panggilan ajax font-end : ketika halaman digulir ke bawah halaman, halaman variabel akan bertambah secara otomatis dan meminta backend untuk lebih banyak produk. jika lebih banyak produk yang dikembalikan, produk tersebut akan ditambahkan ke elemen dengan id = "daftar produk" di produk.blade.php

    //lazy load
    var page = 1;
    $(window).scroll(function() {
        if($(window).scrollTop() + $(window).height() >= $(document).height()) 
        {
            page++;
            loadMoreData(page);
        }
    });

  function loadMoreData(page){
        $.ajax({
            url: '?page=' + page,
            type: "get",
            beforeSend: function(){
                $('.ajax-load').show();
            }
        }).done(function(data){
            if(!data.html){
                $('.ajax-load').html("No more records found");
                $('.ajax-load').show();
                return;
            }

            $('.ajax-load').hide();
            $("#productLists").append(data.html);

        }).fail(function(jqXHR, ajaxOptions, thrownError){
             //error handle
        });
    }
person Jason    schedule 17.12.2018