Ответы пользователя по тегу PHP
  • Оптимальный способ автоматической модификации исходного кода?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Я бы сделал версию проекта, которую можно считать шаблонной.
    Все места где BrandName заменил бы на уникальный placeholder на подобии TEMPLATE_BRAND_NAME
    Далее замену исходного кода в файлах можно делать любой консольной утилитой типа sed при деплое или при необходимости.

    sed -i -- 's/foo/bar/g' *

    find . -type f -exec sed -i 's/foo/bar/g' {} +

    То есть делаете основной модуль как обычно, и делаете билды под нужный бренд, в котором при сборке производится замена placeholder'ов на нужные строки.
    Ответ написан
    Комментировать
  • Как сделать выборку и обработать данные пачками?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Единственные лимит это хранение выбранных данных в памяти скрипта во время работы.
    Данные можно доставать по частям, аналогично тому как делается пагинация на любом сайте.
    Например, если в таблице есть поле id (autoincrement), то можно выбирать данные порциями с условием типа id > XXXXX
    Дополнительно прикрутить last_check тоже можно, если это требует логика приложения.

    Пример кода ниже, для понимания логики. Вместо mysqli можно использовать pdo или что угодно
    <?php
    //$db = new mysqli(); //соединение с БД
    
    $min_id = 0;
    $LIMIT = 1000;
    
    //в цикле идём от id = 0 до id = "самый максимальный", выбирая по 1000 записей за раз.
    while(true)
    {
        $result = $db->query("SELECT * FROM `table` WHERE `id` > '{$min_id}' LIMIT {$LIMIT}");
    
        //если записей больше не найдено прерываем цикл
        if($result->num_rows == 0)
        {
            break;
        }
        
        while($row = $result->fetch_assoc())
        {
             //обрабатываем данные производим манипуляции
    
            //сохраняем последний обработанный id
            $min_id = $row['id'];
        }
    }
    Ответ написан
    Комментировать
  • Как получить данные методом file_get_contents чужого сайта с другого ip?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Через выбранный internal-интерфейс
    <?php
    $opts = array(
        'socket' => array(
            'bindto' => '10.10.1.1:0',
        )
    );
    
    $context = stream_context_create($opts);
    $file = file_get_contents("https://site.com/", false, $context);


    http-прокси с авторизацией
    <?php
    $auth = base64_encode('LOGIN:PASSWORD');
    
    $aContext = array(
        'http' => array(
            'proxy' => 'tcp://192.168.0.2:3128',
            'request_fulluri' => true,
            'header' => "Proxy-Authorization: Basic $auth",
        ),
    );
    $cxContext = stream_context_create($aContext);
    
    $sFile = file_get_contents("http://www.google.com", False, $cxContext);
    
    echo $sFile;


    Материалы для изучения
    https://www.php.net/manual/en/context.php
    https://www.php.net/manual/en/ref.stream.php
    Ответ написан
    Комментировать
  • Как правильно сравнивать многобайтовые строки с однобайтовыми?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Если в файле строки однобайтовые (cp1251, win-1251) то конвертируйте их в UTF-8 через iconv

    $strUtf = iconv('CP1251', 'UTF-8', $str_from_file);


    Далее так как все строки utf8 уже можете сравнивать строки как обычно if($str1 == $str2) - с учётом регистра или прогонять через mb_strtoupper() / mb_strtolower() чтобы сравнивать без учёта регистра.
    if(mb_strtoupper($str1) == mb_strtoupper($str2))
    Ответ написан
  • Как сделать в php парсере выдачу данных построчно?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    elisee84.bget.ru/parser.php - результаты итак выдаются построчно разделённые \n
    Вы просто этого не видите в браузере. Чтобы убедиться что данные построчно, откройте исходный код страницы Ctrl+U и узрите истину
    5e7922cd2244e608826904.png

    Если хотите прям в браузере увидеть данные построчно то пишите
    echo nl2br($String);
    Ответ написан
    1 комментарий
  • Браузер виснет при выполнении скрипта. почему?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Это продолжение вопроса Не может больше внести txt чем 3 мб. почему?

    Правильный ответ - не запускать долгоиграющие скрипты через браузер, а запускайте их через консоль (синонимы: CLI, командная строка)

    1. https://www.php.net/manual/ru/features.commandline...
    2. https://hackware.ru/?p=8454

    Не правильный ответ - увеличить/отключить таймаут на работу скрипта
    <?php
    ignore_user_abort(true);
    set_time_limit(0);

    Этот метод может не сработать, так как тут ещё играет роль настройки веб-сервера.

    Настоятельно рекомендую всё же осилить тему запуска скриптов через командную строку.

    p.s. если используете php-fpm то как вариант есть ещё fastcgi_finish_request() которая позволит оставить работающий процесс в фоне и закрыть соединение с клиентом
    https://ruhighload.com/Асинхронность+в+php+и+fpm
    https://www.php.net/fastcgi_finish_request

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

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Через PHP - никак, так как браузер не передаёт такую информацию на сервер.

    Через javascipt можно
    if (window.screen.width < 1300) {
    }


    То есть можно на странице запустить javascript, который считает ширину экрана и сделает http-запрос на сервер (ajax) сообщив какая ширина в браузере сейчас.
    Эти данные можно сохранить в сессию и использовать в дальнейшем уже в РНР скриптах
    Так же можно считать ширину и сохранить её в cookies. Из РНР считать значение $_COOKIE при последующих запросах.

    Но в любом случае всё это методы которые требуют минимум два этапа чтобы получить данные о браузере - на серверной стороне.
    Если же задача звучит как "пользователь открывает страницу в первый раз и мы уже должны знать размер экрана в РНР" - то ответ никак.

    p.s. для мобильных устройств есть различные базы например WURFL которые могут по user agent определить модель телефона/планшета, и исходя из этого сказать какая ширина экрана у девайса по его спецификациям.
    Ответ написан
    Комментировать
  • Как разбить список на блоки?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Если $all_users->response->profiles это массив профилей, то можно разбить массив на части функцией array_chunk()
    https://www.php.net/manual/ru/function.array-chunk.php

    <?php
    $parts = array_chunk($all_users->response->profiles, 100);
    print_r($parts);
    Ответ написан
    Комментировать
  • Где найти хорошую библиотеку для работы с Instagram API?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    https://github.com/postaddictme/instagram-php-scraper
    Это указанная в вопросе либа, отлично справляется с поставленой задачей. Это по сути парсер веб версии инстаграма.
    Авторизация не нужна, если парсите публичные профили, только нужно будет пачку приватных проксей, в идеале резидентные прокси.
    Если будете парсить приватные профили, тогда конечно нужно авторизоваться.
    Ответ написан
  • Не может больше внести txt чем 3 мб. почему?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Тут скорее проблема в том что скрипту не хватает памяти чтобы вместить все $collectuids, так как никаких ограничений на выгрузку groups.getMembers vk не накладывает, и я без проблем выгружал списки участников сообществ по 1млн+ участников.

    Быстрый хак - увеличить скрипту памяти при выполнении, а так же включить отображение ошибок
    <?php
    ini_set('display_errors', 1);
    error_reporting(-1);
    
    ini_set('memory_limit', '512M'); //512Mb
    
    //тут ваш код


    p.s. так же если скрипт запускается не через CLI, а через браузер, то он может вылетать просто по таймауту соединения.
    Ответ написан
    Комментировать
  • Как переписать код?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    <?php
    // Guestbook, Гостевая книга
    
    if (!is_dir("messages")) {
    mkdir("messages");
    };
    
    function postMessages() {
    foreach (glob('messages/*.txt') as $message) {
    $message = file($message);
    echo str_replace("\n", "", $message[0]) . "<br/>";
    echo str_replace("\n", "", "<a href='mailto:$message[1]'>$message[1]</a>") . "<br/>";
    for ($i = 2; $i < sizeof($message); $i++) {
    echo htmlspecialchars($message[$i]) . "<br/>";
    };
    echo "<br/>";
    };
    };
    
    $messages = scandir("messages");
    
    if (!$_POST) {
    postMessages();
    //a:
    print_form();
    } else {
    if (filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) !== false && $_POST['author'] && $_POST['email'] && $_POST['message']) {
    $author = str_replace("\r\n", "", $_POST['author']);
    $email = str_replace("\r\n", "", $_POST['email']);
    $msg = $_POST['message'];
    $time = (int)(microtime(true) * 1000000);
    file_put_contents("messages/$time.txt", "$author
    $email
    $msg");
    } else {
    echo 'Error while adding your message.';
    //goto a;
    print_form();
    };
    postMessages();
    //goto a;
    print_form();
    };
    
    function print_form()
    {
        echo
        '<form action="index.php" method="post">
        <p><input type="text" name="author" required /></p>
        <p><input type="text" name="email" required /></p>
        <p><textarea name="message" required></textarea></p>
        <p><input type="submit" /></p>
        </form>';
    }
    ?>
    Ответ написан
  • Почему ничего не происходит каксделать чтоб что-то происходило?

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

    <?php
    function myChown($fname, $attr) {
            if (PHP_OS == "UNIX") {
                // Функция-заглушка
                // Ничего не делает
                 return 1;
            } else {
                  return chown($fname, $attr);
            }
        }
    Ответ написан
    Комментировать
  • Сертификат по ГОСТ-2012?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    openssl вполне подходит для этих целей

    статья с подробным разбором и докер образами
    https://habr.com/ru/post/353534/

    Пару ссылок для общего ознакомления с болью
    https://www.cryptopro.ru/forum2/default.aspx?g=pos...
    http://wiki.rosalab.ru/ru/index.php/OpenSSL_и_ГОСТ
    Ответ написан
    Комментировать
  • Как перебирать такие массивы/объекты?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Это не массивы. Для работы со строками столбцами и данными нужно использовать специальные методы (гетеры и тд) которые предоставляет данная бибилотека.

    К сожалению Вам придётся всё-таки изучить документацию
    https://phpspreadsheet.readthedocs.io/en/latest/

    а так же можно ознакомится с примерами кода тут
    https://github.com/PHPOffice/PhpSpreadsheet/tree/m...

    Получить данные из ячейки или строки
    https://phpspreadsheet.readthedocs.io/en/latest/to...
    Ответ написан
    Комментировать
  • Как найти ссылку в тексте с якорем (#anchor)?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Есть даже целый сайт с регулярками по матчингу url для разных ЯП - https://urlregex.com/

    %^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}|(?:(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)*(?:\.[a-z\x{00a1}-\x{ffff}]{2,6}))(?::\d+)?(?:[^\s]*)?$%iu


    <?php
    $str = 'Здесь ссылка должна быть в теге <a> https://example.ru/ru/task#348141 конец текста';
    
    $re = '%(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}'.
    '|(?:(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)'.
    '(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)'.
    '*(?:\.[a-z\x{00a1}-\x{ffff}]{2,6}))(?::\d+)?(?:[^\s]*)?%usi';
    
    $result = preg_replace($re, '<a href="$0" target="_blank">$0</a>', $str);
    
    var_dump($result);
    
    //string(167) "Здесь ссылка должна быть в теге <a> <a href="https://example.ru/ru/task#348141" target="_blank">https://example.ru/ru/task#348141</a> конец текста"
    Ответ написан
    4 комментария
  • Сбилась кодировка у страницы, как исправить?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    whatislov, хочу заметить, что на скриншоте редактируемого файла и скриншоте страницы всё в порядке с кодировкой и отображением.
    Вы редактируете текст с места "... инвестиционный проект и тд" и он нормально тображается.

    А проблемы с кодировкой в верхнем меню, которое, видимо и нужно отредактировать отдельно.
    Ответ написан
    Комментировать
  • Не может раскодировать символ?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    HellFingers,
    echo mb_substr($string, 0, 1);
    Ответ написан
    Комментировать
  • Как php повторно узнает о файлах в каталоге: из памяти или читает все занова?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    1. путь до файла (куда пишете) у вас в $path, а вы проверяете $name, что не верно
    2. проверку на существование делаете после curl, а значит даже если в файл не пишете, то всё-равно делаете http запрос что не имеет смысла

    Подправленный вариант
    <?php
    foreach($data as $k)
    {
        foreach($k as $kq => $v)
        {
            foreach(($v["photo_list"]) as $key => $url)
            {
                $name = (basename($url));
                $path = "/".$name;
                
                //если файл существует идём к следующему $url
                if(file_exists($path))
                {                
                    continue;
                }
    
                //скачиваем
                $ch = curl_init($url);
                curl_setopt($ch, CURLOPT_HTTPHEADER, 0);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                $data = curl_exec($ch);
                curl_close($ch);
                
                //записываем
                $file = fopen($path, "w+");
                fwrite($file, $data);
                fclose($file);
            }
        }
    }
    Ответ написан
  • Как оптимизировать выборку из Mysql?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    И за какое время у вас отрабатывает 10000 SELECT'ов? Индекc на uid есть + LIMIT 1?

    10тыс SELECT'ов на таблице в 300тыс строк, при условии что на uid есть индекс должно выполняться за 1-2 секунды на нормальной машине.
    Не вижу необходимости что-либо оптимизировать.
    Можно разве что минимизировать кол-во данных передаваемых по сети и вместо SELECT * использовать SELECT type, lvl, country, isoc так как лишние данные, это лишние задержки.

    БД создана для того чтобы работать, нет смысла её жалеть.

    - Другой вариант, если позволяет память - выбирать все строки из базы одним SELECT'ом и потом фильтровать в приложении.
    - Можно прикрутить memсached для кеширования так как по сути у вас key-value выборка
    - Выбрать другое хранилище (Redis, tarantool) где скорость выборки по ключу будет выше

    upd. Можно несколько SELECT'ов группировать в один запрос через IN
    SELECT ... FROM table WHERE uid IN(uid1, uid2, uidN)

    Этим можно уменьшить суммарное кол-во SELECT'ов, но не факт что в итоге данные получите быстрее.
    Ответ написан
    4 комментария
  • В чем ошибка при обходе дерева?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Проблема в том что если в самой функции делаете echo да ещё и рекурсию, то не нужно результат работы функции помешать внутрь другого echo так как в таком случае сперва отрабатывает функция, и делает echo, а потом уже отрабатывает внешнее echo.

    Чтобы избежать этого, и вставлять функцию как вы хотите, нужно изменить код функции так чтобы вместо echo там был return;

    Исправленный код с echo.
    <?php
    function draw($array)
    {
        foreach($array as $item)
        {
            if(isset($item['CHILD']))
            {
                echo '<li>'.$item['NAME'].'<ul>';
                draw($item['CHILD']);
                echo '</ul></li>';
            }
            else
            {
                echo '<li>'.$item['NAME'].'</li>';
            }
        }
    }
    
    $arr = [
        'CHILD' => [
            '16' => [
                'NAME'  => '1',
                'CHILD' => [
                    '17' => [
                            'NAME' => 'a'
                    ],
    
                    '18' => [
                            'NAME' => 'b'
                    ]
                ]
            ]
        ]
    ];
    
    echo '<ul>';
    draw($arr['CHILD']);
    echo '</ul>';
    Ответ написан
    1 комментарий