[Закрыть]
 
popoff.donetsk.ua
Электронный мозг думает за нас точно также, как электрический стул за нас умирает.
Начало | Новости | Статьи | Форум | Опросы | Карта сайта | Обо мне
popoff.donetsk.ua - Статьи - Программирование - Движок для портала - Часто задаваемые вопросы
Я это делаю
Персональное меню
Голосование
Деньги, либо любимое занятие? Постоянный адрес этого вопроса
Деньги, но неинтересная работа и невозможность уделить время семье
Интересная работа, возможность саморазвиваться, но нищенский заработок
Ваш возраст (не обязательно)
Почему? (не обязательно)

Голосование закрыто.

Поиск по сайту
Реклама
Гинеколог, стоматолог, психотерапевт в Донецке
Статистика

Часто задаваемые вопросы

Постоянный адрес статьи

Содержание

Где взять базу к системе popoff.donetsk.ua/light?

База данных создается на страницах программиста. Страницы программиста находятся в папке public_html/prg/. Пароль для входа задается в библиотеке prg.options в файле libs/prg/prg.options.php. Скрипты для создания базы данных находятся в файлах libs/*/*.db.php.

В системе для хранения деревьев используются Nested Sets. Почему Вы выбрали именно этот способ?

Время от времени возникает вопрос о том, какой из способов хранения деревьев лучше. Кто-то хвалит или ругает один способ, кто-то - другой. О большинстве способов можно сказать что-то хорошее и что-то плохое. Но здесь я не буду оценивать достоинства и недостатки способов хранения деревьев в базах данных.

Вот здесь можно найти информацию о способах хранения деревьев:
http://phpclub.ru/faq/Tree

В своей системе я выбрал Nested Sets для хранения деревьев. Но я не буду отстаивать этот выбор, потому что я не считаю это наилучшим выбором. Я так же не буду спешить изменить этот способ хранения деревьев на какой-либо другой, потому что недостатки других способов хранения деревьев я тоже знаю. Почему я выбрал именно Nested Sets? Так сложилось исторически. В будущем, возможно, способ хранения деревьев будет задаваться в настройках.

Почему при генерации страниц выполняется так много SQL-запросов?

Действительно, в моей системе при генерации страниц может генерироваться довольно большое количество (порядка 500) sql-запросов.

Дальше я буду говорить о том, почему от большого числа запросов избавиться не просто. Хотя я буду защищать свое «право на запросы», я все же согласен с тем, что такое количество запросов при каждом обращении к сайту - это очень много. Именно поэтому я ввел в систему модуль кеширования. С его появлением много запросов выполняется только при первом обращении к странице, а потом оно уменьшается до разумных пределов.

Время от времени возникает вопрос о том, возможно ли избавиться от большого количества запросов. Многие говорят, что «большое количество запросов - это потому что кривые руки программиста». На самом деле люди, которые так говорят, не понимают, что они говорят: они привыкли писать простенькие сайтики, без поддержки мультиязычности и без особо гибкого интерфейса - в таком случае большое количество sql-запросов действительно говорит о кривых руках программиста.

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

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

Порядка 90% запросов возникает из-за использованной системы поддержки мультиязычности: все отображаемые на сайте сообщения и надписи хранятся в базе данных. В случае, если Вы только что установили систему и у Вас полностью пустая база данных переводов, то для каждой надписи выполняется 2 запроса, а при первом обращении - 3 запроса (1 - найти перевод на текущий язык, 2 - найти перевод на наиболее похожий язык, 3 - добавить сообщение в базу данных).

Попытаемся уменьшить это количество. Курсивом я буду выделять то, как мне предлагали это количество уменьшить. Начнем с малого.

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

Запрос для проверки перевода на наиболее похожий язык содержит в себе сортировку по похожести языков, а для поиска перевода на текущий язык - только поиск по уникальному ключу. При заполненной базе данных поиск перевода выполняется по одному запросу - поиск перевода на текущий язык. Удалив этот запрос, при при пустой базе данных мы получили бы на 30% меньше запросов для поиска переводов. Но при заполненной базе данных мы выполняли бы такое же количество запросов: один для каждого сообщения, но теперь этот один запрос - гораздо более сложный. Мы выиграли?

Хорошо, этот спсособ оптимизации - плохой. Давайте поищем в другом месте. Например, если на странице выводятся одинаковые сообщения, то их можно было бы кешировать и при повторном показе не выполнять sql-запрос, а доставать сообщение из кеша. Но на страницах не так-то часто выводятся одинаковые сообщения, гораздо чаще одинаковые сообщения выводятся между страницами, например, на всех страницах есть название сайта. Можно было бы кешировать, например, в переменных сессии.

Ужас! Да, закешировав в переменных сессии запросы к базе данных мы действительно уменьшили бы их количество до минимума при повторных обращениях к сайту. Но зачем, скажите мне, делать кеширование результатов запроса средствами php, если сама MySQL уже кеширует результаты своих запросов! Фактически, получается, мне предлагают сделать кеш для кеша. К тому же гораздо менее производительный, чем кеш запросов в MySQL.

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

Кардинальное решение. Но здесь вопрос упирается в то, почему я выбрал именно такой способ хранения данных? Потому что при хранении переводов в базе данных:

  1. проще искать перевод на наиболее похожий язык в случае, если перевода на нужный язык нет.
  2. можно автоматически добавлять новые сообщения в базу данных перевода. Иначе я должен был бы ходить по сайту и искать, «а где это у меня там появилась новая непереведенная фараза?» Хорошо, если на сайте всего две-три страницы и я - единственный человек, который работает над сайтом.
  3. я могу предоставить администраторам привилегии на добавление новых языков, на редактирование переводов и сделать любой удобный интерфейс для перевода сайта. Иначе я должен был бы либо давать им ftp-аккаунты, либо закачивать вместо них файлы переводов, либо объяснять им настройки php, либо самому настраивать, либо объяснять им, как редактировать файлы на php, либо каким-либо другим способом учавствовать в процессе перевода.
  4. у меня одинаковым способом хранятся как переводы коротких фраз/сообщений, так и все данные, которые зависят от языка. Эти данные есть практически в любом модуле. В чате - названия комнат. В форуме - названия и комментарии к темам. В модуле управления загрузкой изображений - комментарии/заголовки изображений. В службе управления аккаунтами пользователей - названия ролей. А в таких модулях, как служба новостей и служба управления статьями вообще все зависит от языка.
  5. текстовый файл со списком переводов одних лишь надписей для такого простенького сайта, как popoff.donetsk.ua весит порядка 150 КБ. Если говорить о способе хранения базы данных в виде php-скрипта (в виде массива, в виде набора констант или любым другим способом), то я не стану утверждать, что парсить такого размера скрипт и искать переводы в массиве - это быстрее, чем обращаться к базе данных. Просто мне так показалось, хотя на самом деле это может быть и не так.
  6. собственно, из желания все контролировать я отказался от использования встроенной функции GetText().

Все переводы у меня ищутся через функцию m(), и как именно эта функция устроена внутри - не имеет значения для остальных скриптов. Просто изменив эту функцию можно легко изменить способ хранения сообщений. Вопрос лишь в том, стоят ли те sql-запросы, от которых мы избавимся той головной боли, которую мы получим взамен?

Кроме мультиязычности много sql-запросов может выполняться в следующих случаях:

  • При подсчете статистики - у меня она хранится не в одной таблице, а в нескольких. Поэтому при каждом обращении выполняется поиск/добавление в разные таблицы. На эти таблицы по очереди накладываются и снимаются блокировки, а наложить блокировку и снять блокировку - это два разных sql-запроса. О том, почему в данном случае выгоднее блокировать их разными sql-запросами по очереди, а не сразу все, написано в документации по MySQL в разделе «Оптимизация в MySQL - Вопросы блокировок». Впрочем, статистика будет оптимизирована в будущих версиях.
  • Некоторые элементы страниц невыгодно кешировать, и поэтому они создают дополнительное количество sql-запросов даже при включенном кеше. Это в первую очередь касается тех элементов, содержимое которых меняется при каждом обращении к сайту (например, ротаторы). Наличие элементов этого первого типа не позволяет закешировать ВСЮ генерируемую страницу. Во вторую очередь это касается тех элементов, содержимое которых зависит от сессии (например, у администратора в службе новостей могут появиться ссылки на удаление новостей - эти ссылки зависят от сессии). Поскольку эти элементы второго типа изменяются значительно чаще, чем другие элементы страниц, то кешировать их вместе со всеми остальными элементами не выгодно - выгоднее кешировать отдельно часто изменяющиеся элементы и отдельно - редко изменяющиеся. Отдельный кеш, однако, приводит к генерации отдельных sql-запросов.
  • Я с большой осторожностью отношусь к кешированию данных, которые зависят от непроверенной информации, пришедшей от пользователей. Первый пришедший мне в голову пример - кеширование статей. Если я буду кешировать в зависимости от имени файла, переданного в URL, не проверяя предварительно это имя на существование, то удаленный пользователь, делая много запросов к разным несуществующим страницам, может легко устроить атаку на сервер, в которой размер кеша разрастется до неимоверных размеров. Проверка имени файла на существование требует своего sql-запроса. То же касается и других данных.
  • Эти приведенные выше три пункта - это три места, на которые я обратил внимание, когда создавал подсистему кеширования. Возможно, есть и другие места, на которые я не обратил внимания.

После инсталляции системы при попытке зайти на главную страницу появляется пустая страница.

Постоянный адрес статьи

Если посмотреть исходный текст этой пустой страницы, то можно увидеть РНР-код.

Проблема связана с тем, что РНР-код, записанный в файлах с расширением *.html не выполняется, а отдаётся в браузер как есть. Вот возможные пути решения проблемы:

  • Проверьте внимательно все пути, прописанные в файлах public_html/inc-all.php и options/addr.php. Пути в файле inc-all.php должны указывать на каталог с файлом addr.php.

    Одна из самых распространённых ошибок - каталоги располагают не так, как они были расположены в инсталляционном архиве и не меняют при этом пути. Прилагающаяся инструкция по инсталляции предполагает, что структура каталогов на диске в точности соответствует структуре каталогов в архиве.

  • Попробуйте в файле .htaccess, который находится в каталоге public_html поменять эту строчку (она самая первая в файле):
    AddHandler application/x-httpd-php .html
    на вот такую:
    AddType application/x-httpd-php .html

  • Если Вы используете локальную версию, то проверьте, разрешена ли у Вас обработка файлов .htaccess в настройках сервера.

    Для этого в файле httpd.conf нужно проверить настройку AllowOverride. Её значение для каталога, в котором установлена система должно быть AllowOverride All. Не забывайте о том, что эта настройка может быть разная для разных каталогов, и что проверить нужно не любое одно вхождение этой настройки в файл httpd.conf, а именно то, которое отвечает за каталог с системой popoff.donetsk.ua/light.

    После внесения изменений не забудьте перезапустить сервер.

  • Если проблема - на хостинге, то задайте этот вопрос Вашему хостеру. При этом обязательно укажите суть проблемы, что в файлах с расширением *.html РНР-код не выполняется, а выдаётся в браузер в исходном виде. Возможно, на Вашем хостинге нужны какие-то особые настройки - такое бывает довольно часто.

    Перед тем, как задавать вопрос хостеру - попробуйте внести описанное в первом пункте изменение в файл .htaccess - поменять AddHandler на AddType.

    Изучите FAQ Вашего хостера. Проблема, с которой Вы столкнулись - часто встречаемая и, возможно, на сайте Вашего хостера уже есть ответ на этот вопрос.

  • Если ничего не помогло, то всё, что я могу сделать - это попросить Вас разобраться с тем, почему у Вас возникает этот эффект и выложить в комментарии к этой странице описание сути проблемы и способа решения проблемы в Вашем конкретном случае.

Смотрите также

Постоянный адрес статьи

Многоязычность в движке для портала
Некоторые особенности устройства подсистемы поддержки многоязычности (вопрос в форуме)

Выбираем лучший инструмент: Объектно-ориентированное и процедурное программирование в PHP
http://phpclub.ru/detail/article/oop-vs-proc

Последняя модификация: 16.06.08 01:19

Не проходите мимо! Оставьте Ваш комментарий в форуме! >>>