17:43

Правильного ответа нет. Любой выбор приводит к жертвам, любое решение требует платы. | Лишь навык имеет значение.
Здравствуйте.

Прошу помочь, если кто-нибудь вообще возьмётся разбираться в моём дурдоме)

читать дальше
Не знаю что я там изменил, но вот глючить стало.
Если кто может - посмотрите, может вы увидите в чём проблема.

К сожалению ссылку на работающий проект дать не могу, ибо он закрытый и меня за это покарают маленько ^^"

@темы: Программирование

Комментарии
07.06.2012 в 21:37

Sanctus Satanas
Ну я лично не заметил явного косяка в коде. Вероятно, он где-то в другом месте.
Поэтому просто несколько комментов:

Проще говоря, поле в ячейке на третьей строке в седьмом столбце имеет id="p37"
А каждая строка это отдельный юзер? Просто, например, 11-я строка, 1-й столбец и 1-я строка, 11-й столбец — будут иметь один id. Впрочем, если столбцы никогда не будут иметь номер больше 9, то не важно.

for (var i = "0"; i < ku; i++)
Зачем инициализировано строкой 0, а не числом 0?

$ku = mysql_escape_string($ku);
mysql_escape_string() не будет работать с многобайтовыми кодировками, нужно использовать mysql_real_escape_string(). В свою очередь, для последней требуется установленное соединение с базой, т.к. невозможно правильно экранировать данные, если неизвестна кодировка соединения.
07.06.2012 в 22:23

Правильного ответа нет. Любой выбор приводит к жертвам, любое решение требует платы. | Лишь навык имеет значение.
--==SS==--, Просто, например, 11-я строка, 1-й столбец и 1-я строка, 11-й столбец

Про это кстати не подумал. Но у меня 9 столбцов, так что я на это не нарвался. А вообще - спасибо, я где-то в августе буду весь проект пелелопачивать, как раз и подправлю индексацию)))


Зачем инициализировано строкой 0, а не числом 0?

Оу. Видимо я был не в себе.))) Плавающий дедлайн - страшная штука)))


mysql_escape_string() не будет работать с многобайтовыми кодировками, нужно использовать mysql_real_escape_string().

Не, тут как раз всё правильно. Я специально тестил. Не помню в чём там дело было, но как раз-таки _real_ мне на выходе давало не то что нужно. А кодировка - utf8 у меня. Такое же соединение и кодировка таблиц.
Возможно дело в том, что _real_ надо после соединения делать, а у меня все данные и запросы до соединения подготавливаются. Ибо после соединения там и так ветвлений хватает, и запихивать туда ещё "дерево" формирвания запроса как-то напряжно. Хотя может в будущем так и сделаю, всё равно буду проект переделывать.


Ну я лично не заметил явного косяка в коде. Вероятно, он где-то в другом месте.

Да вот непонятка. Всё работало уже полтора месяца как. А тут мне сегодня падает письмо с описанием. Пошёл, посмотрел - действительно. Хотя, говорю же, проект активно используется уже больше месяца. Это что-то недавнее.

Очень надеюсь, что это из-за ошибки в клиентской части. Сейчас прогоняю каждую функцию через www.javascriptlint.com. Кое-что уже подправил. Дойду до конца скрипта, буду смотреть как оно.

А то получается "отпусти меня чудо-трава". Вроде уже всё оттестил, запустил, народ пользуется, все частливы. И тут вылезает такая вот хрень. Причём ВНЕЗАПНО. Ладно, потом отпишусь, если найду в чём дело было.
07.06.2012 в 23:33

Правильного ответа нет. Любой выбор приводит к жертвам, любое решение требует платы. | Лишь навык имеет значение.
Вот странно. Сделал вывод формируемого запроса. - Сколько пользователей было отправлено, столько запросов и формируется. Но в базу пишется больше. Странно.
08.06.2012 в 01:20

Sanctus Satanas
Надо поискать по всем файлам проекта все INSERT IGNORE'ы в эту таблицу и перед каждым поставить вывод в лог: имя файла, время и т.п. Чудес-то не бывает.
Роль INSERT IGNORE'ов так же могут выполнять UPDATE ... ON DUPLICATE KEY INSERT IGNORE. Ну и в браузере (в отладчике) последить за запросами к серверу. Обычно там есть опция «не очищать список запросов при переходе на другую страницу».

Не, тут как раз всё правильно. Я специально тестил. Не помню в чём там дело было, но как раз-таки _real_ мне на выходе давало не то что нужно. А кодировка - utf8 у меня. Такое же соединение и кодировка таблиц.
Возможно дело в том, что _real_ надо после соединения делать, а у меня все данные и запросы до соединения подготавливаются. Ибо после соединения там и так ветвлений хватает, и запихивать туда ещё "дерево" формирвания запроса как-то напряжно. Хотя может в будущем так и сделаю, всё равно буду проект переделывать.

Да, именно так. Потому что правильно проэкранировать возможно только зная кодировку соединения с базой. А её можно узнать только с базой соединившись.
Но вообще, конечно, всё не так страшно. ) В случае однобайтовых кодировок и UTF-8 обмануть обычный mysql_escape_string() не получится, т.к. в UTF-8 обратная косая черта не может быть частью другого символа. Впрочем, можно вспомнить классический случай с Simple Machines Forum, где существовала ещё одна уязвимость, позволявшая назначить соединению с базой произвольную кодировку.

А по поводу того, что можно переделать…
url = "z.php?f=2&login=" + encodeURIComponent(login) + "&ku=" + encodeURIComponent(ku) + "&zay=" + encodeURIComponent(t2) + "&num=" + encodeURIComponent(c1) + "&fio=" + encodeURIComponent(c2) + "&nick=" + encodeURIComponent(c3) + "&pers=" + encodeURIComponent(c4) + "&email=" + encodeURIComponent(c5) + "&tel=" + encodeURIComponent(c6) + "&contact=" + encodeURIComponent(c7) + "&age=" + encodeURIComponent(c8) + "&city=" + encodeURIComponent(c9);
getAjax (url, nof);

В таких местах просто напрашивается функция. А учитывая, что это AJAX-запрос, было бы логично, чтобы вызов был, например, таким:

getAjax(
'z.php',
{
f: 2,
login: login,
ku: ku,
zay: t2,
num: c1,
...
},
nof
);


Оу. Видимо я был не в себе.))) Плавающий дедлайн - страшная штука)))
Да бывает. ) Просто это потенциальная ошибка, т.к. в JS «+» это ещё и конкатенация.
Поэтому i++ — всё равно будет инкремент на 1, а вот i += 1 — получатся строки «01», «011» и т.д.
08.06.2012 в 01:39

Правильного ответа нет. Любой выбор приводит к жертвам, любое решение требует платы. | Лишь навык имеет значение.
А её можно узнать только с базой соединившись.

Или если самому кодировку соединения указывать. Не?


Надо поискать по всем файлам проекта все INSERT IGNORE'ы в эту таблицу и перед каждым поставить вывод в лог: имя файла, время и т.п. Чудес-то не бывает.
Роль INSERT IGNORE'ов так же могут выполнять UPDATE ... ON DUPLICATE KEY INSERT IGNORE. Ну и в браузере (в отладчике) последить за запросами к серверу. Обычно там есть опция «не очищать список запросов при переходе на другую страницу».


Пока решил принудительной проверкой на наличие в базе пользователя с заданным номером. То бишь, если пользователь с таким номером уже есть, то итерация пропускается и начинается новая.
Вообще, надо какой-нибудь отладчик, который будет и с js и с php работать, наверное.


А по поводу того, что можно переделать…
url = "z.php?f=2&login=" + encodeURIComponent(login) + "&ku=" + encodeURIComponent(ku) + "&zay=" + encodeURIComponent(t2) + "&num=" + encodeURIComponent(c1) + "&fio=" + encodeURIComponent(c2) + "&nick=" + encodeURIComponent(c3) + "&pers=" + encodeURIComponent(c4) + "&email=" + encodeURIComponent(c5) + "&tel=" + encodeURIComponent(c6) + "&contact=" + encodeURIComponent(c7) + "&age=" + encodeURIComponent(c8) + "&city=" + encodeURIComponent(c9);
getAjax (url, nof);
В таких местах просто напрашивается функция. А учитывая, что это AJAX-запрос, было бы логично, чтобы вызов был, например, таким:

getAjax(
'z.php',
{
f: 2,
login: login,
ku: ku,
zay: t2,
num: c1,
...
},
nof
);



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

Пока в плане есть, как минимум переписание всё на POST-запросы аяксовские. А то у меня почти везде аякс GET-ом, что не есть хорошо, т.к. у пользователей ручки шаловливые.)) Хотя некоторые вещи надо будет в гете оставить. Например номер ресурса. Ибо очень удобно, когда с одним ресурсом закончил, вбить в адресную строку номер следующего нужного и сразу на него попасть. А не возвращаться каждый раз к списку и искать там. Даже с фильтрами это порой долго.
Вообще, многое надо будет переделать - от сss и обработки форм, до работы с базой. Но это не раньше чем июль пройдёт. Сейчас пик активности и без надобности лучше ничего не делать. Ибо главная заповедь - "работает - не трожь"))) А августе будет затишье и можно будет системку переписать по уму, без спешки.

Спасибо за помощь.
08.06.2012 в 02:05

Sanctus Satanas
К тому же тут ничего особо сложного нет, чтобы упрощать за счёт функции.
Так дело не в том, что сложное, дело в том, что это длинная копипастная портянка. Малейшая опечатка — и придётся внимательно просматривать каждый символ, а их много и большая часть — повторяются. Ну и потом — это просто как пример. )

если пользователь с таким номером уже есть
А эти айдишники уникальны? Просто может быть на них стоит уникальный индекс повесить в базе. Особенно, если по этому полю потом будут запросы.

Или если самому кодировку соединения указывать. Не?
Где? В mysql_escape_string() только один аргумент — сама строка.
08.06.2012 в 02:26

Правильного ответа нет. Любой выбор приводит к жертвам, любое решение требует платы. | Лишь навык имеет значение.
--==SS==--, Так дело не в том, что сложное, дело в том, что это длинная копипастная портянка. Малейшая опечатка — и придётся внимательно просматривать каждый символ, а их много и большая часть — повторяются. Ну и потом — это просто как пример. )

Ну, в принципе да. Верно всё.


А эти айдишники уникальны? Просто может быть на них стоит уникальный индекс повесить в базе. Особенно, если по этому полю потом будут запросы.

Ну, таблица строится так:
1) id - уникален, первичный ключ с автоинкрементом.
2) zay - к какому ресурсу принадлежит пользователь.
3) num - номер пользователя.

Ну и дальше всякая инфа о пользователе - контакты, фио и т.д. В пределах одного ресурса номера не могут повторяться (проблема как раз и была, что один пользователь дублировался несколько раз).
Номера пользователей никто поменять не может. Они соответствуют строкам. То бишь, пользователь в пятой строке имеет num=4 (с нуля ж считается). А при выводе в таблицу, в инпуты/поля, просто делается запрос к таблице, где запрашиваются пользователи с zay=номеру ресурса. Ну и сортируются по номерам пользователей, чтобы были выведены в том же порядке, в каком их заносили в таблицу.


Где? В mysql_escape_string() только один аргумент — сама строка.

Ну... допустим так:

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

mysql_query("set character_set_client='cp1251'");
mysql_query("set character_set_results='cp1251'");
mysql_query("set collation_connection='cp1251_general_ci'");

relaxart.ru/archives/340"

Я про то, что кодировку соединения можно указать после соединения. Тогда данные можно преобразовывать простым mysql_escape_string. Хотя в моём случае нет необходимости устанавливать кодировку соединения, ибо всё под utf8 настроено. И таблицы, и соединение, и скрипты, и сами странички))) Я просто решил что правильнее и проще будет использовать одну кодировку везде)
08.06.2012 в 03:39

Sanctus Satanas
2) zay - к какому ресурсу принадлежит пользователь.
3) num - номер пользователя.

Можно индекс повесить на два поля: alter table `table` add unique index(`zay`, `num`). В таком случае база гарантирует, что связка ресурс—пользователь будет всегда уникальна (при попытке вставки ещё одной записи — выдаст ошибку). Заодно это может ускорить выборку по ресурсу и сортировку по пользователям в пределах одного ресурса.
08.06.2012 в 03:43

Правильного ответа нет. Любой выбор приводит к жертвам, любое решение требует платы. | Лишь навык имеет значение.
--==SS==--, Спасибо. А вот выдавать ошибку мне не надо, ибо если ответ функции отличается от заданного, то он выводится просто алертом (чтобы мне могли сказать, какая ошибка произошла). А так получится, что скрипт чего-то подглючивает и пользователю ошибки валятся. Пользователь в панике. Нехорошо)
08.06.2012 в 11:53

Sanctus Satanas
Так речь же про MySQL-ошибку, т.е. mysql_query() просто вернёт false, а описание будет доступно через mysql_error(). Можно не выдавать такую ошибку пользователю, а только записать в лог. Как раз будет понятно, где в точности и в какой момент происходит попытка записать в базу хрень.
Если принципиально важно, чтобы остальные ошибки при запросе всё же выводили пользователю предупреждение, то можно пойти другим путём: делать insert ignore, а затем выполнить mysql_affected_rows(). Если вставлено 0 записей, но запрос выполнился успешно (без ошибок), значит была коллизия с уже существующим значением.