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

    Vamp
    @Vamp
    Практический смысл видится мне только один - избежание проблем в случае появления в будущем в неймспейсе Foo\Bar функции, совпадающей по имени со стандартной.

    Но вероятнее всего это просто принятый в проекте стиль написания кода.
    Ответ написан
  • Что нужно вернуть при вызове сервиса методом OPTIONS?

    Vamp
    @Vamp
    Список поддерживаемых методов обычно передается через http заголовок Allow. Этот заголовок допускается возвращать в ответ на метод OPTIONS.
    HTTP/1.1 200 OK
    Allow: OPTIONS, GET, HEAD, POST
    Cache-Control: max-age=604800
    Date: Thu, 13 Oct 2016 11:45:00 GMT
    Expires: Thu, 20 Oct 2016 11:45:00 GMT
    Server: nginx
    Content-Length: 0


    По default планирую возвращать, что метод не поддерживается.

    Если вы планируете возвращать эту ошибку используя http код 405, то наличие заголовка Allow со списком поддерживаемых методов обязательно. Это требование RFC7231.
    Ответ написан
    Комментировать
  • PHP-DI и контроллеры. Как избежать повтора кода?

    Vamp
    @Vamp
    Если аргументы конструктора у контроллеров помечены type hint'ами, то контроллеры необязательно регистрировать в контейнере. Можно создавать их напрямую по имени класса:

    $controller3 = $container->get('project\Controllers\Controller3');

    Здесь используется фича autowiring, которая по умолчанию включена. PHP-DI смотрит при помощи рефлексии какие типы требует конструктор контроллера и подставляет соответствующие сервисы, зарегистрированные в контейнере.
    Ответ написан
    1 комментарий
  • Как средствами PHP нарисовать дугу для SVG файла?

    Vamp
    @Vamp
    Проще всего нарисовать дугу через элемент path.

    $image = new SVG('100mm','100mm');
    $doc = $image->getDocument();
    $square = new SVGLine('0mm', '0mm', '55mm', '55mm'); // x0 y0 x1 y1
    $square->setStyle('stroke', '#FF0000'); //цвет
    $doc->addChild($square);
    
    $arc = new SVGPath('m 40,40 A 30,30,0,0,1,150,150');
    $arc->setStyle('stroke', '#FF0000');
    $doc->addChild($arc);
    
    header('Content-Type: image/svg+xml');
    echo $image;


    Нужно немного изучить формат path. Он не сложный.

    m 40,40 A 30,30,0,0,1,150,150

    m - это команда move. Устанавливает "кисть" в указанную позицию. Далее команда A - arc (дуга). Её формат несколько сложнее:

    30,30 - радиус дуги по осям x и y
    0 - угол поворота дуги вокруг оси x
    0 - должна ли дуга быть больше 180 градусов или нет
    1 - в какую сторону рисовать дугу - по часовой или против
    150,150 - координаты конца дуги
    Ответ написан
    2 комментария
  • Как проверить какая ошибка в $_FILES?

    Vamp
    @Vamp
    Согласно официальной документации, превышение post_max_size можно отследить только добавив get параметр к форме:
    <form action="edit.php?processed=1">

    if (!empty($_GET['processed']) && empty($_POST) && empty($_FILES)) {
        echo 'Ошибка! Вы загрузили слишком большой файл';
    }
    Ответ написан
  • Php Comet + Sokil\Mongo, почему class '\MongoCollection' not found, хотя mongodb на php поставлен?

    Vamp
    @Vamp
    Необходимо установить расширение mongodb для самого PHP и дополнительную библиотеку alcaeus/mongo-php-adapter.
    Ответ написан
  • Как реализовать "защиту" авторизации по номеру телефона?

    Vamp
    @Vamp
    1. Проверьте синтаксическую корректность номера телефона. Все мобильные номера в РФ начинаются на +79 и имеют длину ровно 11 цифр. Проверку можно даже добавить в веб форму на уровне js. Это нельзя назвать защитой от хулиганов, но она отсеет реальные ошибки и опечатки, облегчив жизнь обычным пользователям.

    2. Пробейте номер по базе россвязи (файл DEF-9xx). Так вы определите номера, на которые 100% не будет доставки. В отличии от проверки синтаксиса, не выдавайте пользователю ответ о некорректном номере. На все номера отвечайте "Одноразовый код отправлен, введите его сюда", но на невалидные номера не отправляйте сообщение.

    3. Добавьте ограничение на количество отправляемых форм в минуту с одного IP и количество отправляемых сообщений на один и тот же номер (независимо от IP).

    4. Оцените сколько может быть отправок форм в день и поставьте общий лимит на все отправки смс за день. Это единственный реальный способ контролировать атаку на сливание бюджета. Да, реальные пользователи пострадают при достижении лимита, но вы не должны доводить до него - настройте мониторинг количества отправляемых смс и алертинг при достижении порога в 90% от лимита, чтобы у вас было время среагировать на атаку и отбить её до полного исчерпания лимита. Либо если это всплеск реальных пользователей (например, неожиданно удачная реакция на рекламу), то у вас будет время скорректировать лимит. Можно рассчитывать лимит как 2 * среднее количество отправок смс за последние Х дней, чтобы не приходилось править его вручную по мере естественного роста посещаемости. Формулу и процент для алертинга, разумеется, подберёте под свои требования. Но можете взять и мои за основу.

    Отдельно хочу рассказать про так называемые прямые мобильные номера. Они выглядят как городские (например, +7495), но в реальности являются мобильными и могут принимать смски. Проверка в пункте 1 не пропускает такие номера и нет никакого способа проверить без отправки смс является ли отдельно взятый городской номер прямым мобильным. Прямых номеров мало по сравнению с настоящими мобильными или настоящими городскими. К тому же у каждого прямого номера есть мобильный аналог, начинающийся на +79, которым пользователь может воспользоваться для регистрации. Поэтому предлагаю просто забить на прямые номера, а в случае жалоб на невозможность регистрации с прямым номером, рассказывать про существование мобильного аналога, который может быть прописан где-то в договоре с оператором на оказание услуг связи или узнать в техподдержке оператора и с которым можно спокойно зарегистрироваться.

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

    Альтернативным вариантом является аренда входящего номера. В этом случае не вы отправляете сообщения пользователям, а они вам. Обычно за входящий номер берут фиксированную плату в месяц независимо от количества смс, так что не придётся в принципе волноваться за бюджет. Но тогда у вас будут в пролёте пользователи с отключенной услугой отправки смс. А таких немало, могу сказать. Благодаря интернет-мессенджерам.
    Ответ написан
    2 комментария
  • Запуск крон. Доступ запрещен?

    Vamp
    @Vamp
    Вам нужно явным образом вызвать интерпретатор php и передавать ему путь к скрипту:
    cd /var/www/no-name/data/www/oushd.ru/core/channels/channels/ && php /var/www/no-name/data/www/oushd.ru/core/channels/channels/test.php
    
    cd /var/www/no-name/data/www/oushd.ru/core/channels/channels/ && php /var/www/no-name/data/www/oushd.ru/core/channels/channels/channels.php
    Ответ написан
    1 комментарий
  • Какой подход для валидатора правильней?

    Vamp
    @Vamp
    Архитектурно правильнее возвращать как в примере с Yii2. Использование исключений для управления потоком выполнения программы считается серьёзным антипаттерном.

    Например:
    1. Исключения в данном случае - просто более хитрая замена оператору GOTO. Надеюсь, не нужно объяснять почему GOTO тоже считается антипаттерном?
    2. Программы, написанные в таком стиле, становится сложно читать и понимать.
    3. Меньшая эффективность в рантайме, так как большинство современных компиляторов не оптимизированы для случаев использования исключений в качестве управляющей логики.

    Более подробно по ссылке.
    Ответ написан
    5 комментариев
  • Почему не устанавливается расширение php-bcmath?

    Vamp
    @Vamp
    Потому что нужно устанавливать пакет php7.3-bcmath. На вашем же скриншоте видно, что установилась версия модуля для PHP 7.4: php-bcmath is already the newest version (2:7.4+73+ubuntu18.04.1+deb.sury.org+1)
    Ответ написан
    Комментировать
  • Стоит ли уменьшать количество подключенных файлов?

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

    Если хотите точно знать как сильно влияет на производительность то или иное ваше решение в проекте, берите apache bench, siege, yandex.tank и тестируйте. Сразу скажу, разницы между 11 и 5 файлами вы точно не увидите. Впрочем, как между 5 и 555. Но не во всех случаях ответ будет сразу очевиден, поэтому обязательно освойте какую-нибудь тулзу для нагрузочного тестирования и не гадайте на кофейной гуще.
    Ответ написан
    Комментировать
  • Как добавить HTTP заголовки к SOAP запросу?

    Vamp
    @Vamp
    __setSoapHeaders устанавливает заголовки soap запроса, а не http. Они размещаются в элементе Header. По вашему примеру кода получится что-то типа такого:
    <SOAP-ENV:Envelope
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:ns1="yourns"
        xmlns:ns2="http://soapinterop.org/echoheader/">
        <SOAP-ENV:Header>
            <ns2:token>token</ns2:token>
            <ns2:user-token>user_id</ns2:user-token>
        </SOAP-ENV:Header>
        <SOAP-ENV:Body>
            <!-- тело запроса -->
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>


    Для добавления именно http заголовков нужно создать stream context:
    $aOptions['stream_context'] = stream_context_create([
        'http' => [
            'header' => "token: abc\r\nuser-token: 123"
        ]
    ]);
    
    $oSoapClient = new SoapClient( $url, $aOptions );
    $result = $oSoapClient->__doRequest( $sXml, $url, null, SOAP_1_1 );
    Ответ написан
    3 комментария
  • Что значить atime в stat?

    Vamp
    @Vamp
    Время последнего доступа кого угодно к файлу, на который вызываете stat(). Открытие файла и чтение данных из него обновляет метку atime. Причём последнее зарегистрированное время открытия/чтения необязательно могло быть сделано PHP скриптом.
    Ответ написан
    Комментировать
  • Тип данных с плавающей точкой в php?

    Vamp
    @Vamp
    Храните и отображайте в обычной строке. Влезет столько знаков, сколько нужно.
    Ответ написан
  • Как правильно между запросами cURL делать паузу?

    Vamp
    @Vamp
    Сразу после вызова функции.

    for ($i=0; $i < 3; $i++) { 
      echo curlNew();
      sleep($sleepTime);
    }
    Ответ написан
    Комментировать
  • Как пользоваться gRPC?

    Vamp
    @Vamp
    1. Надо смотреть какое именно API предоставляет сервер. Если JSON REST, то gRPC не подойдёт. gRPC - отдельный протокол, который должны поддерживать и клиент, и сервер, чтобы можно было по нему взаимодействовать.

    2. Если хотите взаимодействовать с удалённым сервером, то нужен только клиент. Если хотите сами быть для кого-то сервером, предоставляющим gRPC API, то нужен сервер. На PHP нельзя сделать gRPC сервер, видимо поэтому и предлагают node.js. Попробуйте поднять сервер на линуксе, вместо openserver. Тогда появятся команды, описанные в доке, и вообще разработка станет гораздо проще.

    3. Простых доков по gRPC не видел.

    Помимо самого gRPC вам придётся разобраться ещё и с protobuf, так как gRPC основан на нём. Его тоже необходимо установить либо как модуль к PHP, либо как composer зависимость. Помимо этого, удалённый сервер должен предоставить proto файл, на основе которого вы будете делать gRPC клиента. Этот файл необходимо скомпилировать при помощи protoc (компилятора protobuf) с использованием специального плагина к нему - grpc_php_plugin. В результате получится набор PHP скриптов, реализующих gRPC клиента для доступа к API удалённого сервера. Вот эти скрипты вы и будете использовать в своих скриптах для общения с сервером.
    Ответ написан
    3 комментария
  • Как сформировать XML в SOAP на PHP?

    Vamp
    @Vamp
    Вам придется вручную составить XML. Встроенных средств для работы с атрибутами у SoapClient нет.

    $xw = new XMLWriter();
    $xw->openMemory();
    $xw->startElementNS('ns1', 'GetTariffRequest', null);
        $xw->startElement('NeedList');
            $xw->text('1');
        $xw->endElement();
    
        $xw->startElement('Subject');
            $xw->writeAttribute('SbjKey', '1');
        $xw->endElement();
    $xw->endElement();
    
    $s = new SoapClient(...);
    $s->GetTariff(new SoapVar($xw->outputMemory(), XSD_ANYXML));

    XMLWriter здесь только как пример. Составлять строку с XML вы можете любым другим способом.
    Ответ написан
    Комментировать
  • Какой путь прописать для upload_tmp_dir?

    Vamp
    @Vamp
    upload_tmp_dir нужно указывать в пределах open_basedir, иначе скрипты сайта не смогут получить доступ к загружаемым файлам. Аналогично нужно настроить ещё session.save_path и sys_temp_dir, иначе не будут работать сессии и функции для работы с временными файлами.

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

    Пару лет назад я описывал рабочую схему для усиления безопасности в другом вопросе на тостере. Взгляните.
    Ответ написан
  • Как подключить google authenticator?

    Vamp
    @Vamp
    Сложно сказать в чём у вас ошибка, так как вы не предоставили код. Вероятно, криво составили QR, раз уж ошибка возникает при его сканировании. Более подробно о том как нужно составлять урл для QR-кода можно прочитать в вики.

    Я внедрил Google Authenticator в свой проект без каких-либо проблем. Использую пакет sonata-project/google-authenticator.

    Генерация кода:
    $g = new \Google\Authenticator\GoogleAuthenticator();
    $secret = $g->generateSecret();
    echo '<img src="https://chart.googleapis.com/chart?'
      .'cht=qr&chl=otpauth://totp/mysite%3Fsecret%3D'
      .$secret.'&chs=200x200&chld=L|0" />';
    Значение $secret сохраняется в БД и привязано к конкретному юзеру.

    Проверка OTP:
    $g = new \Google\Authenticator\GoogleAuthenticator();
    if ($g->checkCode($secret, $code)) {
      echo 'Welcome!'
    } else {
      echo 'Wrong code';
    }
    Примеры кода приведены для библиотеки версии 1.0.2.

    Важный момент - время на сервере и на телефонах должно совпадать, чтобы генерируемые OTP совпадали. Поэтому сервер синхронизируется по протоколу NTP. С телефонами сложнее. Можно в настройках системы установить синхронизацию часов телефона с временем из GSM сети (для любых платформ), либо в настройках приложения Google Authenticator (в android версии есть, в iOS версии нет, про другие платформы не в курсе).
    Ответ написан
    Комментировать