0

Doctrine を使用しており、ユーザーのブラウザーに表示されるメモのコレクションに無限スクロールを実装しようとしています。

アプリケーションは非常に動的であるため、ユーザーが新しいメモを送信すると、メモはサーバーに送信 (および保存) されるだけでなく、すぐにコレクションの先頭に追加されます。

これが、ページ番号をサーバーに送信するだけで、サーバーがオフセットとそこから結果の数を 計算する従来のページネーション方法を使用できない理由です。

たとえば、20 件のメモが表示され、ユーザーがさらに 2 件のメモを追加すると、22 件のメモが表示されます。単純に「ページ 2」を要求すると、そのページの最初の 2 つのアイテムが、現在ユーザーに表示されているページの最後の 2 つのアイテムになります。

だからこそ、これから説明するより洗練された方法を求めています。

詳細については、AJAX 要求を処理するサーバー コードの一部である次のコードを検討してください。

// $lastNoteDisplayedId is coming from the AJAX request
$lastNoteDisplayed = $repository->findBy($lastNoteDisplayedId);

$allNotes = $repository->findBy($filter, array('numberOfVotes' => 'desc'));

$offset = getLastNoteDisplayedOffset($allNotes, $lastNoteDisplayedId);

// retrieve the page to send back so that it can be appended to the listing
$notesPerPage = 30       
$notes = $repository->findBy(
  array(), 
  array('numberOfVotes' => 'desc'), 
  $notesPerPage, 
  $offset
);
$response = json_encode($notes);
return $response;

基本的にgetLastNoteDisplayedOffset、メモのセット全体と 1 つの特定のメモが与えられた場合、そのオフセットを与えることができるメソッドを記述する必要があります。これにより、前の Doctrine ステートメントのページ付けに使用できます。

おそらく可能な実装は次のようになります。

getLastNoteDisplayedOffset($allNotes, $lastNoteDisplayedId) {
    $i = 0;
    foreach ($allNotes as $note) {
        if ($note->getId() === $lastNoteDisplayedId->getId()) {
                break;
        }
        $i++;   
    }
    return $i;
}

パフォーマンスは重要な要素であるため、すべてのノートをループするのは避けたいと思います。Doctrine 自体がメソッドを持っているのか、それとも別のアプローチを提案できるのか疑問に思っていました。

4

2 に答える 2

1

古いプロジェクトでは、私はあなたがやりたいように無限のスクロールを作成していました。

私がやったことは、offsetと呼ばれるパラメーターを受け取ることができるWebサービスです。

私のJavaScriptには、ユーザーがドキュメントを十分に下にスクロールしたかどうかを検出するイベントを追加します。イベントがトリガーされたら、ajaxクエリを作成し、ページにすでに存在する要素の数をカウントします(それらはテーブルにありました)。

$(window).scroll(function(){
            if  ($(window).scrollTop() + $(window).height() >= $(document).height() - 50){
                lastEvents();
            }
        });


var isLoading = false;
function lastEvents() {
    if (!isLoading) {
      isLoading = true;
      var nb = $('table#events tr').length

      $.ajax({
        url: 'getEvents.php',
        data: {
          offset: nb
        },
        success: function (data) {
          isLoading = false;
          $('.table#events').append(data);
        }
      });
    }
}

それから私の教義の質問で、私はそのようなことをしました:

$events = Doctrine_Query::create()
            ->select()
            ->from('Events e')
            ->orderBy('e.created_at ASC')
            ->limit(10)
            ->offset($_REQUEST['offset'])
            ->execute();

次に、テンプレートで、JSが追加される新しいテーブル行を生成します。

注:今、私は確かにjsonを返し、クライアント側で解析します;)

于 2012-06-11T11:13:15.710 に答える
1

私はDoctrineを使用していませんが、解決策にはオフセットではなくWHERE条件を使用する必要があります。こんな感じになると思いますが、Doctrineの構文がわかりません。

$notes = $repository->findBy(
  array('id < ' => $lastNoteDisplayedId), // I'm guessing the first param is the where condition, don't know the syntax
  array('createdAt' => 'desc'), 
  $notesPerPage
  // remove the offset
);
于 2012-06-11T10:36:31.057 に答える