• Порекомендуйте подходящую базу данных?

    sgjurano
    @sgjurano
    Разработчик
    Для OLAP нагрузки в последнее время активно используют Clickhouse — у него довольно высокий порог вхождения, зато бесплатный и производительность того стоит.
    Ответ написан
    Комментировать
  • Что будет при подключении около трех тысяч сторонних модулей на сайте?

    saboteur_kiev
    @saboteur_kiev Куратор тега Веб-разработка
    software engineer
    Подключить можно и десять тысяч модулей, и в зависимости от количества работы каждого модуля в одну и ту же секунду, мощности сервера, разница может быть от "все летает" до "система навернулась и подниматься не хочет"

    Большой онлайн у разных людей это тоже разные цифры.

    Ваш вопрос явно не подходит под этот ресурс. Нужно либо полная конкретика со всеми уточнениями, а тогда это тянет на полноценное обсуждение ТЗ с правками.
    Либо задавать более простые технические вопросы.

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

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Не стоит передавать аргументы по ссылке без реальной на то необходимости.
    А чревато это изменением значений аргументов внутри функции и использованием незапланированно изменённых значений после возврата из функции.
    Ну и константы не сможете передать в таких аргументах.
    Ответ написан
    Комментировать
  • Подпись по ГОСТ в php или как подписать SOAP ГОСТ алгоритмами?

    irishmann
    @irishmann Автор вопроса
    Научись пользоваться дебаггером
    С OpenSSL ничего не вышло. Сделал с помощью КриптоПРО. Поставил CSP на сервер, установил сертификаты и собрал расширение phpcades. Ниже говнокод, ссылки на примеры и инструкции.

    класс CryptoPro

    <?php
    
    namespace PHPCadesSOAP;
    
    use CPStore;
    
    class CryptoPro {
    
        public static function SetupStore($location, $name, $mode) {
            $store = new CPStore();
            $store->Open($location, $name, $mode);
            return $store;
        }
    
        public static function SetupCertificates($location, $name, $mode) {
            $store = self::SetupStore($location, $name, $mode);
            return $store->get_Certificates();
        }
    
        public static function SetupCertificate($location, $name, $mode, $find_type, $query, $valid_only, $number) {
            $certs = self::SetupCertificates($location, $name, $mode);
            if ($find_type != NULL) {
                $certs = $certs->Find($find_type, $query, $valid_only);
                if (is_string($certs))
                    return $certs;
                else
                    return $certs->Item($number);
            }
            else {
                $cert = $certs->Item($number);
                return $cert;
            }
        }
    
        public static function createMessageID() {
            $uuid = md5(uniqid(rand(), true));
            $guid = 'uudi:' .
                    substr($uuid, 0, 8) . "-" .
                    substr($uuid, 8, 4) . "-" .
                    substr($uuid, 12, 4) . "-" .
                    substr($uuid, 16, 4) . "-" .
                    substr($uuid, 20, 12);
    
            return $guid;
        }
    
    }


    класс MySoapClient

    <?php
    
    namespace PHPCadesSOAP;
    
    use SoapClient;
    use PHPCadesSOAP\Logger;
    use DOMDocument;
    use PHPCadesSOAP\CryptoPro;
    use CPSigner;
    use CPSignedXml;
    
    class MySoapClient extends SoapClient {
    
        private $certSubjectName = 'test certificate';
        private $IPS_id = '********-****-****-****-************';
    
        function __doRequest($request, $location, $saction, $version, $one_way = NULL) {
            Logger::debug('Неподписанный запрос от MySoapClient - ' . $request);
    
            $cert = CryptoPro::SetupCertificate(CURRENT_USER_STORE, "My", STORE_OPEN_READ_ONLY, CERTIFICATE_FIND_SUBJECT_NAME, $this->certSubjectName, 0, 1);
            $certData = preg_replace('/\n+/', '', $cert->export(0));
    
            $xml = new DOMDocument();
            $xml->loadXML($request);
    
            $Envelope = $xml->getElementsByTagName('Envelope')->item(0);
            $Body = $Envelope->getElementsByTagName('Body')->item(0);
            $prefix = $Envelope->prefix;
    
            $Envelope->setAttribute('xmlns:wsse', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd');
            $Envelope->setAttribute('xmlns:wsu', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd');
            $Envelope->setAttribute('xmlns:ds', 'http://www.w3.org/2000/09/xmldsig#');
            $Envelope->setAttribute('xmlns:a', 'http://www.w3.org/2005/08/addressing');
    
            $Header = $xml->createElement($prefix . ':Header');
    
            $To = $xml->createElement('a:To', 'https://**********************');
    
            $Action = $xml->createElement('a:Action', 'sendResponse');
    
            $ReplyTo = $xml->createElement('a:ReplyTo');
            $ReplyToAddress = $xml->createElement('a:Address', 'http://www.w3.org/2005/08/addressing/anonymous');
    
            $FaultTo = $xml->createElement('a:FaultTo');
            $FaultToAddress = $xml->createElement('a:Address', 'http://www.w3.org/2005/08/addressing/anonymous');
    
            $MessageID = $xml->createElement('a:MessageID', CryptoPro::createMessageID());
    
            $Security = $xml->createElement('wsse:Security');
    
            $BinarySecurityToken = $xml->createElement('wsse:BinarySecurityToken', $certData);
            $BinarySecurityToken->setAttribute('EncodingType', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary');
            $BinarySecurityToken->setAttribute('ValueType', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3');
            $bsd_id = uniqid('x509-');
            $BinarySecurityToken->setAttribute('wsu:Id', $bsd_id);
    
            $Signature = $xml->createElement('ds:Signature');
    
            $SignedInfo = $xml->createElement('ds:SignedInfo');
    
            $CanonicalizationMethod = $xml->createElement('ds:CanonicalizationMethod');
            $CanonicalizationMethod->setAttribute('Algorithm', 'http://www.w3.org/2001/10/xml-exc-c14n#');
    
            $SignatureMethod = $xml->createElement('ds:SignatureMethod');
            $SignatureMethod->setAttribute('Algorithm', 'urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-256');
    
            $Reference_of_body = $xml->createElement('ds:Reference');
            $uri_on_body = uniqid('body-');
            $Reference_of_body->setAttribute('URI', '#' . $uri_on_body);
            $Body->setAttribute('wsu:Id', $uri_on_body);
    
            $Reference_of_body_Transforms = $xml->createElement('ds:Transforms');
    
            $Reference_of_body_Transforms_Transform = $xml->createElement('ds:Transform');
            $Reference_of_body_Transforms_Transform->setAttribute('Algorithm', 'http://www.w3.org/2001/10/xml-exc-c14n#');
    
            $Reference_of_body_DigestMethod = $xml->createElement('ds:DigestMethod');
            $Reference_of_body_DigestMethod->setAttribute('Algorithm', 'urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256');
    
            $Reference_of_body_DigestValue = $xml->createElement('ds:DigestValue');
    
            $SignatureValue = $xml->createElement('ds:SignatureValue');
            $KeyInfo = $xml->createElement('ds:KeyInfo');
    
            $SecurityTokenReference = $xml->createElement('wsse:SecurityTokenReference');
    
            $SecurityTokenReference_Reference = $xml->createElement('wsse:Reference');
            $SecurityTokenReference_Reference->setAttribute('ValueType', "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3");
            $SecurityTokenReference_Reference->setAttribute('URI', '#' . $bsd_id);
    
            $Envelope->insertBefore($Header, $Body);
            $Header->appendChild($To);
            $Header->appendChild($Action);
            $Header->appendChild($ReplyTo);
            $ReplyTo->appendChild($ReplyToAddress);
            $Header->appendChild($FaultTo);
            $FaultTo->appendChild($FaultToAddress);
            $Header->appendChild($MessageID);
            $Header->appendChild($Security);
            $Security->appendChild($BinarySecurityToken);
            $Security->appendChild($Signature);
            $Signature->appendChild($SignedInfo);
            $SignedInfo->appendChild($CanonicalizationMethod);
            $SignedInfo->appendChild($SignatureMethod);
            $SignedInfo->appendChild($Reference_of_body);
            $Reference_of_body->appendChild($Reference_of_body_Transforms);
            $Reference_of_body_Transforms->appendChild($Reference_of_body_Transforms_Transform);
            $Reference_of_body->appendChild($Reference_of_body_DigestMethod);
            $Reference_of_body->appendChild($Reference_of_body_DigestValue);
            $Signature->appendChild($SignatureValue);
            $Signature->appendChild($KeyInfo);
            $KeyInfo->appendChild($SecurityTokenReference);
            $SecurityTokenReference->appendChild($SecurityTokenReference_Reference);
    
            $request = $xml->saveXML();
    
            $signer = new CPSigner();
            $signer->set_Certificate($cert);
            $signer->set_Options(2);
    
            $sd = new CPSignedXml();
            $sd->set_SignatureType(2);
            $sd->set_Content($request);
            $sd->set_DigestMethod('urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-512');
            $sd->set_SignatureMethod('urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-512');
            $signedXml = $sd->Sign($signer, "//*[local-name()='Signature']");
    
            Logger::debug('подписанный запрос от MySoapClient - ' . $signedXml);
            return parent::__doRequest($signedXml, $location, $saction, $version);
        }
    
    }


    Проверка такой подписи

    <?php
        $xml = file_get_contents('/var/www/dsig.xml');
        try {
            $xpath = "//*[local-name()='Signature' and namespace-uri()='http://www.w3.org/2000/09/xmldsig#']";
            $xmldsig = new CPSignedXML();
            $xmldsig->Verify($xml, $xpath);
            print("OK\n");
        } catch (Exception $e) {
            echo $e->getMessage() . "\n";
        }



    Ответ написан
    Комментировать
  • Актуальны ли админ панели на PHP?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    как мне очень трудозатратно, нужно разделение фронт и бек, или хороший фулстек программист.
    как правило если у вас SAAS сервис и требуется клиентоориентированный интерфейс то 90% индивидуальная админка + rest.
    если же cms которая теражируется клиентам, должна иметь возможность кастомизироваться то подойдет многостроничник на bootsrap, с twig и фреймворком.
    Ответ написан
    Комментировать
  • Насколько актуален чистый PHP?

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


    Налицо непонимание даже не рынка, а жизни в целом :) Для начала надо определиться, работа это или хобби.

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

    Если работа — так иди на любую "боевую" работу. Там, грубо говоря, тебя жизнь поставит на место. Не нужного никакого сидения в коробочке и изучения чего-то там. Ты хочешь понять рынок? Так выйди на него. Рынку нужно одно — решение задач заказчика за минимально возможные деньги и время. Пойди на любую работу, там ты не будешь маяться вопросами о бытии, языках и фреймворках. Тебе руководитель даёт задачу — ты её решаешь, отдаёшь, берёшь следующую. На более высоких уровнях иерархии — ты раздаёшь задачи, добиваешься готового решения, сдаёшь заказчику. Повторить несколько раз. Я сменил примерно 3-4 места работы, прежде чем научиться просто РАБОТАТЬ, хотя PHP я к тому времени знал на уровне миддла.

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

    Таксисты не изучают правила дорожного движения и устройство автомобиля целый год. Когда им надо кормить семью — они просто выезжают и возят людей. Сначала получается не очень, но потом всё лучше и лучше.

    И уж точно один день реальной работы стоит года "вкатывания" и сидения в песочнице.
    Ответ написан
  • PHP как определить недоступность сайта?

    New_Horizons
    @New_Horizons
    Бред:
    ну попробовать взять информацию)
    если не получилось, значит недоступен)
    Ответ написан
    9 комментариев
  • Что случится с программой (Go, Python, JS, PHP), если потребуется выделить память, а оперативная память в ОС закончилась?

    romesses
    @romesses
    Backend инженер
    Не имеет значения какой язык программирования будет использован. ОС, прежде всего, постарается обслужить аппетиты программы. И если доступной ОЗУ не хватит, полезет в файл/раздел подкачки (swap).
    В Линукс программу убьет защитный механизм OOM как только превысит определенный порог нагрузки на ресурсы системы. В Windows - не знаю, возможно просто не выделит критический кусок памяти для приложения.

    А если программа не умеет обрабатывать ошибки нехватки памяти, то она просто зависнет или рухнет с посмертным дампом.

    1. Из сети (диска) читается файл чанками
    Ух, замечательно!

    2. Все это складыватся в переменную
    Что?! Зачем это понадобилось? Это как если бы в строительстве ставили кирпичный дом на фундамент целиком, а не по частям.
    Ответ написан
    Комментировать
  • Двойной ip при определении ip пользователя?

    @stimu
    Настоящий IP находится только в REMOTE_ADDR, все остальное может содержать все что захотел написать отправляющий эти заголовки, хоть буквы.
    Ответ написан
    2 комментария
  • Какие серверные языки можно использовать в HTML?

    vabka
    @vabka
    Токсичный шарпист
    Никакой нельзя. HTML отображется у клиента - в браузере.
    А в браузере есть только браузерный javascript.

    На сервере вы можете средствами серверного языка генерировать html, который будет выдан клиенту.
    Это можно делать на любом языке, который может выполняться на сервере, с разной степенью удобства (есть даже примеры на bash и ассемблере)

    Везде это будет делаться по разному, но смысл один - на веб-сервер приходит HTTP-запрос, а программа (aka скрипт) на сервере, в зависимости от данных в этом запросе, сгенерирует HTTP-ответ, который веб-сервер отправит клиенту, который сделал запрос.

    Надеюсь, я смог ответить на ваш вопрос достаточно подробно - если что-то непонятно, то пишите в комментарий.

    PS: чисто теоретически вы можете скомпилировать код на любом языке в js или wasm и выполнять его в браузере: такое решение точно есть для C/C++, golang, rust, C#, F#, kotlin. На счёт других языков я не уверен.
    Но не думаю, что это именно то, что вам нужно.
    Ответ написан
    Комментировать
  • Переход к PHP-фреймворку. Какому?

    myks92
    @myks92 Куратор тега PHP
    Нашёл решение — пометь вопрос ответом!
    Порядок:
    1. Yii2
    2. Laravel
    3. Symfony

    Yii2 слишком старый, но очень хорош для старта. Можно подождать Yii3, либо сразу начинать с Symfony. Это вам обеспечит много сложностей, но при этом даст хорошее будущее. Так как в хороших компаниях практически все используют Symfony. Если покажется сложным и не подъёмным - вернитесь к Yii2.

    Рекомендую к прочтению:
    Ответ написан
    2 комментария
  • Как сохранить 500 млн документов в Mysql или Postgresql?

    ThunderCat
    @ThunderCat Куратор тега MySQL
    {PHP, MySql, HTML, JS, CSS} developer
    500 млн документов в Mysql или Postgresql... Мне нужно их индексировать через Sphinx

    However, Sphinx does not depend on nor require any specific database to function.
    Если у вас не стоит задача работать с УЖЕ СУЩЕСТВУЮЩЕЙ базой, база сфинксу как таковая не нужна, у него свои индексы и свой движок, хотя и с базами она тоже умеет.

    PS: sphinxsearch.com/forum/view.html?id=11964
    Ответ написан
    Комментировать
  • Почему PHP не принимает символы / ' ` и смайлики в строке input и textarea для записи в БД MySQL?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Чтобы смайлы не вызывали ошибку надо выставить правильную кодировку
    чтобы никакие символы не мешали запросу, все переменные надо передавать в БД отдельно от запроса

    // правильно соединяемся
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    $mysqli = new mysqli($host, $user, $pass, $db, $port);
    $mysqli->set_charset("utf8mb4");
    // правильно вставляем
    $sql = "INSERT INTO users (name, email, password) VALUES (?,?,?)";
    $stmt= $conn->prepare($sql);
    $stmt->bind_param("sss", $name, $email, $password);
    $stmt->execute();
    Ответ написан
    Комментировать
  • Какой ЯП выбрать как дополнение к php - Go или Python?

    @bacon
    Если очень кратко, без всяких нюансов:
    Python - для ускорения разработки.
    Go - для ускорения работы сервиса, хотя наверно лучше сказать, для оптимизации узких мест.
    Ответ написан
    4 комментария
  • Есть ли приимущества у Ruby перед PHP?

    c3gdlk
    @c3gdlk
    Ментор в http://rubyboost.ru/
    Работа должна приносить удовольствие. Почему бы не потратить часов 40 чтобы понять нравится оно вам больше чем php или нет? А что там умеет в итоге язык это дело десятое.

    Если говорить об отличиях, то у руби очень сложная внутренняя структура, которая позволяет писать невероятно выразительный код. Но, это все медленно работает и жрет кучу памяти. Только последние версии языка начали понемногу сокращать разрыв с тем же php или питоном
    Ответ написан
    Комментировать
  • Почему Service Locator это зло и что использовать вместо?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    Основные минусы:
    - В результате, между классом и его клиентом существует формальный или неформальный «контракт», который выражается в виде предусловий (требований к клиенту) и постусловий (гарантий выполнения работы). Однако если класс принимает экземпляр сервис локатора, или, хуже того, использует глобальный локатор, то этот контракт, а точнее требования, которые нужно выполнить клиенту класса, становятся неясными
    - Когда наш класс использует сервис локатор, то стабильность класса становится неопределенной. Наш класс, теоретически, может использовать что угодно, поэтому изменение любого класса (или интерфейса) в нашем проекте может затронуть произвольное количество классов и модулей
    - Самое страшное в Сервис Локаторе то, что он дает видимость хорошего дизайна. У нас никто не знает о конкретных классах, все завязаны на интерфейсы, все «нормально» тестируется и «расширяется». Но когда вы попробуете использовать ваш код в другом контексте или когда кто-то попробует использовать его повторно, вы с ужасом поймете, что у вас есть дикая «логическая» связанность, о которой вы и не подозревали
    - Для меня ясность и понятность интерфейса класса важнее количества параметров конструктора. Я не исключаю, что бывают случаи, когда сервис локатор является наименьшим злом, но я бы в любом случае постарался свести его использования к минимуму.
    Ответ написан
    Комментировать
  • Единая бд для апи и веба в docker?

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

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

    Пример:

    docker-compose.laravel.yml
    services:
        mysql: 
          image: ...
          networks:
             - default
             - my_private_network
    
        redis: 
          image: ...
          networks:
             - default
             - my_private_network
    
    networks:
      my_private_network:
        name: my_private_network
        driver: bridge


    docker-compose.lumen.yml
    php-fpm:
        image: ...
        networks:
          - default
          - my_private_network
    
    networks:
      my_private_network:
        external: true
        name: my_private_network

    - В первом стаке мы создаем новую сеть, и подключаем нужные нам контейнеры;

    - Во втором стаке мы объявляем о существовании сети которая была создана ранее, и так же подключаем наш php-fpm контейнер, к этой сети, что бы коммуницировать с другими контейнерами по сети;

    После этого, в стаке для Lumen вы можете смело подключиться к контейнерам mysql, redis по их алиасам, как и ранее:

    Lumen .env
    DB_HOST=mysql
    REDIS_HOST=redis


    Успехов!
    Ответ написан
    1 комментарий
  • Как организовать и хранить конфиг по каждому пользователю, чтобы что-то делать один или несколько раз?

    @cicatrix
    было бы большой ошибкой думать
    Уже делал что-то похожее. Если показывать всегда по порядку, то вовсе не обязательно хранить все со всеми.
    Если все новые фичи имеют ID и показываются по порядку, то хранить с каждым пользователем достаточно ID последней просмотренной. И никакого разрастания.
    Есть и ограничение, разумеется, показывать можно только по мере возрастания ID, но зато хранить надо намного меньше всего.
    Ответ написан
    Комментировать
  • Php 7+ умеет без библиотек открывать excel и гугл таблицы?

    @sl0
    Конечно можно. Надо лишь написать свою.
    Ответ написан
    Комментировать