Doctrine - получить смещение объекта в коллекции (реализуя бесконечную прокрутку)

Я использую Doctrine и пытаюсь реализовать бесконечную прокрутку для коллекции заметок, отображаемых в браузере пользователя.

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

Вот почему я не могу использовать традиционный метод разбивки на страницы, когда вы просто отправляете номер страницы на сервер, а сервер определяет смещение и количество результатов.

Чтобы дать вам пример того, что я имею в виду, представьте, что отображается 20 заметок, затем пользователь добавляет еще 2 заметки, поэтому отображается 22 заметки. Если я просто запрошу «страницу 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, который, учитывая весь набор заметок и одну конкретную заметку, может дать мне свое смещение, чтобы я мог использовать его для разбиения на страницы предыдущего утверждения Doctrine.

Я знаю, что возможной реализацией будет:

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

Я бы предпочел не перебирать все заметки, потому что производительность является важным фактором. Мне интересно, есть ли у Doctrine метод или вы можете предложить другой подход.


person dan    schedule 30.05.2012    source источник


Ответы (2)


В старом проекте я использовал для создания бесконечной прокрутки, как вы хотите сделать.

То, что я сделал, — это веб-служба, которая может получать параметр, называемый смещением.

В моем 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, а затем анализирую его на стороне клиента;)

person j_freyre    schedule 11.06.2012

Я не использовал 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
);
person Sarke    schedule 11.06.2012
comment
Это можно сделать - но что делать, если коллекция не упорядочена по id? Может быть, мне следует переименовать createdAt, потому что это вычитает обобщение того, что я пытаюсь сделать. - person dan; 11.06.2012
comment
Что ж, тогда получите createdAt последнего элемента идентификатора и сравните, используя его вместо I'd. - person Sarke; 11.06.2012