Хранить php-код в базе данных MySQL — насколько это корректно?

На одном сайте нужно сделать раздел психологических тестов. Делать для каждого теста отдельный файл очень не хочется, поэтому всё будет храниться в базе данных. Это просто и удобно.

Тесты бывают с простым ключом: это когда каждому ответу соответствует определенный балл. Все баллы суммируются, и на основе этой суммы выдается результат. Для такого рода тестов не требуется отдельный php-обработчик. Он для всех один. Суть работы проста до безобразия. На основе суммы баллов в базе ищется соответствующий результат. Таблица примерно такая:
test_id | min_score | max_score | result
----------------------------------------------------------
1       | 0         | 3         | Результат 1.1
1       | 4         | 6         | Результат 1.2
1       | 7         | 9         | Результат 1.3
2       | 0         | 5         | Результат 2.1
2       | 6         | 9         | Результат 2.2

Таким образом, если сумма баллов, например, 5 и test_id = 1, то будет выдан "Результат 1.2"

Но бывают тесты со сложным ключом. Простым суммированием баллов там не обойтись. Например, что-то типа этого:
если на вопрос 1 был дан ответ А, то увеличить сумму баллов на 5.
если на вопрос 2 был дан ответ С, то уменьшить сумму баллов на 10.
если на вопрос 3 был дан ответ А и на вопрос 8 был дан ответ В, то результат теста недостоверен
и т.д.

В таком случае без php-обработчика не обойтись. Хранить для каждой теста свой обработчик в отдельном файле, это почти то же самое, что делать для каждого теста отдельный файл - не комильфо! Представьте, что через 2-3 года там будет 10000 тестов, это же файловый ужас!!!

Можно хранить php-обработчик в базе данных, но это значит использовать eval. А везде где только можно пишут, что использовать eval крайне не желательно. Что же делать? Возможно, Вы решали подобную задачу? Если да, то как Вы поступили? Если нет, то какие есть идеи по этому поводу? Насколько плох eval? Были ли у Вас проблемы при использовании этой функции в реальном проекте?
  • Вопрос задан
  • 6131 просмотр
Пригласить эксперта
Ответы на вопрос 11
begemot_sun
@begemot_sun
Программист в душе.
В целом хранить PHP-код в БД не корректно. MODx, например, страдает этим. Я не знаю куда смотрели авторы.

Корректно хранить данные, опираясь на которые скрипт может менять логику своего поведения.
Ответ написан
Комментировать
Хранить код в БД - извращение.
Ответ написан
begemot_sun
@begemot_sun
Программист в душе.
Напишите свой DSL который будет заточен под вашу задачу и храните код на DSL где вам угодно.
Например чтобы распарсить и выполнить код на DSL можно использовать вот такое:
https://github.com/loguntsov/jison/tree/php-port/p... - генератор парсеров на PHP.
Ответ написан
@GCoda
Если речь идет о тестах развлекательных где нет необходимости защиты от поддатасовок и мошеничества то можно просто создать кусок кода для клиентской части, никаких проблем с тем что код поломает серверную часть или злоумышленик вставит кусок своего кода в базу через иньекцию в другом месте.

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

Итого, я бы не хранил серверный код в базе, если нужны сложные правила для определения результатов и их нельзя сделать с помощью набора требований в сериализированом массиве или как регулярное выражение то я бы это все считал на клиенте.
Ответ написан
@artemev Автор вопроса
1. Простите, но с DSL не знаком. Что это в двух словах?
2. Согласен, что не корректно, но в данном конкретном случае не вижу другого выхода. Поэтому и ищу совета.
Ответ написан
WaliterIrlandec
@WaliterIrlandec
Я бы сделал подобие схемы через массив для каждого файла и его уже, JSONом например, в БД.
Ответ написан
Sander_Li
@Sander_Li
Backend developer
как вариант, хранимые процедуры
что мешает выгружать все ответы, а потом подсчитывать на php?
Ответ написан
@SHAKIRA
Желательно это не делать. Это опасно
Ответ написан
Ну можно ведь не доходить до крайности и не хранить каждый тест в отдельном файле. можно выдумать простенький фреймворк для тестов, пусть это будет для начала один большой класс с методами test_TEST_ID($answersData) и публичным методом solveTest($testID, $answersData) { $this->${test_$testID}($answersData); } . Для тестов с простым ключом там будет просто return $this->simpleTestSolver($anwersData), для сложных - логика. По мере разрастания класса можно будет уже выделить какой-то вменяемый общий код, разбить на подклассы.
Ответ написан
Если речь о простых кусках кода с макросами, типа
if($answ[1]=='b' && $answ[2]=='c' || $answ[3]=='a' && $answ[4]=='d' ) $summ+=10;

То может и ничего критичного, но вообще лучше хранить упакованное условие, вроде
1:b;2:c|3:a;4:d=10
Ответ написан
Mandor
@Mandor
- Хранить PHP-код в базе не страшно. Но: 1. исполнять код из БД медленнее чем из файла (нужен как минимум коннект к БД + не очень быстрый eval, как максимум - еще и чтение таблицы с данными с диска), 2. редактировать код из БД обычно менее удобно, чем из файла (будь-то FTP-доступ или SSH), то же самое на счет отладки.
- Eval можете использовать, он для того и сделан, чтобы его использовали тогда, когда надо.
- Если хранить обработчики в файлах или даже добавить к ним и сами тесты никакого файлового ужаса не будет. Просто продумайте структуру заранее. Если вас пугает наличие 10000 файлов в одном каталоге - можно предусмотреть разбивку на подкаталоги, в каждом из которых будет например по 100 тестов. В конце концов как хранят фотки фотохостинги и видео - видеохостинги, не в БД же?!
- Про DSL идея хорошая. Помимо всего остального это поможет снять запрет на редактирование обработчиков тестов только разработчиком сайта.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы