Самый быстрый способ сохранить просмотры страниц в базе данных с доктриной

Используя Symfony 4 с доктриной, я хочу сохранить просмотры страниц для одного объекта Program в базе данных. Я хочу сохранить это в базе данных, потому что хочу дать некоторым пользователям права просматривать эти числа. Что я сделал, так это добавил свойство к сущности следующим образом:

Program.php

/**
 * @ORM\Column(type = "integer", nullable=true)
 */
private $pageViews;

/**
 * @return mixed
 */
public function getPageViews()
{
    return $this->pageViews;
}

/**
 * @param mixed $pageViews
 */
public function setPageViews($pageViews)
{
    $this->pageViews = $pageViews;
}

А в моем ProgramController.php в функции showProgram

//...
$program->setPageViews($program->getPageViews()+1);
$em->persist($program);
$em->flush();

Это работает и добавляет 1 к существующему числу при каждом обновлении страницы. Мой вопрос: это приемлемый метод или есть более быстрые / лучшие альтернативы? И это снижает производительность или это незначительно?

public function addPageViews() { ++$this->pageViews; } может быть немного быстрее, кроме того, я не вижу, что можно оптимизировать
Cid 13.11.2018 10:29

Вы можете использовать doctrines dql lang, чтобы избежать гидратации сущностей, так что это будет намного быстрее, как это - ОБНОВЛЕНИЕ MyProject \ Model \ Program p SET p.pageViews = p.pageViews + 1

Eakethet 13.11.2018 10:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
2
90
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку вам действительно не нужна сущность, вы можете сделать это напрямую с помощью SQL, используя соединение Doctrine:

$connection = $this->getDoctrine()->getConnection();
$connection->executeUpdate('UPDATE page_view_counter SET page_view = page_view+1;');

или используя заранее подготовленный оператор:

$connection = $this->getDoctrine()->getConnection();
$statement = $connection->prepare(
    'UPDATE programs SET page_views = page_views + 1 WHERE programs.id = :id'
);
$statement->bindValue('id', $id);
$statement->execute();

Это немного ускорит процесс, если не использовать некоторые из более сложных функций ORM, которые вам не нужны в вашем случае.

Другой альтернативой для ускорения работы может быть переключение технологий, например хранение данных в кеше, таком как redis. Будет ли это действительно улучшать производительность (особенно при более высокой нагрузке), необходимо будет проверить с помощью какого-либо измерительного инструмента, такого как JMeter.

Мне действительно нужна сущность, потому что на показываемой мной странице мне нужно показать программные переменные. Так что, я думаю, в этом случае мое решение или решение Сида могло бы быть лучше?

Dirk J. Faber 13.11.2018 15:33

Да, по крайней мере, для начала. Вы все равно должны быть осторожны, так как ваш код может создавать условия гонки. Если пользователи A и B загружают сайт примерно в одно и то же время, скажем, 100 page_views, они оба загружают это значение и увеличивают его. Затем они сохранят свое значение, и поэтому независимо от того, какой из них сохраняет значение последним, счетчик, вероятно, будет говорить 101, а не 102. С моим кодом этого не произойдет, потому что каждый запрос обновляет значение в базе данных напрямую, а не загружает это первое. Если вы не возражаете против этого небольшого отклонения, ваше решение должно работать нормально.

dbrumann 13.11.2018 17:26

Кстати, подход Сида будет иметь тот же недостаток. Поскольку он также загружает значение в объект, обновляет его, а затем сохраняет новое состояние объекта в базе данных. Единственный способ обойти это - сделать обновление атомарным, не извлекая его сначала, а вместо этого выполняя +1 непосредственно в базе данных с помощью SQL.

dbrumann 13.11.2018 17:27

Очевидно, что прямая отправка SQL-запроса - безусловно, лучший вариант. Этот запрос достаточно прост, чтобы избежать проблем связи между различными СУБД. Будем надеяться, что у вас нет полей и таблицы с неправильным именем, которую необходимо заключить в обратные кавычки или скобки.

Cid 14.11.2018 08:53

@dbrumann, еще кое-что; есть ли способ привязать параметр к этому SQL? Я пытаюсь сохранить просмотры страниц для каждой отдельной программы, поэтому сейчас я пытаюсь сделать что-то вроде этого: $connection->executeUpdate('UPDATE programs SET page_views = page_views+1 WHERE programs.id is :id; '); Однако я не могу привязать параметр, чтобы использовать его в запросе.

Dirk J. Faber 14.11.2018 14:24

Да, DBAL также поддерживает параметры: doctrine-project.org/projects/doctrine-dbal/en/2.8/reference‌ /…. Я добавил пример к своему ответу

dbrumann 14.11.2018 16:11

Другие вопросы по теме