Задать вопрос
Ответы пользователя по тегу PHP
  • Как спарсить сайт через PHP с более 30 тыс. ссылками?

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

    И помним, админу сайта может не понравиться 100500 запросов к их серверу, так как это похоже на ддос.
    Ответ написан
    Комментировать
  • Как создать мгновенно самоперезапускающийся скрипт php?

    @rPman
    while(true);do php some.php;sleep 1;done
    sleep 1 это чтобы между запусками была пауза, можешь убрать но если ошибка будет возникать сразу при запуске, такой скрипт будет жрать ресурсы просто так, что иногда выходит в копеечку в облачных хостингах с оплатой за ресурсы.

    не забудь отметить ошибку в логе чтобы реагировать на них
    Ответ написан
    Комментировать
  • Как получить историю транзакций с биржи Poloniex?

    @rPman
    Обычно наоборот, работают с текущего момента времени и в прошлое, пока данные в принципе возвращаются.

    Устанавливая только end на время самой первой сделки в предыдущем запросе минус 1
    Ответ написан
  • Можно ли написать try-catch один раз?

    @rPman
    Написать можно но смысла в этом практически нет, а вреда полно

    В момент ошибки вместо записи ее в логи сервера, эта ошибка выпадет у клиента, или верстка сломается и страничка будет кривая и непонятная. 99% пользователей увидят, закроют и пойдут дальше, не возвращаясь, а ты так об этом и не узнаешь.

    Если try catch будут не единственными, то корневой имеет смысл чтобы отлавливать 'все остальные' ошибки и отправлять их в свой собственный лог (чтобы их поправить само собой)... ну кому как удобно
    Ответ написан
  • Как правильно работать с большим количеством данных?

    @rPman
    Избавляйся от ... where fld like '%...%' это самые плохие по скорости запросы, хотя не всегда это возможно без увеличения размера базы, вообще полнотекстовый поиск можно отдавать на откуп стороннему приложению (это может расширить возможности фильтрации), считай это еще одной формой индекса, хотя лучше данные по другому хранить. Я встречал ситуации когда в varchar хранили значения справочника из десятка значений, но делали по нему like %% что грузило базу прилично, когда как сделать простой комбобокс на порядок эффективнее и удобнее - поиск по подстроке лучше по справочнику делать на клиенте.

    Без индексов скорее всего никуда, если в запросе идет фильтрация по полю, то если не создать на него индекс, этот запрос и будет создавать нагрузку

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

    Частный случай прогноза, не делать select ... limit ... на каждую страницу, а при смене фильтра запрашивать весь диапазон, но только идентификаторы, сохранив их либо в таблице на сервере либо на бакэенде, генерирующим запросы вида select ... id in (...), последнее если количество записей не больше тысяч. Кстати именно постраничная навигация с прогруженным списком id самая шустрая

    Кешируй результаты запросов, можно на клиенте, можно даже средствами браузерного кеша, очень часто работа человека состоит в перемещении туда сюда по своим запросам, так зачем нагружать лишний раз сервер тем что уже известно. Осторожно с инвалидацией данных, и кстати не всегда она так уж и критична.

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

    p.s. диск на сервере hdd или ssd? если не хватает денег на большой ssd, настрой маленький ssd как кеш к медленному hdd (linux bcache), даже когда данные полностью не влезают в кеш, это дает заметный прирост, потому что hdd начинает менее случайно двигаться, плюс добавляется буферизация записи (данные записываются на ssd и лежат там пока hdd не освободится), так же дает эффект ускорения записи вынос журнала файловой системы (если ext4) на ssd (требуется пара гигабайт от силы).

    Осторожно, если высокие требования к надежности хранения, кеширующий ssd в режиме записи лучше пусть будет хотя бы raid1, так как иначе при смерти ssd починить данные, размазанные по диску и кешу будет очень сложно. Для кеша только для чтения это не так критично (при смерти ssd сервер просто упадет, не убивая данные).

    Но мне больше нравится резервирование на лету (настроить онлайн репликацию, пусть и на слабый, бакап сервер)
    Ответ написан
    1 комментарий
  • Как передать байтовую строку из python скрипта в PHP?

    @rPman
    preg_replace_callback('/\\\\x([0-9a-f]{2})/',function($m){return hex2bin($m[1]);},закодированная строка);
    Ответ написан
    Комментировать
  • Почему при копировании в инпут буквы "ё" появляются проблемы у strtr?

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

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

    @rPman
    Запакуй папку tar-ом, без сохранения архива, через пайпы передай в md5sum, получишь результат
    $md5=explode(' ',`tar -cf - /path/to/dir | md5sum`)[0];
    upd. осторожно, используй относительные пути а не прямые, так как этот путь файлов так же хешируется

    на php делать все будет тупо сложнее и медленнее

    p.s. новые версии tar поддерживают --order=name чтобы гарантировать хоть какой то порядок файлов
    Ответ написан
    Комментировать
  • Помощь с POST запросом php?

    @rPman
    Измени теги вопроса, так как у тебя сторона браузера, т.е. Javascript

    Делать это с помощью ajax запроса или самостоятельно собирать с помощью xmlhttprequest
    Ответ написан
    Комментировать
  • Как отредактировать doc/docx на PHP?

    @rPman
    docx, это zip архив с набором текстовых xml файлов, простейшие манипуляции с текстом там максимально простые, хотя формат и не простой, но в большинстве задач в дебри залезать не придется.
    Ответ написан
    Комментировать
  • Параллельные запросы к СУБД во время отсутствия кэша записи - какой алгоритм?

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

    Определенно, необходимо отлавливать эту ситуацию и останавливать генерацию контента на всех страницах кроме одной, буквально - 'тормозить, чтобы двигаться быстрее'.

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

    Логично было бы не делать случайный sleep для этого, а ждать ивент от соседнего процесса, в идеале средствами этой базы данных
    Ответ написан
    2 комментария
  • Можно ли сымитировать отправку POST запроса?

    @rPman
    curl - мощная утилита и одноименная библиотека (в php есть curl_init/curl_setopts/curl_exec) позволяет создать http запрос

    Браузеры в отладочной консоли (network monitor) позволяют на выбранном запросе из лога (нажав правую кнопку - copy - copy as curl) получить готовую строчку запуска curl полностью симулирующю его.
    Ответ написан
    1 комментарий
  • Как запустить python скрипт из под php?

    @rPman
    Добавь в команду 2> err.txt

    Проверь что можешь писать в текущий каталог

    Вместо shell_exec попробуй passthru($cmd,$return_int) сможешь увидеть код возврата $return_int а еще этот метод не съедает вывод программы
    Ответ написан
    Комментировать
  • Как принимать только актуальных данные по API в PHP без базы?

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

    тебе нужна key-value база данных, если данных мало и они влезают в память массивом $index[$hash]=true то тогда храни в файле в сериализованном виде var_export/serialize/json_encode или даже по 1 строке на запись - читать array_flip(file('имя файла'))

    p.s. бери sqlite, на столько простой удобной и неприхотливой базы данных не найти, реализованна в файле, ничего не требует для администрирования, работает везде...
    Ответ написан
    Комментировать
  • Как хранить подключение к БД для удобного обращения из других классов без глобальной переменной?

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

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

    class Main
    {
      public $db; // само собой можно геттеры сеттеры делать или сами методы по работе с базой тут определить
    }
    class Work
    {
      function __construct($main)
      {
        $this->main=$main;
      }
      function do()
      {
        $this->main->db->connect(...)
      }
    }
    Ответ написан
    5 комментариев
  • Как передать такой формат в POST CURL?

    @rPman
    curl_setopt($ch, CURLOPT_POSTFIELDS,['contacts'=>'[{"type":"phone","code":"+972","phone":"44255424"}]');
    https://www.php.net/manual/ru/function.curl-setopt.php

    Все данные, передаваемые в HTTP POST-запросе. Этот параметр может быть передан как в качестве url-закодированной строки, наподобие 'para1=val1&para2=val2&...', так и в виде массива, ключами которого будут имена полей, а значениями - их содержимое. Если value является массивом, заголовок Content-Type будет установлен в значение multipart/form-data. Файлы можно отправлять с использованием CURLFile, в этом случае value должен быть массивом.
    Ответ написан
    Комментировать
  • Как с помощью PHP скопировать часть контента из файла?

    @rPman
    метод file (тоже умеет http) вернет массив из строк в указанном файле, проходишь по нему в цикле, как найдешь стартовую строку, начинай все строки сохранять в результирующий файл, заведи переменную статус - true - сохраняем, false - пропускаем, как найдешь строку окончание - устаналивай ее в false.
    Ответ написан
    Комментировать
  • Что происходит при создании объекта класса(при наследовании) в PHP?

    @rPman
    Боюсь у вас все как то переусложнено.

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

    Соответственно виртуальных методов нет, точнее они работают так автоматически, т.е. можно считать все методы виртуальными.

    И да, все что касается методов и их наследования скорее всего сделано однократно, в момент компиляции, а в момент создания экземпляра объекта в него копируются методы и переменные из этого сохраненного.

    Деструктор будет вызван если закончится работа приложения, закончатся ссылки (это кстати не факт, висячие могут жить до конца приложения, и даже unset не вызовет деструктор если есть ссылки на объект) и закончится область видимости переменной в которую поместили объект.
    пример:
    class A
    {
    	public $a;
    	function __construct(){echo '{C}';}
    	function __destruct(){echo '[';unset($this->a);echo 'D]';}
    }
    
    echo 1;
    $a=new A();$b=new A();
    $b->a=$a;$a->a=$b; // закоментируй, тогда деструктор будет вызван до вывода 2 иначе после
    unset($a);unset($b);
    echo 2;

    если есть ссылки:1{C}{C}2[[D]D]
    если ссылок нет: 1{C}{C}[D][D]2
    Ответ написан
    Комментировать
  • Можно ли получить файл по URL в РНР? Нужно ли для этого писать модуль на другом языке?

    @rPman
    php имеет штатный инструмент работы с файлами по ссылкам http/ftp во всех своих методах типа fopen или file_get_contents

    Протоколов много, можно регистрировать собственные

    Расширения для php пишут на c и с++, вы конечно можете извратиться и писать на любом другом языке, главное чтобы он был компилируемый, но работа эта бессмысленно сложная
    Ответ написан
    Комментировать
  • Как выбрать рандомную запись с бд на основе веса записи?

    @rPman
    Мне кажется эта задача красиво средствами базы данных не решается.
    Любое решение будет либо медленным, либо вероятностное распределение итоговое не будет желаемым.

    100 запросов в секунду - зачем такой нетипичной задачей грузить базу данных?

    Задайся вопросом, сколько у тебя записей? миллионы? миллиарды? может эффективнее будет держать список id на бакэнде массивом и выбирать от туда?
    * Запили миниатюрный сервис с сокетами, в который бакэнд при удалении или добавлении записи будет присылать id, а при перезапуске будет загружать весь список id... памяти это занимать будет порядка 16х от количества записей умножить на логарифм (зависит от того какие списки поддерживает бакэнд, нужно хранить упорядочный num -> id, причем это просто массива, при добавлении id добавляется в конец, а при удалении - на место удаленного ставится элемент с конца, к сожалению тогда для быстрого удаления нужен map: id->num).
    * Списков таких должно быть несколько - свой по каждому значению веса (считается что вес - целочисленный и вариантов значений значительно меньше общего количества записей), соответственно каждый id попадает в свой список.
    * Каждый раз, как идет запрос на случайный id, считаешь два случайных числа:
    - первое на интервале [0..максимальное значение веса) - выбираешь какой вес сейчас сработает
    это нужно делать с учетом вероятности, которое соответствует каждому весу, т.е. для каждого веса свой интервал значений случайного числа, для 1 это будет попадание между [0..1), для 2 - [1..3), для 3 - [3..6), для 4 - [6..10),.. макс значение интервала равно сумма арифметической прогрессии 1....N где N максимальное значение веса. Левое значение интервала для n считать по формуле суммы арифметической прогрессии а правое + значение веса для него.
    - второе, [0..максимальное значение num в соответствующем списке)
    второе число даст искомый номер в массиве, а значит и id.
    * Для значений весов которые не используются (пустые списки id) нужно будет исключать такое число из списка доступных значений весов, делать новый список с меньшим количеством и давать соответствие значений их этого нового списка с меньшим количеством весов и общим, чтобы такие неиспользуемые веса не попадались.
    К примеру из весов 1..10 используются только 1,4 и 10, тогда делаем получаем новый список из 3 элементов, но в формуле расчета интервала для вычисления правой границы использовать значение веса, т.е.:
    [0..1), [1,5),[5..15) - общий интервал [0..15)

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

    Трудоемкость алгоритма О(1) с очень маленькой константой, но требует память O(n)= n*log(n) с процессором O(n) log(n) на любые модификации.

    p.s. Данный алгоритм можно реализовать и в базе данных, на тригерах, так как держать в оперативной памяти списки не требуется, причем базы могут быть отдельные от реальной (очень неудобно и повышенная нагрузка на процессор, лучше использовать key->value базы данных только как хранилище списков id)
    Ответ написан
    Комментировать