• Как вызывать динамический метод класса как статический в PHP?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Тебе нравится концепция ларавельных фасадов, которые публичные методы статически вызывают.

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

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

    Причина (но не проблема) этого - отсутствие в пхп понятия "перегрузка метода" которое позволяет в одном классе написать один и тот же метод 3-4 раза указав разный набор параметров и по числу переданных параметров будет выбрано что это есть. Это штука конечно модная, но хорошо, что её нет. Когда она есть код будет более странным и непредсказуемым при беглом чтении. В пхп решили это не делать. Вернее как сказать - понятие ввели, как написал Сергей delphinpro, но реализация идет через 4 разных метода, которые ты потом с помощью if() вручную определяешь.

    У меня так в библиотеке сделаны модули, я специально писал генератор фасадов, потому что у меня 20 классов, во всех методов около 10, и надо чтоб хочешь - фасадом как в ларе, хочешь иньекцией зависимости как предполагает паттерн инжектор, хочешь трейтом можно было подключать когда лень и побыстрому, хочешь - aware интерфейсом через сеттер как в симфони прямо контейнером. https://github.com/6562680/support

    Но "ООПшным" способом - это если хочеться разобраться "как". Если хочется решить проблему - бери статью о фасадах в ларе и делай по ней.

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

    Судя по твоему примеру с моделью ты пытаешься дать модели некое действие, потому что так подразумевает логика твоей программы, то есть ты условно хочешь научить модель Юзер создавать или там менять как-то другого/несколько/всех юзеров. Поздравляю, ты подошел к понятию "агрегата", который в книгах много где встречается. Но это слово упрощается до слова "класс-сервис", когда ты свой метод создаешь не в модели Юзер, а в другом классе, называешь его UserService, и потом его на входе конструктора ожидаешь, и он туда будет подброшен, и не надо будет статикой ничего делать.

    Но да, есть и тут подводный камень. Когда хочешь изнутри модели в методе вызвать, там же конструктор уже занят $attributes, надо наследовать, а потом создавать модельки уже не через new, а через контейнер, чтобы подбрасывалось - но это боль. Поэтому перейди к работе с классами сервисами. Если ты хочешь поменять модель - ты свою модель передаешь в метод сервиса параметром, где сервис над моделью делает действие и выдает измененную.
    Ответ написан
    4 комментария
  • Как сделать парсер крупных сайтов и маркетплейсов на PHP, обходящий блокировки?

    dbkv
    @dbkv
    backend developer
    Подскажите, что именно стоит изучать, на что акцентировать внимание, какие библиотеки использовать, чтобы создать желательно быстрый парсер маркетплейсов на PHP?

    Зависит от ваших текущих знаний. Написать парсер сайтов можно на любом языке программирования, при желание. Удобнее всего, на мой взгляд сделать это на Python с использозованием библиотеки -- https://www.crummy.com/software/BeautifulSoup/bs4/doc/ либо на NodeJS.

    Посоветуйте,какой стек использовать, что почитать и изучить, чтобы реализовать следующий функционал:

    Python / Request / BeautifulSoup4 либо NodeJS / Axios / node-html-parser. Если осмелитесь писать на PHP, что на мой взгляд крайне не удобно, то guzzle + phpQuery, как вы уже сами и написали.

    Также, сейчас на многих сайтах используется технология SPA и клиентский рендеринг. Если в кратцы - то контент на сайт подгружается через API и рендерится с помощью JS. Если в тупую обратиться к такому сайту с сервера (например через curl), то с высокой долей вероятности мы получим пустую страницу.

    Для таких сайтов нужно использовать эмуляторы браузеров, например seleniumhq.org или https://pptr.dev/. Биндинги есть на Python и NodeJS, возможно и на PHP.

    можно ли будет использовать парсер от Python на PHP сайте?

    Да, можно просто написать API на Python и поднять сервис на отдельном поддомене или порту, а далее в JSON-формате возвращать данные на сайт и делать с ними дальнейшие операции.

    На счет обхода блокировок. Стоит сказать сразу, что блокировки будут всегда, поэтому при разработке парсера надо обязательно предусмотреть следующее:


    1. Каждый запрос рандомизируем заголовки (request headers) и User-Agent. Обязательно. Тут без вариантов.

    2. Делаем запросы исключительно через proxy + каждый запрос рандомизируем их. В идеале иметь пулл из ~20 проксей. Крайне желательно чтобы прокси были приватными.

    3. Если уперлись в капчу, то делаем повторный запрос с другой прокси, если сайт ни в какую не хочет нас пускать к контенту, то разгадываем капчу. Либо реализуем разгадывание руками пользователя (т.к у вас интерфейс есть), либо с помощью любого сервиса разгадывания капчи, типа https://capmonster.cloud/ru/ или https://rucaptcha.com/.

    Надеюсь я смог прояснить некоторые технические детали парсинга сайтов.
    Ответ написан
  • Как правильно использовать socks proxy в python requests?

    @RivalCode
    Неправильно указан словарь с прокси: "://" в схеме не нужны, h после {socks_type} тоже
    proxies = {
            "http": f'socks{socks_type}://{host}:{port}',
            "https": f'socks{socks_type}://{host}:{port}'
        }
    Ответ написан
    1 комментарий
  • Как задать пользователя для cron?

    romy4
    @romy4
    Exception handler
    crontab -u username -e
    Ответ написан
    Комментировать
  • Парсер на VPS получает код ответа 403. Как исправить?

    dimonchik2013
    @dimonchik2013
    non progredi est regredi
    403 Forbidden

    видимо IP VPS ему на нравится, а может и факт VPS
    Ответ написан
    Комментировать
  • Как спарсить подобный сайт?

    fenrir1121
    @fenrir1121
    Начни с документации
    Как спарсить подобный сайт?
    Подобный чему?

    Сайт может блокировать аккаунты на несколько часов, что и происходит примерно через 30 минут парсинга.
    Что за операции, что вам не хватает 30 минут?

    Сначала пробовал работать через api сайта.
    Демонстрируйте код.

    Логинился в селениуме, получал заголовки и делал запросы на нужную мне информацию
    Так через api или селениум, вы определитесь.

    Можно ли попытаться выдать селениум хром за сафари на iPhone, и есть ли вообще в этом смысл?
    Вы сами пишите что парсинг возможен только из под аккаунта и блочится аккаунт. Очевидно сайту все равно сколько устройств вы имитируете, если аккаунт один и тот же.
    Ответ написан
    3 комментария
  • Как зарегистрироваться в яндексе без номера телефона?

    @DmitryRed
    В Яндексе есть упрощённая регистрация. С помощью неё можно зарегистрироваться в Яндексе, используя только свою почту (причём можно использовать не только Яндекс Почту).
    Действуйте так:
    1) Зайдите на yandex.ru
    2) Нажмите на кнопку "Войти" (именно "Войти", а не "Зарегистрироваться")
    3) В открывшемся окне появятся две кнопки с полями для ввода: "Почта" и "Номер телефона". Выберите "Почта" и введите Ваш e-mail. Яндекс отправит на указанный электронный адрес код с подтверждением. И далее регистрация будет без номера телефона.
    Ответ написан
    2 комментария
  • Как правильно организовать очередь с условием?

    iNickolay
    @iNickolay Автор вопроса
    Вообщем, решение, как я и предполагал, простое:

    В классе необходимо указать $tries, а вместо исключения вызывать $this->release()

    В спойлере код класса:
    Job class
    class MyQueueJob implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    
        const TIMEOUT = 10;
    
        public $tries= 288;
    
        public $url;
    
        public $data;
    
        public function __construct(string $url, $data)
        {
            $this->onQueue('myqueue');
    
            $this->url = $url;
            $this->data = $data;
        }
    
        public function handle()
        {
            try {
                $response = Http::withOptions(['verify' => false])
                    ->timeout(self::TIMEOUT)
                    ->post($this->url, [$this->data]);
            } catch (\Exception $exception) {
                $this->release(300);
            }
    
            if (isset($response) && $response->failed()) {
                $this->release(300);
            }
        }
    }

    Команда, выполняемая в supervisor`e:

    command=php /laravel/artisan queue:work --queue=myqueue
    Ответ написан
    Комментировать
  • Проблема с сохранением в csv результата парсинга на Python. Как решить?

    @PavelMos
    Ты создаешь словарь в company , а потом пытаешься взять данные по ключам словаря из объекта soup
    Ответ написан
    1 комментарий
  • Какую OS выбрать для NAS?

    @Drno
    Ну ubuntu\debian....
    TFTP должен поддерживать в первую очередь Ваш роутер...

    Из готового посмотрите openMediaVault
    В том числе есть виртуалки и докер...
    Там же ничего не мешает поднять там же на голом железе некстклауд и перенастроить веб сервер для работы некстклауда и веб интерфейса
    Ответ написан
  • Стоит ли переходить с Proxmox на Docker? Какая архитектура более удобна для множества highload проектов?

    voidnugget
    @voidnugget
    Программист-прагматик
    Ну как-бэ до 100Мбит трафика на ноду - ну совсем не Highload.
    Нужно понимать что вопрос сформирован достаточно плохо и сразу видно общее недопонимание темы деплоя и непрерывной интеграции. Советую сначала разобраться с особенностями современных систем оркестрации и управления инфраструктурой: Puppet, Chef, Ansible, SaltStack и OpenStack, потом разобраться как с этим дружить виртуалки и системы управления контейнерами типа XEN, KVM и LXC (Docker). Также советую разобраться с понятием Test Driven Deployment и как оно соотносится с Continuous Integration в целом.

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

    В общем большая часть вышеописанного вообще не ассоциируется с реальным highload'ом - от 10ти и до 40Гбит на ноду (чистого REST трафика). PHP для такого - ну совсем не тортъ, но есть проблески типа Phalcon, правда там есть проблемы со стабильностью.

    Docker сам по себе не имеет никакого отношения к микросервисным архитектурам, но часто используется для менеджмента контейнеров в таких случаях, хотя можно использовать любое решение для этого. А вообще у микросервисных архитектур есть куча недостатков, и они совершенно не подходят для задач около-реального времени.
    Ответ написан
    1 комментарий
  • Не отображает путь и пользователя Ubuntu terminal, в чем проблема?

    ky0
    @ky0
    Миллиардер, филантроп, патологический лгун
    По умолчанию шелл пользователя sh, он без красивостей. Поменяйте в /etc/passwd на что хотите, тот же bash.
    Ответ написан
    Комментировать
  • Как запустить python скрипт из php на xampp который установлен на Windows?

    druzhanja
    @druzhanja Автор вопроса
    Не пойму где меджик но заработало ))

    test.py
    print "Hello world"


    test.php
    <?php
    $python =  shell_exec('C:\Python27\python.exe e:\xampp\htdocs\scripts\test.py');
    echo "Python is printing: " .  $python;
    ?>
    Ответ написан
    5 комментариев
  • Почему запросы к "Балабоба" возвращают 403? И как сделать правильно?

    deepblack
    @deepblack Куратор тега Python
    Выкидываем requests и используем urllib.request
    Рабочий вариант, python 3.8-3.9:

    import json
    import urllib.request
    
    headers = {
        'Content-Type': 'application/json',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_4) AppleWebKit/605.1.15 '
                      '(KHTML, like Gecko) Version/14.1.1 Safari/605.1.15',
        'Origin': 'https://yandex.ru',
        'Referer': 'https://yandex.ru/',
    }
    
    
    API_URL = 'https://zeapi.yandex.net/lab/api/yalm/text3'
    payload = {"query": "Ура Хабр", "intro": 0, "filter": 1}
    params = json.dumps(payload).encode('utf8')
    req = urllib.request.Request(API_URL, data=params, headers=headers)
    response = urllib.request.urlopen(req)
    print(response.read().decode('utf8'))
    Ответ написан
    6 комментариев
  • Как запустить 5000 потоков параллельно с GET запросами?

    Vamp
    @Vamp
    Распараллелить выполнение в самом воркере с помощью ReactPHP или лучше GuzzleAsync. В таком случае не придется держать 5000 воркеров именно

    Вариант с GuzzleAsync - самый лучший. Под капотом он использует возможности curl_multi_exec, которые позволяют асинхронно отправлять несколько запросов, не плодя при этом лишние процессы. Не уверен конечно, что осилит 5000 параллельных запросов, но даже если и не сможет, то можно разделить 5000 между несколькими воркерами.

    2. "Правильно ли" это вообще делать с помощью PHP или это все таки задача уже других языков которые умеют в параллельное выполнение, корутины? Go, NodeJs?

    У вас нагрузка в основном IO bound, так что не имет значения какой язык выбрать. Главное чтобы он поддерживал IO multiplexing (который поддерживается в PHP через вышеупомянутый curl_multi_exec).

    3. Может уже есть готовые решения в виде библиотек на PHP? Искал, но не нашел

    Guzzle
    Ответ написан
    3 комментария
  • Блокировка PHP flock создает последовательную очередь?

    @fomiash
    Согласно такому тесту:

    <?php
    // Файл /test/tester.php
    
    <?php
    @unlink("/test/document.txt");
    $processTime = 0.0001;
    for ($i = 1; $i <= 15; $i++) {
       $processTime *= 2;
       $time = $i === 1 ? 0 : $processTime;
       if ($i === 2) {
           sleep(2);
       }
       usleep($time * 1000000);
       passthru("php /test/subject.php $i $time >> /test/log_file.log 2>&1  &");
    }

    <?php
    // Файл /test/subject.php
    
    $processId = $argv[1];
    $processTime = $argv[2];
    
    $fp = fopen(__DIR__ . "/document.txt", "a+");
    flock($fp, LOCK_EX);
    if($processId == 1) {
        sleep(15);
        $processTime = 15;
    }
    fwrite($fp, $processId . ': ' . $processTime . ' sec.' . "\n");
    echo $processId . "\n";
    flock($fp, LOCK_UN);
    fclose($fp);

    в /test/document.txt оказался лог:

    1: 15 sec.
    3: 0.0008 sec.
    15: 3.2768 sec.
    5: 0.0032 sec.
    4: 0.0016 sec.
    12: 0.4096 sec.
    10: 0.1024 sec.
    7: 0.0128 sec.
    6: 0.0064 sec.
    8: 0.0256 sec.
    11: 0.2048 sec.
    13: 0.8192 sec.
    9: 0.0512 sec.
    14: 1.6384 sec.
    2: 0.0004 sec.


    в /test/log_file.txt

    1
    3
    15
    5
    4
    12
    10
    7
    6
    8
    11
    13
    9
    14
    2


    Очередность не соблюдена(
    Ответ написан
    Комментировать
  • Какие нюансы работы самозанятым?

    alexgp13
    @alexgp13
    Руководитель ИТ-проектов
    При устройстве самозанятым четко проговорите с работодателем:
    1. Отпуск - условия, оплату, и т.п.
    2. Больничные - сколько дней можно болеть без больничного, требуются ли вообще больничные, в каком размере оплачиваются
    3. Налоги (Вам должны перечислять дополнительные 6%, которые отдадите в налоговую)
    4. Так как работодатель не платит за Вас отчисления в пенсионный и т.п. фонды - он экономит примерно 30% от Вашей зарплаты. Обычно в такой схеме предлагают зарплату чуть-чуть выше рынка. Плохо ли это? Решайте сами.

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

    По поводу трудового кодекса и гарантий - могу рассказать немало историй про увольнение неугодных сотрудников одним днем. Из полностью белых компаний с официальным трудоустройством. И про отсутствие отпусков, и про отсутствие обещанных при трудоустройстве премий.

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

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

    @Stalinko Куратор тега Фриланс
    PHP'шник и фрилансер до мозга костей
    1. Самостоятельное ведение бухучёта, общение с налоговой, выписывание чеков.

    2. Отсутствие пенсии, налоговых вычетов, банки очень плохо дают кредиты

    3. Налоговая в курсе про эти схемы и пристально следит за ними. Если человек работал на компанию, а потом вдруг стал самозанятым с единственным клиентом - этой же компанией, то это красный флаг для налоговой, о том, что идёт подмена понятий. Нужно быть готовым к этому.
    Ответ написан
    13 комментариев
  • Как обработать возникшую ошибку в PHP скрипте загрузки страницы?

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

    Во-первых, очень хорошо что он сам по себе поставлен. Обычно пользователи РНР не задумываются о таких "мелочах". Но на самом деле об этом должен думать каждый программист, делающий сайты
    Во-вторых, здесь мы можем видеть довольно характерный баг Апача, который действительно, почему-то не выполняет директиву ErrorDocument для 500 ошибок, полученных от РНР. Ну и вообще, завязываться на Апач во времена доминирования Нжинкса как-то не очень дальновидно.
    В-третьих, как правильно заметил Stalker_RED, сделать редирект при 500 статусе (или 500 статус при редиректе) невозможно - статус может быть только один. Да это и нет смысла делать - проще сразу на месте нужную страницу и прочитать.
    В-четвертых, текущий подход, прямо скажем, не очень оптимальный:
    - о роботах мы позаботились, о пользователе позаботились, но надо ещё не забыть и программиста. Которому как раз сообщение об ошибке-то нужно видеть во всех подробностях!
    - просто отдать нужный НТТР код недостаточно - надо бы ещё и завершить работу скрипта.
    - ловить все ошибки вручную через try-catch так себе удовольствие. И код раздувает,и поведение потом быстро не поменяешь. А если в какой-то момент захочется для отладки прикрутить whoops - это придётся по всем блокам бегать?

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

    В самом простом варианте это будет что-то вроде такого:

    set_exception_handler(function ($e)
    {
        error_log($e);
        http_response_code(500);
        if (ini_get('display_errors')) {
            echo $e;
        } else {
            include 'pages/error_500.php';
        }
    });

    В теории, конечно, можно заменить error handler на глобальный try-catch который оборачивает точку входа, но это менее удобно. Тем более, что для обработки фатальных ошибок нужен свой отдельный обработчик, и в итоге код обработки ошибок начинает занимать довольно значительный объем и лучше конечно его инициализацию вынести отдельно.
    Ответ написан
    Комментировать