Ответы пользователя по тегу PHP
  • Кто-нибудь из уважаемого сообщества понял зачем нужны Файберы появившиеся в 8.1?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Простым языком волокна придуманы для упрощения параллельных взаимных блокировок.
    Например у вас есть сложный параллельный многошаговый алгоритм, у которого параллельные ветви работают с некоторым расшаренным объектом, например куском памяти или файлом.

    Вот тут почитайте, сразу прояснится.

    https://wiki.php.net/rfc/fibers
    https://clue.engineering/2021/fibers-in-php
    https://ruby-doc.org/core-2.5.0/Fiber.html

    Из-за того, что в PHP нет полноценной системной асинхронности и мультипоточности, появяются вот такие городушки, но все равно надо использовать какой-то планировщик вроде Amp.
    В общем, это первые шаги на пути к полноценной асинхронности в PHP.
    Ответ написан
    Комментировать
  • Стоит ли учить php в 2021 году для разработки web приложений и сайтов?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Для Web-приложений не очень. Для сайтов очень даже.

    Почему для Web-приложений не очень: чаще всего они требуют сложных пользовательских интерфейсов. А это JavaScript, скорее даже TypeScript. Если у вас в команде Fullstack разработчики, то добавление каждого нового языка программирования усложняет разработку. В целом Typescript ничем не уступает PHP. ООП и т.д., строгая типизация, это все имеется. Да, в некоторых случаях он медленнее и разработка на нем несколько сложнее. Но это уже зависит от кривизны ваших рук.

    В общем и целом зависит от того, чем вы хотите заниматься в дальнейшем. Хотите пилить Битрикс и клепать веб-магазинчики - тогда PHP.
    Хотите заниматься разрботкой веб-приложений, тогда Typescript/Javascript. Опять же React Native никто не отменял. В любом случае вам прийдется учить Javascript, т.к. фронт весь сделан на нем. Так почему бы не начать с него?

    Как начинающему, я бы советовал вам учить языки примерно в такой последовательности Javascript, Typescript, PHP, Python, Rust или Go.
    Ответ написан
  • Как сгенерировать изображение 3D кубиков (игральных костей) на стороне сервера?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    У вас есть 2 пути: сделать рендеринг в браузере, но генерировать данные на сервере, либо сделать рендеринг на сервере.
    При выбросе костей на самом деле имеет значение лишь то, что на верхних гранях, а остальное по большому счету не важно. Данных вам нужно немного, по сути массив с выпавшими костяшками.
    На мой взгляд, логичнее всего произвести рендеринг на клиенте с использованием Three.js. Благо нарисовать кубик с разными гранями задача элементарная. В threejs вы можете начать с простых кубиков, а потом нарисовать хорошую модель с материалами в Fusion 360, экспортировать в STL, загрузить модель в Three.js и анимированно разместить ее в пространстве.
    Так или иначе вы прийдете к тому, что вам захочется иметь красочный результат. Такой результат возможен лишь при наличии контроля освещения и материалов поверхностей. Т.е. нужна работа OpenGL или иного графического движка. Это можно делать на PHP https://github.com/Ponup/php-opengl Вопрос лишь в накладных ресурсах.
    Если вам не нужно делать статическую одинаковую картинку, которая будет потом отправляться по почте, то нет смысла делать рендеринг на сервере.
    Ответ написан
    1 комментарий
  • Трюк с тернарным оператором PHP?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Просто выбрасывать исключение нужно внутри метода check() и переименовать его в assert(). Тогда все станет на свои места.
    Ответ написан
  • Какой набор пакетов использовать, чтобы реализовать простой веб-сайт?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Для того, чтобы создать простой веб-сайт, вам не нужен PHP.
    Возьмите старый добрый HTML и сделайте 2-3 странички в редакторе. Готово.
    Ответ написан
    7 комментариев
  • Как правильно организовать структуру фабрики логгера?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Это один из примеров ситуации, когда использование синглтона может быть частично оправдано.

    class LoggerFactory {
      static $instance = null;
      public static create() {
        if (!is_null(static::$instance)) {
          return static::$instance;
        }
         static::$instance = new Logger('name');
         // ну т.д.
         return static::$instance;  
     }
    }
    
    // используется вроде бы так
    $logger = LoggerFactory::create();


    Код я не проверял, но идея примерно такая.
    Ответ написан
    Комментировать
  • Как данное реализуется?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Реализуется достаточно просто.
    У вас один nodejs процесс слушает TCP порт 80. Браузер может создавать множество соединений с сервером, как короткоживущих, вроде GET/POST, так и долговременных, как WebSockets.
    Websockets используют механизм апгрейда соединения, суть которого заключается в изменении самого протокола верхнего уровня при установлении TCP соединения. Простыми словами, сначала веб-сокеты цепляются по обычному HTTP, потом шлют заголовки Upgrade: WebSocket и Connection: Upgrade, после чего штаны (http) превращаются в элегантные брюки (websockets).
    Поэтому один и тот же сервер может обслуживать и веб-сокеты и http. На этом заканчивается магия одновременных соединений со стороны браузере с одним и тем же сервером по разным протоколам. Дальше начинается магия того, как передаются данные с одного протокола (http) в веб-сокет.
    Поскольку чат работает внутри одного процесса (это я нарочно упрощаю), то у процесса есть разделяемый обработчик событий. Через него сообщения пересылаются между обработчиками разных протоколов.

    В коде очень упрощенно это выглядит так:
    // импортируем зависимости
    
    import app from 'express';
    import { createServer } from 'http';
    import socketio from 'socket.io';
    
    // наш http сервер
    const app = express();
    const http = createServer(app);
    
    // наш websocket сервер
    const io = socketio(http);
    
    // глобальная шина сообщений
    const messageBus = new EventEmitter();
    
    // так мы получаем сообщение по http
    app.get('/message', (req, res) => {
    	console.log('http message:', req.params);
    	// и пихаем его дальше по шине сообщений
    	messageBus.emit('message', req.params);
    })
    
    // когда установлено соединение, 
    // мы можем настроить подписку на сообщения
    io.on('connection', (socket) => {
    	// соединение установлено!
    	console.log('Connected!');
    
    	// так мы подписываемся на сообщение
    	// приходящее через вебсокеты
    	socket.on('message', (message) => {
    		console.log('websockets message:', message);
    		// и шлем его дальше по шине сообщений
    		messageBus.emit('message', message);
    	});
    
    	// теперь мы подписываемся на любые сообщения
    	// вне зависимости от того, откуда они были получены,
    	// и пересылаем их всем через вебсокеты
    	messageBus.on('message', (message) => {
    		io.emit('message', message);
    	});
    
    });
    
    // слушаем по http порт 3000
    http.listen(3000, () => {
      console.log('запустились на порту 3000');
    });


    В реальной жизни вместо разделяемого объекта EventEmitter используется реальная шина сообщений на основе Redis Pub/Sub или очередей, вроде RabbitMQ. Такие штуки делаются для очень больших чатов, способных держать десятки и сотни тысяч человек онлайн. Например чаты в масштабах Youtube, Twitch и т.д.
    Для небольших чатов до несколько десятков тысяч пользователей вполне достаточно одного хорошо написанного сервера на Go.
    Nodejs не подходит для высоконагруженных проектов ввиду очевидно высокого уровня потребления ресурсов.
    Ответ написан
    4 комментария
  • Как сделать limit_req_zone для api token?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Ответ написан
    Комментировать
  • Почему меняется кодировка при загрузке файла?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Вам нужно использовать application/octet-stream и напрочь убрать charset.
    Тут хороший пример заголовков https://www.php.net/manual/ru/function.readfile.php
    Ответ написан
    Комментировать
  • Этот код сильно ужасен)?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Ну что же, начнём? Только не плакать потом, сами попросили.

    Итак, начнем с архитектуры. Начнем с того, что код чем только не занимается, он и из консоли запускает и как веб-хук и т.д. Сам по себе он является куском битрикса в том или ином виде.
    Далее - код использует ООП, но написан в процедурном стиле.

    Уже за это надо проявлять насилие над личностью.

    <?php
    include "bitrix.php";
    include "function.php";
    require_once  '../src/db.php';


    Просто используйте require_once.

    use должен быть вверху файла.

    $id = $_GET['id'];
    Будет генерировать ошибки, если скрипт был вызван без id.

    $select = $db->query("SELECT * FROM tg_bot WHERE  tg_bot.id='$id'");

    Добро пожаловать в мир SQL-инъекций.

    $bot_token = $select[0]['api_key'];
    Что произойдет, если бот не существует? Ошибки.

    define('BOT_TOKEN', "$bot_token");
    Бить железной линейкой по пальцам. Сильно. Больно. Долго.

    Нельзя использовать переменные внутри define. Эта инструкция придумана для объявления констант. Объявлять константы используя переменные недопустимо.

    if (php_sapi_name() == 'cli') {
        apiRequest('setWebhook', array('url' => isset($argv[1]) && $argv[1] == 'delete' ? '' : WEBHOOK_URL));
        exit;
    }

    Жуть какая-то.

    $content = file_get_contents("php://input");
    $update = json_decode($content, true);
    
    if (!$update) {
        exit;
    }

    Я так понимаю, что здесь происходит вызов самого веб-хука.

    Ну а дальше просто идет месиво. Смешались в кучу кони, люди...

    Что с этим можно сделать?

    Вызубрить ООП и getjump.github.io/ru-php-the-right-way

    Вспомните принцип "Разделяй и властвуй".
    Разделяйте код по функционалу и уровням абстрации.
    Например разделите код на работу с базой, на работу с API, на бизнес-логику.

    Например ваш код мог бы выглядеть так:

    // добавляем автозагрузку классов
    require_once 'vendor/autoload.php';
    // импортируем конфигурацию
    require_once 'config.php';
    
    use Chaly/Bot;
    
    // проверяем, что наш скрипт вызван с индентификтором бота
    if (!isset($_GET['id'])) {
      exit(1); // ненулевой статус говорит об ошибке
    }
    
    // загрузить робота из базы данных
    $bot = Bot::loadById($_GET['id']);
    if (!$bot) {
      exit(1);
    }
    
    // запустить робота
    $bot->run();


    Как может выглядеть тело run()

    public function run() {
      if (Cli::isValid()) {
        switch (Cli::getCommand()) {
            case 'delete':
                $this->delete();
                break;
            case 'register':
                $this->register();
                break;
        }
        return;
      }
    
      $payload = $this->getWebHookPayload();
      if (!$payload) {
        return;
      }
    
      if (isset($payload['message'])) {
        $this->interpretMessage($payload['message']);
      }
    
      // и так далее, думаю смысл понятен
    }
    Ответ написан
    3 комментария
  • Есть ли реализации packagist (composer-сервера) на PHP?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Боюсь Artifactory вам наверно не очень подойдет.

    Еще можно вот так делать, но это для локального кода
    {
      "autoload": {
        "psr-4": { "NameSpace\\": "src/NameSpace" }
      }
    }
    Ответ написан
    1 комментарий
  • Есть ли библиотеки для PHP (может даже PECL) для работы со звуком (подключиться к PulseAudio)?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    1. Изучаем PulseAudio, особенно D-Bus.
    https://gavv.github.io/articles/pulseaudio-under-t...

    2. Управляем всем через D-Bus
    https://github.com/derickr/pecl-dbus

    Также можно почитать про самописные расширения на PHP и сделать свое для воспроизведения опираясь на этот пример https://freedesktop.org/software/pulseaudio/doxyge...

    Альтернативный подход - управлять другой программой через какой-нибудь IPC.
    Например https://milesalan.com/notes/mplayers-fifo/
    https://github.com/TheJosh/mplayer-web-remote/blob...
    Ответ написан
    2 комментария
  • Как реализовать отчёт по продажам с меняющейся иерархией?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Как специалист по Монге скажу - Монга тут ненужна.

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

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

    Кстати, ничего не мешает вам делать снапшоты для Nested Sets и хранить их в отдельной таблице в виде леса деревьев.
    Ответ написан
    Комментировать
  • Как реализовать постоянную взаимосвязь ajax+php не перегружая сервер?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Пора перестать заниматься херней и открыть для себя Server Sent Events или человеческую работу с веб-сокетами.
    А лучше использовать что-нибудь такое https://github.com/wandenberg/nginx-push-stream-module
    Ответ написан
    Комментировать
  • Как получить уже подключенный websocket из другого файла?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    <?php
    require_once __DIR__ . '/vendor/autoload.php';
    use Workerman\Worker;
    
    // Create a Websocket server
    $ws_worker = new Worker("websocket://0.0.0.0:2346");
    
    // 4 processes
    $ws_worker->count = 4;
    
    // Emitted when new connection come
    $ws_worker->onConnect = function($connection)
    {
        echo "New connection\n";
        $connection->send('Have you tried to read the manual?');
     };
    
    // Emitted when data received
    $ws_worker->onMessage = function($connection, $data)
    {
        // Send hello $data
        $connection->send('hello ' . $data);
    };
    
    // Emitted when connection closed
    $ws_worker->onClose = function($connection)
    {
        echo "Connection closed\n";
    };
    
    // Run worker
    Worker::runAll();
    Ответ написан
    Комментировать
  • Как составить правильный запрос на получение информации из инстаграм через фейсбук?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Этот метод работает только для страниц. Поддержка персональных аккаунтов из Instagram отсутствует на данный момент.

    Пожалуйста, прочитайте это https://developers.facebook.com/blog/post/2018/01/...

    Смысл в том, что Facebook постепенно закручивает гайки для доступа к персональным данным со стороны приложений.
    На мой взгляд, приложениям нужен доступ только к следующим персональным данным - ФИ, полу, почте, аватарке и признаку совершеннолетия.
    Я понимаю, что всяким музыкальным приложениям вроде Spotify неплохо бы иметь более глубокую интеграцию, например, начал фолловить артиста в Spotify, автоматически подписался на страницу в Фейсбук. На мой взгляд это удобно, но некоторым это может не понравиться.
    Ответ написан
  • PHP. Как спарсить видео (или live видео) из профиля пользователя Facebook?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    PHP SDK нужно для работы с Graph API.
    Список видео доступен через это API https://developers.facebook.com/docs/graph-api/ref...
    Для доступа потребуется запрашивать разрешение user_videosб для которого нужно будет пройти ревью.
    Ответ написан
    Комментировать
  • Асинхронные методы в php?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Можете еще на это посмотреть https://github.com/amphp/
    Там много интересных проектов так или иначе связанных с асинхронностью.
    Ответ написан
    Комментировать
  • Регистрация facebook?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    1. Scope указан неверно. https://developers.facebook.com/docs/facebook-logi...

    2. Если пользователь регистрируется с телефона, то email у него скорее всего отсутствует.
    Ответ написан
    3 комментария