• Fatal error: Allowed memory size. Как сделать запрос SQL чтобы не получать ошибку?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Читаем https://www.php.net/manual/ru/mysqlinfo.concepts.b...
    и делаем свой запрос небуферизованным.
    Ну и разумеется читаем все 300 офигиллиардов строк не сразу в массив, а обрабатываем по одной.
    Ответ написан
    6 комментариев
  • Почему не видит файл?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Как правильно заметили в комментарии выше, какой-то из файлов не является изображением.
    Соответственно, такие файлы надо пропускать
    imgs = os.listdir("images")
    for file in imgs:
        img = cv.imread(f"images\{file}")
        if img is not None:
            copy = img.copy()


    Хотя конечно заголовок вопроса почему-то не имеет никакого отношения к изображениям, и непонятно, что в итоге нужно получить.
    Ответ написан
  • Как подключить одну базу к разным хостингам?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Разумеется, API.
    Сейчас даже в рамках одного "хостинга" многие проекты переходят на микросервисную архитектуру, ходя в лежащую рядом БД не напрямую, а обращаясь по НТТР к сервису, который уже и лезет в БД.

    Тем более что тут нужна не вся БД, а всего-то одна таблица. То есть код пишется за полчаса.
    На клиенте file_get_contents, на сервере такой же код, что и при обычной авторизации, но возвращает не Location а true.
    Ответ написан
    Комментировать
  • Как правильно распределить хранение комментариев?

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

    Так же при проектировании БД следует опираться на требования архитектуры, а не на влажные эротические мечты про "сумасшедшие масштабы". Если когда-нибудь проект достигнет сумасшедших масштабов, то к этому моменту вся архитектура будет переделана не один раз. И проблема комментариев будет решаться в зависимости от реальных проблем с которыми столкнётся проект, а не в соответствии с фантазиями, которые были у кого-то на начальном этапе.
    Ответ написан
    Комментировать
  • Как работать с сырыми результатами SELECT MySQL CLI в PHP CLI?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вопрос, конечно, ад, из серии "помогите достать занозу гвоздодёром" но в целом мне приходилось такое делать. Ключик -X и simplexml

    Ну и всякие мелочи, типа -N чтобы получить сразу значение, если запрос возвращает одно поле одной строки, group_concat() если надо получить значения через запятую, и прочее
    Ответ написан
    1 комментарий
  • Почему не записываются данные в бд SQLITE?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    После запросов, выполняющих изменения в БД, надо вызывать
    self.connection.commit()

    И имена колонок и таблиц нельзя брать в одинарные кавычки. Потому что в одинарных кавычках пишутся строки.
    И если даже иногда sqlite и смотрит сквозь пальцы на такую ошибку (когда она может понять по контексту, что имеется в виду), это не значит, что так будет везти всегда.
    Строка 'money' никогда не будет равна числу.
    Ответ написан
    8 комментариев
  • Как обновлять данные каждые 24 часа в MySQL?

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

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    У вас задача на сложение переменных, которые являются элементами разных словарей.
    А не на скоростное гугление по запросу "как сложить элементы в одном словаре".
    Чтобы сложить три переменные, не нужно создавать новый словарь. Надо просто сложить три переменные и вывести результат.

    Это всё очень плохо.
    Программы, которые мы пишем, должны выдавать правильный результат при любых вводных.
    А ваша будет всегда будет выдавать 514, либо её надо будет каждый раз переписывать под новые данные.
    Потому что она считает не то что было задано, а какой-то левый массив, который не имеет никакой связи с исходными данными.
    Ответ написан
    Комментировать
  • Парсинг JSON в Python. Как брать конкретные данные?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Получить "конкретный ключ" - это "парсить все данные" до тех пор, пока не найден искомый.
    То есть банально два оператора, for и if. Только не говорите, что вы даже их не знаете.
    for item in json:
        if item['Ccy'] == 'EUR':
            break
    print(item)

    но лучше сразу перегнать список в словарь,
    rates = {}
    for item in json:
        rates[item['Ccy']] = item

    и дальше просто обращаться по индексу
    Ответ написан
    1 комментарий
  • Как создать локальную базу данных?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    На mysql не создают такой файл.
    Mysql - это отдельная программа, которая хранит данные в своих собственных файлах.
    "Создавать" её не надо. На хостинге она уже есть, дома она обычно тоже уже есть, в составе какого-нибудь набора - XAMPP, MAMP и пр.
    Если никаких наборов нет, то скачать и установить Mysql с офсайта.

    После этого вся работа с БД будет производиться через SQL.
    Лучше это делать через нормальный клиент, типа PHPStorm, Workbench и так далее. В крайнем случае - phpmyadmin, но это конечно очень уродливая программа.
    Настроить программу на соединение с сервером БД и выполнять в нем команды SQL.
    Например, создать database - это типа такой каталог, в котором лежат таблицы - CREATE DATABASE mydb;
    И вот это mydb потом указывать в параметрах подключения PDO.
    Ответ написан
    Комментировать
  • Дают ли выигрыш ссылки на элементы массива и на поля объектов в PHP?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    С точки зрения памяти не даёт, потому что в РНР и так очень оптимальное управление памятью.
    В частности, при присвоении значений переменным применяется принцип copy-on-write. Объекты же и так всегда копируются по ссылке.

    С точки зрения "вычислять адрес промежуточного объекта" - я никогда не слышал о таких проблемах. Судя по всему, это явно не является узким местом для динамически интерпретируемого языка.
    В любом случае, учитывая copy-on-write, исходно это снова будет опять ссылка.

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

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    просто в цикле продвигаться по уровням словаря не выйдет!

    На самом деле выйдет, поскольку в Питоне новая переменная является ссылкой на старую.
    Перебираем все ключи кроме последнего и потом присваиваем ему новое значение
    def changeDictValueByPath(my_dict, path, value):
        tmp_dict = my_dict
        for k in path[:-1]:
            tmp_dict = tmp_dict[k]
        tmp_dict[path[-1]] = value
    
    indices = "first_sec_x"
    source = {"first": {"sec": {"x": 1}}}
    changeDictValueByPath(source, indices.split("_"), 2)
    print(source);
    Ответ написан
  • Почему выдаёт ошибку? Подключился через MAMP PRO к локальному хосту и попытался реализовать форму регистрации, но выдаёт ошибку, почему?

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

    Чтобы узнать, почему РНР код не работает, надо прочитать сообщение об ошибке РНР. В данном случае мы его не видим, а видим только сообщение веб-сервера о том, что РНР завершился с ошибкой.
    Чтобы увидеть ошибку РНР, надо сделать две вещи:
    1. Убедиться, что РНР генерирует сообщения об ошибках. Для этого во-первых, всегда должен стоять максимальный уровень генерации ошибок, error_reporting(E_ALL);, и во-вторых, программист не должен сам себе стрелять в ногу, насильно подавляя сообщения об ошибках. И никогда не использовать оператор подавления ошибок, @.
    2. На время разработки поставить режим вывода ошибок на экран, ini_set('display_errors', 1);. На боевом сервере, соответственно, этот режим должен быть выключен, а логирование наоборот - включено.

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

    Отдельно отмечу, что в таком виде регистрацию делать бессмысленно, тут сплошная SQL инъекция, то есть кто угодно сможет узнать чужой пароль, залогиниться под чужим именем или вообще зайти без пароля. Все SQL запросы, в которых участвуют переменные, в обязательном порядке должны выполняться через подготовленные выражения, с заменой переменных на знаки подстановки.
    Кроме того, пароль в обязательном порядке должен стойко хэшироваться, функцией password_hash()
    Ответ написан
    Комментировать
  • Как сделать рандом без повторений из PhpExcel?

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

    Исходя из здравого смысла, в данном случае (когда из потенциально большого массива значений надо выбрать несколько случайных) чтобы избежать повторений, надо запоминать все уже использованные значения. Для этого подойдёт массив.
    А для проверки идеально подойдет цикл do while, это редкий случай его использования. просто генерируем новые ключи до тех пор, пока не найдётся ещё не использованный.
    do {
        $key = rand(2,$count);
    } while (array_key_exists($key,$exists));
    $exists[$key] = true;


    Важно не забыть определить пустой массив $exists перед началом цикла.

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

    Если же количество требуемых случайных значений сравнимо с количеством всех данных, то удобнее будет сначала сгенерировать массив всех ключей и перемешать его
    $keys = range(2, $count);
    shuffle($keys);
    for ($a=0; $a < 10; $a++) {
        $key = $keys[$i];
    Ответ написан
    7 комментариев
  • Почему SQL запрос возвращает список?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    > Почему SQL запрос возвращает список?

    Потому что функция execute_read_query написана так, чтобы возвращать список.

    > Как быть?

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

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Тут вопрос не столько в сокращении сколько в осмысленности.

    И ответ зависит от двух вводных, которые мы не знаем:
    1. по какой причине элемент 'test' может отсутствовать
    2. какие ещё значения могут быть у $arr['test']

    Если совсем всё равно на всё и пишем говнокод-стайл лишь бы покороче, то, как правильно написано в соседнем ответе - empty().

    Если элемент обязательно должен присутствовать, то либо убираем проверку на isset совсем, либо - если это интерактивное приложение - выносим отдельно, и при отсутствии элемента сообщаем об ошибке. Пусть даже и тупо 400 кодом.

    Если у $arr['test'] не могут быть другие значения, кроме true, то тоже проверить, и выбросить ошибку, если значение какое-то другое.
    Ответ написан
    Комментировать
  • Что именно делает этот код?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вся магия происходит здесь
    Обычный магический метод __call(), который вызывается, когда происходит обращение к несуществующему методу.

    По факту это такой магический геттер на стероидах.
    Отрезает от имени метода первые три буквы и ищет свойство с получившимся именем.
    Свойства добавляются в класс в конструкторе через массив.

    Если свойство не найдено, ищет в массиве имя класса, объект которого надо создать и вернуть.
    Для этого зачем-то меняет регистр с camelCase на snake_case и ищет элемент массива с таким именем по вышеприведённой карте классов. То есть getForwardFrom превращается в forward_from, и по этому индексу возвращается имя класса. почему нельзя было сразу написать в том же регистре - загадка

    В целом - отборнейший говнокод.
    Ответ написан
  • Как использовать сессию для всех клиентов одновременно?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Единственно правильный ответ - никак.

    Такой вопрос можно задать только от безграмотности. От непонимания того, как работают сессии.
    Потому что сессия в обязательном порядке блокирует файл с данными на время работы с ним. И именно отсюда возникают многочисленные вопросы "а почему у меня долгий процесс в одной вкладке блокирует сайт во всех остальных вкладках?". А теперь представим, что один и тот же файл блокирует не один юзер, а все по очереди. Таймаут будет постепенно накапливаться, и в итоге сайт у всех пользователей сначала начнет ощутимо подтормаживать, а потом и вовсе встанет колом.
    Поэтому такая вещь, как "сессия сразу для всех пользователей" заведомо является бессмыслицей.

    Если под "сессией" имелось в виду общее хранилище для всех пользователей, то оно называется "база данных". И в этом смысле "БД не предлагать" выглядит беспочвенным капризом. Как правильно заметил N в комментарии, такое заявление звучит как "Как кушать суп? Ложку не предлагать."
    Такие заявления надо всегда подробно обосновывать. И в этом случае вам либо действительно подскажут, как обойтись без БД, либо объяснят, что это просто блажь.

    Если хранилище не нужно, то есть значение переменной не меняется со временем, то, как правильно сказано в соседнем ответе, просто делается константа в конфигурационном файле, который по умолчанию включается во все скрипты.
    Ответ написан
    Комментировать
  • Можно ли пользоваться Ajax с помощью SQL?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Нет, нельзя.
    Вопрос не имеет смысла.
    SQL - это язык запросов к базе данных. База данных находится на сервере базы данных.
    РНР - это язык для формирования динамических ответов на НТТР сервере. РНР может обращаться к серверу базы данных, используя язык SQL.
    РНР не "обрабатывает данные аякса". РНР обрабатывает НТТР запросы. Любые, сделанные как напрямую браузером, так и через AJAX. И особой разницы между ними не видит.
    AJAX - это технология выполнения запросов к НТТР серверу из программы на Яваскрипте, исполняющейся в браузере. Браузер может обратиться только к НТТР серверу, но не к серверу баз данных.
    Чтобы из Яваскрипта в браузере обратиться к базе данных, надо запросить НТТР сервер, который запустит программу на РНР (или другом серверном языке), которая обратится к серверу БД, получит результат, и вернёт его в ответ на НТТР запрос.
    Ответ написан
    Комментировать
  • Какую версию PHP учить и по какой книге?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Заголовок - это очень важная часть вопроса. Над ним надо очень вдумчиво работать
    Чтобы он не вводил отвечающих в заблуждение, и чтобы ответы оказались вам самому полезны.

    Если говорить об изучении с нуля, как можно понять из заголовка, то я рекомендую книгу Jon Duckett, PHP&HTML. Но её, вроде бы, не переводили на русский. Из доступного - Котеров, но она конечно уже подустарела. Хотя там хорошо даются такие основы, как НТТР.

    Но в вашем случае вопрос об изучении РНР явно не идёт. А скорее о повышении квалификации.
    Плюс вопрос "Какую версию учить" тоже не стоит - у седьмой версии поддержка кончается осенью. Но в целом различия между версиями в РНР не настолько принципиальны, чтобы можно было учить какую-то конкретную "версию". Чисто синтаксические нововведения в языке лучше всего изучать по разделам "Новая функциональность" каждой версии отсюда https://www.php.net/manual/ru/appendices.php

    Но начиная с определенного уровня изучение РНР уже перестаёт быть изучением РНР, а скорее программирования в целом - ООП, паттернов проектирования и т.д. Тут уже книжки по РНР не нужны, сами пхпшники учат это по явовским учебникам - Фаулера, Мартина и пр.
    Хотя конечно к зарабатыванию денех на PHP + Битрикс это всё не имеет уже ни малейшего отношения.
    Ответ написан
    Комментировать