Задать вопрос
Ответы пользователя по тегу PHP
  • PHP file_put_contents дописывает в файл или перезаписывает его?

    @rPman
    file_put_contents(... FILE_APPEND) дописывает содержимое в конец без пересоздания и перечитывания файла
    это просто упрощенная запись конструкции
    fopen(...,'a');fwrite(...);fclose(...);
    если FILE_APPEND не указывать, то используется режим типа w+ (существующие файлы обрезаются в 0 размер, не существующие ошибки не вызывают)
    p.s. важное замечание file_put_contents FILE_APPEND работает очень медленно, синхронизируя каждую запись с диском, я помню переписывал код на использование fopen/fwrite плюс там можно гибко задавать буфер записи

    upd. на самом деле там используется просто режим 'a' и 'c' и чуть больше проверок
    С интересом обнаружил по исходникам что file_put_contents умеет писать array, объединяя без разделителя значения и пропуская ключи.... век живи век учись, не знаю зачем но смешно
    Ответ написан
    2 комментария
  • Как подключиться к wss по такому адресу?

    @rPman
    wss - это websocket по https, тебе точно нужно вручную заниматься всем что касается шифрованием на php?
    настоятельно рекомендую для работы с websocket использовать уже готовые библиотеки например textalk websocket или ratchet pawl, вот почитай минитуториал на русском
    Ответ написан
  • На windows float выводится с запятой, а на linux с точкой. Как исправить?

    @rPman
    Удивительно, что нужно сделать с windows чтобы в php номера форматировались под настройки локали (в русской там запятая стоит, но я точно помню даже со времен winxp в официальных сборках php там возвращались точки, собственно я сейчас порыл коментарии под setlocale и там твоя проблема подтверждается)
    Наверное setlocale похоже не отрабатывает корректно, покажи вывод после setlocale - localeconv, точнее что там в decimal_point будет

    Советую чтобы уж точно все гарантировать, любые данные, передаваемые в браузер пропускать через json_encode, это будет гарантировать корректный формат для чтения в javascript, а в браузере уже переводи к нужному виду (формат номеров там стандартизирован и не зависит от локали)

    Либо использовать number_format чтобы фиксировать свой десятичный символ вне зависимости от локалей
    Ответ написан
  • Как сделать локальную базу данных?

    @rPman
    локальная sql база данных - это sqlite

    проще этой найти невозможно (база данных в файле, установка настройка и прочее это копирование файла и прописать его имя в настройках подключения), на чтение она достаточно эффективна да и на запись для большинства мелких задач более чем подходит
    Ответ написан
    Комментировать
  • PDO PHP проверить выполнение INSERT?

    @rPman
    используй sql запрос INSERT IGNORE и после запроса проверяй количество вставленных записей с помощью rowCount
    Ответ написан
    1 комментарий
  • PHP cURL не работает с https прокси. Прокси точно работает. Что я делаю не так?

    @rPman
    твоя прокси умеет работать только с http, а https сайты с ней не работают (запрос подвисает в бесконечный таймаут)
    CURLOPT_SSL_VERIFYPEER, false
    вот такие выкрутасы на анонимных проксях могут прокатить, так как прокси атакуют Man-in-the-middle, подменяя на невалидный сертификат, т.е. у тебя утекут либо логины пароли либо куки либо еще какая то критичная информация, а еще прокси могут подменять трафик, в лайтовом виде - подмена рекламного идентификатора и просто реклама, а в хардкоре... любые финансовые сервисы станут уязвимы
    Ответ написан
    1 комментарий
  • Каким образом объединить файлы в один на php?

    @rPman
    и да и нет
    нет - потому что объединять в один файл не надо
    да - потому что есть 'базы данных в файле', поддерживающая многопользовательский доступ и транзакции - sqlite

    если ты объединишь все в один файл, то у тебя возникнет проблема многопользовательского доступа (на запись), пример - у тебя одновременно два разных человека напишут боту, два одновременных php процесса начнут читать и писать файл, и если эти события будут не последовательными, то либо в файле будет каша либо сообщения от одного 'чуть чуть опоздавшего' будут перезаписаны

    Настоятельно рекомендую освоить базу данных, тем более благодаря php PDO и sqlite ничего настраивать устанавливать и тюнить не надо, все максимально удобно и просто
    Ответ написан
  • Почему не освобождается память?

    @rPman
    Проведи больше экспериментов и поймешь что та память что не освобождается не накапливается, т.е. если повторно выделить память и очистить ее, то итоговое потребление не вырастет.

    Мне кажется это часть памяти занята под индексы (увеличивая размер массива увиличивается и потребление но зависимость от количества записей а не от их размера) и переиспользуется в дальнейшем
    Ответ написан
    Комментировать
  • Импорт большого yml в mysql?

    @rPman
    как импортируешь то? ты в свой скрипт не можешь вставить sleep между запросами?

    львиную долю нагрузки базе данных на запись создают:
    1. поддержка транзакций
    2. перестройка индексов
    3. средства защиты данных от сбоев
    каждая запись на диск, которая по мнению базы данных должна быть произведена с гарантией, т.е. снабжается вызовом flush, но база данных не всегда знает когда это стоит делать а когда нет, частично это разруливается длинными транзакциями, вставляя между коммитами 100500 запросов на вставку

    Так вот по каждому пункту можно временно изменить логику и настройки работы базы данных.
    1. отключить транзакционные механизмы, перейдя от innodb к myisam, это может дать чуть ли не двухкратный прирост, но потребует в приложении как то игнорировать отсутствие поддержки транзакций, что не всегда просто сделать
    2. отключить индексы, буквально, оставить только PK и то только там где это имеет необходимость только для импорта, после окончании импорта данных, индексы нужно будет вернуть. Однократное создание индексов на порядок если не два быстрее чем обновление индексов по каждой записи в базу.
    3. отключить поддержку flush в операционной системе, буквально например опция монтирования ext4 data=writeback, база данных не будет ждать когда данные реально будут записаны на диск (есть еще опция O_DSYNC у mysql innodb, совет вообще полистать как тюнить дисковый io) но осторожно, если в это время произойдет краш сервера, данные будут испорчены, причем скорее всего безнадежно. В догонку, можно перенести журнал ext4 на другое более быстрое устройство или лучше совсем его отключить, так как при записи данные пишутся сначала в него потом на диск, на время импорта это лишние операции
    И в догонку, если размер базы данных к примеру считанные сотня гигабайт, то можно временно арендовать в облаке машину с большим объемом RAM, залить базу в tmpfs и на максимально быстрой скорости импортировать данные, потом готовую базу залить обратно.

    т.е. данные действия позволят, остановив работу (без этого никак) провести импорт максимально быстро и восстановить работу, пол миллиона записей это мизерный объем и если что то тормозит то исключительно из-за плохой архитектуры или реализации
    Ответ написан
    3 комментария
  • Как очистить память php?

    @rPman
    у тебя твой скрипт съел 256мб оперативной памяти, ищи куда она делась, расставляй по всему своему скрипту на сервере вывод в лог значение memory_get_usage(true) с пометкой где это произошло, например:
    error_log(json_encode([__FILE__,__LINE__,memory_get_usage(true)]));

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

    а по уму нужно использовать полноценные профилировщики типа такого
    Ответ написан
  • Найти и изменить строку в файле?

    @rPman
    есть 2 подхода по редактированию файлов:
    1. ты находишь место в файле (буквально смещение в байтах), открыв его на чтение и запись fopen(...,'r+') читая его помощью fread или fgets или еще какой функцией (позиция будет перемещаться на следующую для чтения), перемещаешь в нужное место позицию fseek и делаешь запись fwrite или fputs, заменяя содержимое, без сдвига данных после него

    этот способ подходит если заменяемые данные равны по длине с предыдущими

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

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

    Этот способ подходит для редактирования текстовых файлов, а точнее когда заменяемые данные не равны по длине оригинальным.

    p.s. третий способ состоит в том что сначала файл целиком загружается в память (не важно каким способом, целиком, построчно или разобранный по объектам), в памяти он редактируется как надо, и сохраняется обратно.
    В этом способе можно сохранять файл в тот же файл что и был, открыв его fopen..'w+') - что очистит файл при открытии, а значит проблемы с местом на диске менее вероятны, но если произойдет какая либо ошибка то содержимое будет потеряно, рекомендуется точно так же сначала сохранить файл в новый, удостовериться что все прошло как надо и уже после удалить оригинал и переименовать новый.

    p.p.s. бывает что совмещают первый и третий способы, но относительно не всего файла а его части (например базы данных, сначала сохраняют новые данные в специальный лог файл и позже по необходимости перемещают эти данные в нужное место. Так реализуются транзакции

    Некоторые файловые системы предоставляют инструменты для реализации транзакций но в php для этого нет инструментов.
    Ответ написан
    Комментировать
  • Как правильно построить таблицу при получении данных из csv файла?

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

    еще момент, ты по коду старательно парсишь csv самостоятельно да еще и не правильно (строки в ковычках могут содержать переход на новую строку), в php для этого есть хорошая функция fgetcsv, возвращает готовый массив
    Ответ написан
    1 комментарий
  • Как обновлять файл json на php?

    @rPman
    Всегда стремись разделять получение данных бакэндом и выдачу этоих данных на странице, когда это получение медленее чем работа слокальными данными... т.е. всегда кешируй данные, особенно когда инвалидация не строгая.

    Отдельный демон (хоть и по крону) опрашивает api, проверяя появление новых данных или изменение. От этого api зависит, в худшем случае, если нет возможности даже даты изменений получить - запрашиваешь все данные, собираешь свой json и берешь из него как строка - хеш например md5, изменился - есть новые данные, значит записываешь json (совет если работаешь с файлами, пиши всегда файл с новым именем, и при запросе - отдавай тот что записал последним, после окончания записи старый файл удаляй, это исключит ошибку если будет запрос на чтение в момент сохранения).

    Если api позволяет оценить изменения в данных, то хранить в файле json имеет смысл только если он не большой, иначе да, как то оптимизировать хранение, либо по файлу на объект либо действительно в базе данных, по желанию
    Ответ написан
    2 комментария
  • Как с помощью PHP организовать обмен письмами так, чтобы выделять переписку в рамках одного обращения?

    @rPman
    Связывай письма не по теме а по хидерам в письмах: In-Reply-To, References и не стандартный майкрософтовский Thread-Index, по крайней мере так было раньше, маловероятно что что то еще добавилось
    Ответ написан
    Комментировать
  • Как отредактировать данные в php файлах?

    @rPman
    Первый и главный вопрос, на который нужно ответить при хранении данных - существует ли 'многопользовательский' (а точнее множественный одновременный) доступ к этим данным, только ли он на чтение или возможна одновременная запись? есть ли особенности по блокировке записи (например пользователь открыл форму, прочитав данные, и пока он не нажал сохранить или отменить - доступ к данным другим пользователям закрыт) и т.п.

    Второй - как много данных

    Третий - на сколько сложные запросы по поиску и фильтрации у тебя есть

    И если многопользовательского доступа нет и данных не много (максимум мегабайты) и работа с данными простая, то можно совсем не заморачиваться с базами данных и хранить все в файлах. Для этого в php есть несколько инструментов сериализации любых данных в строки (массивы, объекты. строки и т.п.):

    serialize, json_encode, php_export (этот формирует строку в формате php, т.е. загрузить такой файл можно просто импортировав его в код), относительно недавно появился igbinary_serialize (расширение идет в поставке с php) - отличный бинарный формат, достаточно эффективный и наверное самый быстрый из существующих.

    Так же сериализовать в файл можно не сразу все данные а по объекту на файл (файловая система ОС - отличная key-value база данных, удобная быстрая, но без нормальной поддержки многопользовательского доступа, точнее можно с помощью блокировок но сложно), благодаря чему можно решать очень сложные задачи без оверхеда на место на диске, процессор и лишний кодинг. Недостаток этого подхода - индексы реализовывать придется самому.

    p.s. по теме конкретно сформулированного вопроса, гугли CRUD, это готовые инструменты по create,read, update, delete объектов, которые тут же описываешь. Так или иначе эти механизмы мого кто реализует в своих фреймворках

    но начинающему настоятельно рекомендую пройти весь путь от самописных структур данных и работе с sql
    Ответ написан
    4 комментария
  • Как правильно составить SQL запрос SELECT PDO PHP для получения данных по двум строкам?

    @rPman
    так как не сказано какая именно логика в запросе должна быть при нулевых значениях, я выбрал в примере вариант - и в базе тоже нули.
    select .. from ... where ... and (:product_group is null and `product_group` is null) or (`product_group` = :product_group)

    чтобы один и тот же параметр в запросе использовать несколько раз, используй пользовательские переменные (живут до конца сессии), т.е. выполняешь два запроса, первый
    set @product_group=:product_group
    а уже в самом запросе вместо :product_group используешь @product_group
    Ответ написан
    Комментировать
  • Как сделать закрытый доступ для страницы на php и mysql?

    @rPman
    digest http auth
    настоятельно рекомендую не использовать этот метод авторизации (да и любой) без https
    Ответ написан
    Комментировать
  • Как вывести информацию с БД массивом?

    @rPman
    в $query->execute(['ref' => $my_ref[0]]); данные массивом передались.

    к сожалению биндинг в pdo не умеет работать с массивами, каждый параметр должен быть конечным объектом (число., строка...)

    так же чтобы условие в sql обрабатывало массив нужно использовать выражение
    select ... from ... where id in (1,2,3,4,...)

    поэтому чтобы решить указанную задачу нужно формировать sql запрос по старинке (без использования prepare и биндингов), естественно аккуратно к значениям, либо валидировать их что они являются числами, а если должны быть строки - то правильно экранировать

    $sql='select ... from ... where id in ('.implode(',',$id_array).')'

    Так же проверь что массив идентификаторов не пустой, так как иначе будет ошибка в sql

    p.s. осторожно, количество значений в 'id in' лимитировано (кажется 1000), если инужно больше, то придется создавать временную таблицу, заливать в нее искомые идентификаторы и строить запрос с left join

    Еще я встречал похожий метод но с использованием биндингов, когда sql запрос генерировался вида:
    select ... from ... where id in (?,?,?,?,...)
    с нужным количеством ? тогда передав массив напрямую в execute можно получить результат, лимит на количество ? еще меньше, это определяется драйвером базы данных.

    p.p.s. и совсем сверху на засыпку методика, ее имеет смысл использовать когда со стороны клиента фильтруемых данных больше чем 1 поле (например 2 массива точнее таблица с несколькими колонками) и очень не хочется заполнять в базе временную таблицу с этими данными (это очень сильно роняет производительность) то можно сформировать внутри sql таблицу из константных данных:
    select ... from ...,
    (
      select ? as col1,? as col2
      union select ?,?
      union select ?,?
    ...  
    ) x where ...
    Ответ написан
    4 комментария
  • Как можно вытащить стоимость товара из сайта конкурента?

    @rPman
    цена на сайте не формируется скриптом, т.е. достаточно загрузить эту страницу и разобрать например simple_html_dom
    Ответ написан
    Комментировать