Задать вопрос
  • Как исправить проблему с созданием регистрации пользователей?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Это всё просто ужасно. Начиная прямо с первой строчки, class Register extends Database
    Делать отдельный класс для регистрации глупо. Если уж делать класс, то для манипуляции юзером в целом, а не одной только регистрации. Плюс, регистрация пользователя - это не база данных. И не должна наследовать классу Database.
    По сути, вы хотите натянуть ООП на обычное процедурное программирование. Не надо этого делать, получится самолёт из соломы. Сделайте простую функцию.

    Но это ещё цветочки. Остальных проблем тут выше крыши:
    1. Никогда не используйте сокращённый синтаксис INSERT. Всегда надо явно перечислять поля. Это, скорее всего, и является причиной ошибки. Но даже если нет, то проблемы всё равно вылезут в будущем
    2. Собственно сообщение об ошибке нам и надо получить от базы данных, чтобы понять в чем проблема. для этого к коду соединения с БД надо добавить строчку
      mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
      и после этого смотреть сообщение об ошибке
    3. Самое главное - SQL инъекция. Какой смысл делать регистрацию вообще, если любой дурак узнает пароли всех остальных пользователей или сможет авторизоваться вообще без пароля? Запросы надо выполнять только через подготовленные выражения
    4. И по поводу паролей. Пароли надо хранить в фаршированном виде, обработанными функцией password_hash()
    Ответ написан
    Комментировать
  • Будет ли использоваться индекс в запросе вида WHERE `field1` LIKE '_aa_a_'?

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

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

    Полнотекстовый индекс также не является чем-то особенным в этом плане. Он устроен по совершенно тупому принципу: грубо говоря, БД берёт текст из колонки, и разбивает его на слова. И строит по этим словам снова точно такой же отсортированный список, с указанием, в каких строках это слово используется. То есть когда мы делаем запрос с match, то mysql находит искомое слово в индексе, и возвращает из него все строки.

    И точно так же полнотекстовый индекс не работает, если поставить звёздочку спереди. Мануал так и говорит:
    Words match if they begin with the word preceding the * operator

    То есть звездочка работает только если поставить её в конце слова.
    match against ('класс*') найдёт слово "классный", а '*accный' его уже не найдёт.
    То есть БД тебе сразу говорит, что для такого поиска полнотекстовый индекс будет бесполезен.
    Ответ написан
    Комментировать
  • Где я могу получить код-ревью?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ответ написан
    Комментировать
  • Насколько допустимо с точки зрения стилистики вызывать Exception в конструкции if/else?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вопрос не очень понятен, особенно в части "обрабатывать" можно как через try/catch".

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

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

    Я бы только инвертировал условие, чтобы во-первых, сделать логику более стройной (проверили - вывалились), а во-вторых, чтобы избавиться от else и убрать лишний отступ.
    if not (isinstance(data_set, list) or isinstance(data_set, tuple)): 
        raise TypeError('argument must be list or tuple')
    return sum(data_set) / len(data_set)


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

    То есть в реальном коде я бы убрал проверку из функции вообще, а проверял данные при их получении (и выводил ошибку).
    А на случай, если вдруг функция всё равно будет вызвана с неверным типом аргумента, есть системное исключение, 'type' object is not iterable
    Ответ написан
    Комментировать
  • Как в PHP быстрее и с меньшей нагрузкой на сервер вывести случайное значение сроки с 500000 шт?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Способ с инклюде - это ад кромешный. Память процесса РНР- она как бы не бесплатная. И даже если в моменте ничего не упадёт, то может потом не хватить на какую-то другую операцию. Но главное - это просто варварство, каждый раз тягать в память пол-ляма строк ради того чтобы вывести одну.
    Способ с файлами в принципе эффективен, но многие ос начинают тупить при большом количестве файлов в каталоге, придется разбивать по 500 подкаталогам. В целом гемор.
    spoiler
    И непонятно, зачем так сложно писать
    echo file_get_contents("/str/" . mt_rand (1,500000) . ".txt");

    Самый простой способ - это действительно сделать таблицу в БД, где будет два поля, число по возрастанию (первичный индекс) и собственно значение строки.
    и выбирать по первому полю через то же mt_rand (1,500000)

    Сразу отвечу на вопрос про разницу с гениальным решением через инклюде: индекс в БД будет во-первых занимать память только под первую колонку, а во-вторых, этот индекс будет храниться ровно в одном экземпляре. А не занимать память в каждом процессе РНР.
    Ответ написан
    4 комментария
  • Как подсчитать количество элементов в списке с помощью nunique()?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    подсчитать количество элементов в списке без len, и вывести через print уведомление.

    Этот вопрос звучит настолько по-дурацки, что его вполне можно понять буквально
    count = 0
    for tmp in friends:
        count += 1
    Ответ написан
    Комментировать
  • Как узнать баланс юзера?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    5 июня вы уже задавали этот вопрос.
    Если за три месяца вы так и не освоили базовые приёмы работы с БД в РНР, то может ну его совсем?
    Тем более что при таких-то дырищах всё равно это будет не баланс, а решето.
    Ответ написан
    Комментировать
  • Как исправить ошибку Implicit conversion from float (int) to int loses precision?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Этот код какой-то эстет писал.
    Для получения количества полных дней вместо битовых выкрутасов надо просто использовать floor()
    Хотя в данном случае надо использовать ceil, ну или round. Потому что эти 5 сотых дня происходят явно от прехода на летнее время. И с конверсией в int теряется 1 день.
    Ответ написан
    Комментировать
  • Как по очереди проверять и по очереди убирать лишнее?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    А зачем if-ы вкладывать друг в друга?
    Как $tegi[1] может быть одновременно равен $id['TIP_TOVARA'] и $id['AFFILIATION']?
    Ответ написан
  • Почему не работает код?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Потому что результат замены надо записывать. replace() только возвращает результат, а не изменяет исходную строку.
    В целом алгоритм конечно кривой. Чтобы заменить буквы на цифры, не нужно перебирать строку по одной букве. А если уж и делать перебором, как у вас, то тогда собирать новую строку из х.
    Но по уму надо просто сделать в цикле замену по словарю

    Если уж соревноваться в решениях, хотя автор вроде бы не просил, то беглое гугление даёт
    number.translate(''.maketrans("ABCDEFGHIJKLMNOPQRSTUVWXYZ","22233344455566677778889999"))
    Ответ написан
    Комментировать
  • Как быстро найти совпадение в базах?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    либо цикл for в котором перебираются название баз данных и идет поиска по таблице
    либо навести один раз порядок в этом бардаке
    например, если это multi-tenant приложение, то запрашивать не только логин и пароль, но и приложение, например в виде субдомена.
    при текущей структуре ничто не мешает появлению одного и того же пользователя в разных базах
    Ответ написан
  • Как отсортировать кортеж по заданному интервалу времени?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Разумеется, все фильтры и сортировки должны быть только в SQL запросе.
    Чтобы "из сторонней бд" "вытягивались" сразу только нужные данные, уже отсортированные в нужном порядке
    Ответ написан
  • Как кастомизировать ексепшены в общем методе?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Первый вариант - это однозначно глупость. Какое-то совсем уже натягивание процедурного подхода на ООП.
    Второй какой-то невнятный, про него ничего нельзя сказать толком.

    В общем случае, как правильно написал sl0 в комментарии, кидать надо ОДИН тип исключения, но с разными сообщениями.

    В данном конкретном случае, поскольку речь идёт о валидации, то никакое исключение в принципе кидаться не должно. Исключение кидается в случае, если функция не может выполнить свою работу. Но для функции checkParam() невалидный параметр НЕ ЯВЛЯЕТСЯ исключительной ситуацией. Потому что роль этой функции - как раз и определить валидность переданного параметра. В случае неверных данных функция должна записать сообщение об ошибке во внутренний массив ошибок класса-валидатора и вернуть false.
    spoiler

    Исключение в случае неверных параметров может кидать например функция сохранения в БД. Потому что её задача - сохранить переданные данные, а не валидировать их. И в случае, если функция не может сохранить данные - она должна кинуть исключение, в том числе из-за невалидности данных.
    Ответ написан
    9 комментариев
  • Почему else — invalid syntax?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ну неужели самому не видно что предыдущая строчка без отступа?
    Ответ написан
    1 комментарий
  • Как массив из обьектов сделать уникальным?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Если отвечать на вопрос, который в заголовке, и который не имеет никакого отношения к озвученной задаче: сначала надо определиться, как отличать объекты друг от друга.

    Если надо посчитать всего лишь классы, то методика всегда одинаковая: исходный массив перебирается в цикле, и создаётся новый массив, где ключом является значение, которое надо подсчитать, а значением - его количество.
    Ответ написан
  • Создать таблицу базы данных postgresql из json файла?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Я бы исходный джейсон развернул в словарь, где ключом является id
    И дальше шёл просто по этому словарю, добавляя записи в БД. Проверяя, есть ли уже парент.
    если нет - то создавать по цепочке, пока не появится
    Ответ написан
    Комментировать
  • Как убрать элементы из многомерного массива?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Пройти в цикле по обоим массивам и проверять, есть ли индекс в первом. Если нету - удалять элемент с таким индексом
    Важно: удалять надо по полному адресу, $array['DESCRIPTION'][$key]
    Ответ написан
  • Как настроить кодировку?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вопрос сложный, это издержки разработки под виндоуз.
    Весь мир давно уже работает с кодировкой utf-8, а эта допотопная система всё ещё выдаёт свои ошибки в 1251.

    Я бы не стал делать никаких специальных телодвижений по перекодированию ошибок виндоус. На боевом сервере эта проблема будет неактуальной, а пару раз при разработке можно и потерпеть.
    Как вариант - сделать запись ошибок в лог, и смотреть их каким-нибудь Блокнотом - он покажет нормально.
    Ещё как вариант - не использовать опенсервер или чем вы там пользуетесь, а использовать встроенный сервер РНР - он перекодирует выводимые на экран ошибки в utf-8.
    Ответ написан
    1 комментарий
  • Как сделать повторный запуск программы через input, ответом "да или нет"?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Фарш невозможно провернуть назад.
    Блок else вызывается ПОСЛЕ того, как блок while ЗАКОНЧИЛ работу.

    В данном случае, если хотим вернуться, то очевидно что всю логику надо писать внутрь while, а else тут просто не нужен. А всю начинку оттуда добавить в ветку, где чел угадал номер.
    Ответ написан
  • Как лучше поступить с таблицей бд?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Можно удалять по первичному ключу, можно помечать как удалённые. Сам вопрос холиварный, единого ответа на него нет. Исходите из требований своей бизнес-логики.
    К "выгоде" этот вопрос отношения не имеет.
    Ответ написан
    3 комментария