Symfony2 - счетчик просмотров страниц

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

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

Чтобы выполнить этот процесс, мне нужно настроить счетчик, добавить +1 каждый раз, когда он просматривается, сохранить это в базе данных, запросить это, а затем передать это обратно в Twig.

Две части, которые я не знаю, как сделать после часов поиска, это:

1) Как добавлять каждый раз, когда пользователь просматривает страницу (я знаю, что вы хотите как-то использовать +1)

2) Как запросить наибольшее количество просмотров страниц для передачи контроллеру и ветке

показать действие

/**
 * Show Post
 *
 * @param $slug
 * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
 * @return array
 *
 * @Route("/post/{slug}", name="acme_demo_show")
 * @Template("AcmeDemoBundle:Page:show.html.twig")
 */
public function showPostAction($slug)
{
    $article = $this->getDoctrine()->getRepository('AcmeBundle:Post')
        ->findOneBy(array(
            'slug' => $slug
        ));

    if (null === $article) {
        throw $this->createNotFoundException('Post was not found');
    }

    // Increment views each time user clicks on an article
    $em = $this->getDoctrine()->getManager();
    $views = $article->getViews();
    $article->setViews($views + 1);
    $em->flush();

    return array(
        'article' => $article,
    );
}

действие на боковой панели

public function sidebarAction()
{
    $em = $this->getDoctrine()->getManager();

    $post = $em->getRepository('AcmeDemoBundle:Article')
        ->getMostRecentArticles(5);

    if (!$post) {
        throw $this->createNotFoundException('No posts were found');
    }

    $articles = $this->getDoctrine()->getRepository('AcmeDemoBundle:Article')
        ->findBy(array(
            array(
                'views' => 'ASC'
            )
        ));

    return array(
        'post' => $post,
        'articles' => $articles
    );
}

Веточка

<h3>Most Popular Articles</h3>
    {% for article in articles %}
        <a href="{{ path('acme_demo_article_show', { slug: article.slug }) }}" class="anchor" style="text-decoration: none">{{ article.title }}</a><br>
    {% endfor %}

person marty    schedule 22.06.2014    source источник


Ответы (1)


Если вы хотите увеличить счетчик, когда пользователь щелкает ссылку, вам понадобится javascript с AJAX. В качестве альтернативы вы можете сделать это в контроллере вашего поста на чистом php с помощью чего-то вроде:

$views = $article->getViews();
$article->setViews($views + 1);
$em->persist($article);
$em->flush();

Лучшей практикой является добавление метода increment() к вашей сущности Article.

Затем, чтобы запросить статьи по просмотрам:

 $articles = $this->getDoctrine()->getRepository('AcmeBundle:Post')
        ->findBy(array(), array('views' => 'ASC'));

Но лучше всего написать собственный метод в репозитории объекта.

Обновлять:

Репозиторий

public function getMostPopularArticles()
{
    return $this->createQueryBuilder('article')
        ->select('article')
        ->orderBy('article.views', 'DESC')
        ->getQuery()
        ->execute();

}
person Tom Tom    schedule 22.06.2014
comment
Ему также нужно будет обеспечить блокировку таблицы/строки, иначе он не сможет гарантировать правильность приращения. - person Jovan Perovic; 22.06.2014
comment
@jperovic Как вы обеспечиваете блокировку таблицы/строки? - person marty; 22.06.2014
comment
Поскольку вы используете доктрину, об этом есть статья: docs.doctrine-project.org/en/2.0.x/reference/ - person Jovan Perovic; 22.06.2014
comment
Ваша ошибка возникает из-за метода findBy. Используйте тот же синтаксис, что и я. Первый массив мы можем оставить пустым, так как мы не ищем конкретное значение поля, второй массив — это предложение orderby. И @jperovic совершенно прав. - person Tom Tom; 22.06.2014
comment
Хорошо, я исправил это с помощью кода репозитория, и ошибка исчезла. Что вы имели в виду, используя тот же синтаксис? - person marty; 22.06.2014
comment
В соответствии с вашим обновленным кодом вы использовали --findBy(array(array('views' => 'ASC' ))) но это было -›findBy(array(), array('views' => 'ASC' )) - person Tom Tom; 22.06.2014
comment
@ Том Томс Ты прав, я не записал точно так, как ты написал, мой плохой. - person marty; 22.06.2014
comment
Ссылка на документы в приведенном выше комментарии теперь не работает, для всех, кто приходит сюда: doctrine-orm.readthedocs.org/en/latest/reference/ - person Tony; 12.11.2014
comment
почему здесь важна блокировка таблицы? - person Sébastien; 27.01.2015
comment
Потому что могут быть такие случаи, как: вы получаете счетчик из базы данных, но перед увеличением кто-то увеличивает его и сохраняет. На самом деле лучше всего использовать курсор, чтобы этого не происходило, но это не вопрос SQL, поэтому я выбрал простой и совместимый, и вам придется использовать блокировку таблицы для этого в зависимости от базы данных (например, у MongoDB есть метод incr()). - person Tom Tom; 30.08.2015