VBsupport перешел с домена .ORG на родной .RU
Ура!
Пожалуйста, обновите свои закладки - VBsupport.ru
Блок РКН снят, форум доступен на всей территории России, включая новые терртории, без VPN
На форуме введена премодерация ВСЕХ новых пользователей
Почта с временных сервисов, типа mailinator.com, gawab.com и/или прочих, которые предоставляют временный почтовый ящик без регистрации и/или почтовый ящик для рассылки спама, отслеживается и блокируется, а так же заносится в спам-блок форума, аккаунты удаляются
Если вы хотите приобрести какой то скрипт/продукт/хак из каталогов перечисленных ниже: Каталог модулей/хаков
Ещё раз обращаем Ваше внимание: всё, что Вы скачиваете и устанавливаете на свой форум, Вы устанавливаете исключительно на свой страх и риск.
Сообщество vBSupport'а физически не в состоянии проверять все стили, хаки и нули, выкладываемые пользователями.
Помните: безопасность Вашего проекта - Ваша забота. Убедительная просьба: при обнаружении уязвимостей или сомнительных кодов обязательно отписывайтесь в теме хака/стиля
Спасибо за понимание
Сразу извиняюсь, конечно, если не в тот раздел, но куда ещё это тут поместить - не придумал.
По професии я программер. Но не веб разработчик. Моя специализация - базы данных и десктопный софт к ним. Занимаюсь этим лет пятнадцать минимум. И да, базы у нас в разы сложнее того, что есть в том же vBulletin. Сейчас вот так получилось, что ковыряюсь с PHP и vBulletin в том числе, но это все не по работе. PHP-шник же из меня начинающий и поэтому многое мне пока не понятно. И местами даже дико.
Ну, то есть я привык, что у меня база - это не просто данные, но и контроль целостности на внешних ключах, автоматические операции в триггерах и 90% логики завернутые в хранимые процедуры (приложение-клиент вообще прямого доступа к данным не имеет).
Что я вижу в PHP и в частности во всех форумных движках и cms, до которых дотянулись руки:
1. Тотальное неиспользование механизмов контроля ссылочной целостности (foreign key)
2. Тотальное неиспользование хранимых процедур и триггеров, весь SQL код зашит в скрипты
3. Странные неэффективные схемы хранения данных
4. странные методики работы с данными вообще
Вот, например, vBulletin хранит членство пользователя в группах в строчку, через запятую. Что получается? Например:
1. Никто не мешает записать туда код несуществующей группы.
2. Никто не мешает удалить из базы группу, в которой числятся пользователи
3. Вывод списка групп, в которых состоит пользователь без обработки в скрипте, насколько я понимаю, вообще не представляется возможным
Это правильно? Это так и надо?
Или вот.
Есть такая галерея - Dragonbyte Gallery. В какой-то момент я заметил, что там нифига не работает рейтинг изображений. Стал копать - выяснил, что перерасчет рейтинга, хотя и написан, но в реальности нигде не вызывается. Ну вот просто забыли вызвать функцию, выполняющую перерасчет. Дальше я смотрю, как этот рейтинг считается и вижу вот это:
PHP Code:
public static function calculate_weight_rate($imageid)
{
$rate_query = self::$vbulletin->db->query_read_slave("
SELECT
rating
FROM " . TABLE_PREFIX . "dbtech_gallery_rating
WHERE
imageid = " . intval($imageid)
);
while ($rate_data = self::$vbulletin->db->fetch_array($rate_query))
{
switch ($rate_data['rating'])
{
case 5:
$rating = $rating + 2;
break;
case 4:
$rating = $rating + 1;
break;
case 3:
$rating = $rating;
break;
case 2:
$rating = $rating - 1;
break;
case 1:
$rating = $rating - 2;
break;
}
}
return $rating;
}
Ну и потом уже, когда поправили это дело, добавлен был вот такой вызов:
PHP Code:
$vbulletin->db->query_write("
UPDATE " . TABLE_PREFIX . "dbtech_gallery_images
SET weight_rate = " . intval(DBTECH_GALLERY::calculate_weight_rate($vbulletin->GPC['imageid'])) . "
WHERE imageid = " . intval($vbulletin->GPC['imageid']) . "
");
Ну вот то есть тупо достали данные, посчитали, положили обратно. Весь этот подход с моей точки зрения выглядит, как полнейший говнокод. Почему? А потому, что ручной подсчет и запись результата обратно в базу может быть заменен на выполнение одного единственного запроса, который подсчитает и обновит данные без вытягивания их в скрипт. А если засунуть это в триггера, то все будет подсчитываться само и автоматически, без участия PHP вообще. И нет проблемы под названием "забыли вызвать пересчет". Ну вот то есть в принципе нет. Собственно, на триггерах оно у меня и было сделано до тех пор, пока не "починили" подсчет.
Собственно, к чему весь этот спич. Может, оно так и надо и я чего не понимаю? Может, кто объяснит?
1. Никто не мешает записать туда код несуществующей группы.
и ничего не случится =)
во первых, при добавлении/редактировании узера, движок отслеживает существование той или иной группы (ее ID) и удаляет из поля, если такового не обнаружится
Quote:
Originally Posted by WatcherOfTheSun
Никто не мешает удалить из базы группу, в которой числятся пользователи
если это удаляется из админки, стандартными средствами, то все пользователя группы, которая удаляется, будут перенесены в группу по умолчанию ID:2
Quote:
Originally Posted by WatcherOfTheSun
Есть такая галерея - Dragonbyte Gallery. В какой-то момент я заметил, что там нифига не работает рейтинг изображений
дбтех - та еще шаражка
а вот это
PHP Code:
case 3: $rating = $rating; break;
действительно похоже на говнокод
ну и да, с триггерами мало кто заморачивается
пхп - открытый для всех и каждого, этим и пользуются все кому не лень
многие "кодеры", просто копируют куски кода из одного скрипта в другой, даже не вникая в суть копируемого кода
Quote:
Originally Posted by WatcherOfTheSun
Собственно, на триггерах оно у меня и было сделано до тех пор, пока не "починили" подсчет
ну так все в ваших руках =)
сделайте мир лучше
@WatcherOfTheSun
Продвинутый
Join Date: Mar 2013
Posts: 63
Версия vB: 4.2.х
Reputation:
Опытный 27
Репутация в разделе: 0
0
Quote:
Originally Posted by kerk
если это удаляется из админски, стандартными средствами
Ну это-то понятно. Если бы все в мире происходило исключительно стандартными путями, проблем было бы существенно меньше. А так, всё это никак не защищает от средств нестандартных и банальных ошибок. Я не про данное конкретное место, а про подход вообще.
Quote:
Originally Posted by kerk
действительно похоже на говнокод
Да не, там все можно выкинуть нафиг - то же самое считается тупо запросом типа такого:
Code:
select sum(cast(rating as signed)-3) from dbtech_gallery_rating where imageid = ...
Quote:
Originally Posted by kerk
ну так все в ваших руках =)
сделайте мир лучше
Не-не-не, ответственным за мир я себя как-то не чуйствую.
Helenka
Лицензия на флуд!
Join Date: May 2013
Награды в конкурсах:
Posts: 1,073
Версия vB: 3.8.4
Пол:
Reputation:
Expert 1652
Репутация в разделе: 12
0
Quote:
Originally Posted by WatcherOfTheSun
Не-не-не, ответственным за мир я себя как-то не чуйствую.
Вот так всегда. Все только критиковать, а как улучшить, так не-не-не
@WatcherOfTheSun
Продвинутый
Join Date: Mar 2013
Posts: 63
Версия vB: 4.2.х
Reputation:
Опытный 27
Репутация в разделе: 0
0
Quote:
Originally Posted by Helenka
Вот так всегда. Все только критиковать, а как улучшить, так не-не-не
Quote:
...дай мне спокойствие принять то, чего я не могу изменить, дай мне мужество изменить то, что я могу изменить, и дай мне мудрость отличить одно от другого...
kerk
k0t
Join Date: May 2005
Location: localhost
Posts: 28,847
Версия vB: 3.8.x
Пол:
Reputation:
Гуру 20334
Репутация в разделе: 248
0
Quote:
Originally Posted by WatcherOfTheSun
то же самое считается тупо запросом типа такого:
а вы отпишите разрабам галеры и предложите этот вариант
посмотрим, что они ответят =)
@WatcherOfTheSun
Продвинутый
Join Date: Mar 2013
Posts: 63
Версия vB: 4.2.х
Reputation:
Опытный 27
Репутация в разделе: 0
0
Quote:
Originally Posted by kerk
а вы отпишите разрабам галеры и предложите этот вариант
посмотрим, что они ответят =)
Я когда багрепорт писал, в теме показал решение при помощи триггеров. Там, собственно, тот же запрос использован. Проигнорировано и оставлено так как я выше процитровал.
Sellrion
Kernel panic
Join Date: Aug 2007
Location: Екатеринбург
Posts: 2,536
Версия vB: 3.8.x
Пол:
Reputation:
Гуру 1921
Репутация в разделе: 39
2
Quote:
Originally Posted by WatcherOfTheSun
Может, оно так и надо и я чего не понимаю? Может, кто объяснит?
Пффф... ну попробую я.) Собственно, добро пожаловать в веб-программирование.))) Видимо базами данных вы занимались 15 лет, да вот базы данных в высоконагруженных системах вы видать пропустили мимо.) Ну и заодно экосистему виртуальных хостингов.) Есть там все. И поддержка ссылочной целостности и каскадное удаление и хранимые процедуры и триггеры. В известной степени это полноценная РСУБД. Вот только реалии таковы, что в большинстве случаев все эти ништяки отключают и запрещают по разным причинам: начиная с безопасности и заканчивая ограниченностью системных ресурсов. Ну а разработчикам продуктов только под это подстраиваться нужно. Именно поэтому все вышеуказанные вещи обычно реализуются вне РСУБД - при помощи скриптов. Поэтому, к примеру, каскадное удаление данных реализуется не при помощи запроса или автоматически самой РСУБД, а "ручками", отыскивая запросами все связи и удаляя их. Это первое.
Второе. Вы сами очень точно подметили: это форум, а не какая-то там супер сложная база данных. Поэтому в данном конкретном случае, при существующей нагрузке на сервер баз данных и на тот же http-сервер, где крутятся скрипты, более производительным решением как раз является именно сделать все "ручками". Я вам приведу один очень хрестоматийный пример: взятие из таблицы случайной записи. В MySQL это реализуется по идее так:
PHP Code:
SELECT * FROM table WHERE condition = value ORDER BY RAND()
Вот оно ваше желанное "все_автоматически_одним запросом". Но за такое вам оторвут руки и вставят их обратной стороной в неудобоговоримое место, а потом уволят без выходного пособия. А все потому, что для того, чтобы MySQL выбрать случайную запись, нужно построить несколько временных таблиц, удовлетворяющих всем условиям запроса, а потом произвести сортировку по случайному ключу. Представляете, что будет с сервером БД если в базе будет миллиона эдак два записей и этот запрос произведут одновременно тысяч эдак сто человек?) Вы этого сервера больше не увидите.) Поэтому используется более длинный, но более экономный способ: одним запросом берутся из базы все ключи записей, удовлетворяющие условиям, помещаются в массив, генерится случайное число и далее делается запрос на взятие одной записи с ID (к примеру), соответствующим тому, что лежит в массиве со случайным индексом. Да, этот алгоритм тоже неэффективен по памяти. Но далеко не настолько, насколько первый вариант.
Так что не забывайте, что иногда узкоспециализированное решение, может быть в разы эффективнее, если оно применяется строго в рамках решения конкретных задач. У форума задачи не такие уж и сложные. Так что... ))
@WatcherOfTheSun
Продвинутый
Join Date: Mar 2013
Posts: 63
Версия vB: 4.2.х
Reputation:
Опытный 27
Репутация в разделе: 0
0
Quote:
Originally Posted by Sellrion
ну попробую я.)
Благодарю. Вот что-то подобное и хотелось услышать. Я и подозревал, что многое вызвано не только недомыслием и криворукостью. Но и чем-то вполне даже обратным.
Quote:
Originally Posted by Sellrion
Есть там все. И поддержка ссылочной целостности и каскадное удаление и хранимые процедуры и триггеры.
Собственно, я не подвергал сомнению наличие. Вопрос в том, что и насколько применяется и применимо в конкретных условиях.
Quote:
Originally Posted by Sellrion
А все потому, что для того, чтобы MySQL выбрать случайную запись, нужно построить несколько временных таблиц, удовлетворяющих всем условиям запроса, а потом произвести сортировку по случайному ключу.
Скажем так, за использование вещей, работающих именно таким образом отрывать голову будут не только веб-разработчикам.