Пришло письмо от Яндекс, с просьбой заполнить формы.
Здрасти
Мы собирали, собирали данные, в конце концов не поняли сколько у вас детей и решили прямо спросить,
Проблема: бывает так, что при вызове soap, ответ на стороне клиента не собирается в объект, это может быть и из-за wsdl или из-за неверного ответа от сервер.
Решение: распарсить ответ от сервере как XML
// выполняем функцию SOAP
$response = $this->client->__soapCall("getParam", $param);
// костыль, так как первый response ничего не вернул, будем тупо парсить XML ответ
$response = $this->client->__getLastResponse();
// xml парсеру не нравится тег с неймспейсами, вырезаем их
$response = str_ireplace(array('soapenv:', 'tem:', 'SOAP-ENV:', 'rpc:'), '', $response);
$xml = simplexml_load_string($response, "SimpleXMLElement", LIBXML_NOCDATA);
$json = json_encode($xml);
$arrayResponse = json_decode($json,TRUE);
Если есть ошибка при разборе, можно поиграть с параметрами
$xml = simplexml_load_string($response, «SimpleXMLElement», LIBXML_COMPACT | LIBXML_PARSEHUGE);
В книге «Symfony 5. Быстрый старт» есть хороший пример, когда нам надо выполнить какие то долгие действия (отправить почту, вызвать сторонний API) но не заставлять пользователя ждать. Для этого используется очередь. Мы в очередь записываем действие, сразу отправляем ответ пользователю а дальше уже, в другом скрипте делаем задачи из очереди.
Но если по каким то причинам, вы не можете поставить rabbitmq или вам это будет «ДОРОГО», считай излишни, можно обойтись таким асинхронным выполнением. Суть его в том, что все действия делаем быстро, отдаем ответ клиенту, а потом уже, когда он отключился, продолжаем выполнять свои задачи:
<?php
// Игнорирует отключение пользователя
ignore_user_abort(true);
//позволяет скрипту быть запущенным постоянно
set_time_limit(0);
// старт буфиризации
ob_start();
// вывести результат в буфер
echo $result;
$length = ob_get_length();
header('Connection: close');
header("Content-Length: " . $length);
header("Content-Encoding: none");
header("Accept-Ranges: bytes");
// отключаем буфиризацию
ob_end_flush();
// сбросить (отправить) буфер вывода
ob_flush();
// сброс системного буфера вывода
flush();
// а вот тут уже делаем все остальное
По такому принципу у меня работает Telegram бот, он на входе принимает сообщение с внешнего источника, и тут же отключает этот источник от себя, а уже дальше отправляет сообщение в телегу
ClearURLs — https://github.com/ClearURLs/Addon/ расширение которое обрезает в URL все трекеры. Это превосходно.
Ранее я описывал алгоритм авторизации Digest, как самому собрать пакет данных
Для PHP все оказалось проще, в CURL уже есть готовый механизм, который делает 2 запроса для правильной авторизации
Это параметр CURLOPT_HTTPAUTH => CURLAUTH_DIGEST,
Полностью запрос:
$request =[
'SOAPAction: "http://yandex.ru/"',
'Content-Type: text/xml;charset=UTF-8',
];
$options = array(
CURLOPT_URL => $url,
CURLOPT_HEADER => true,
CURLOPT_VERBOSE => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false, // for https
CURLOPT_USERPWD => $username . ":" . $password,
CURLOPT_HTTPAUTH => CURLAUTH_DIGEST,
CURLOPT_HTTPHEADER => $request,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS =>"xmlRequest=" . $input_xml // если нужно передать xml в теле POST
);
$ch = curl_init();
curl_setopt_array( $ch, $options );
try {
$raw_response = curl_exec( $ch );
// validate CURL status
if(curl_errno($ch))
throw new Exception(curl_error($ch), 500);
// validate HTTP status code (user/password credential issues)
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status_code != 200)
throw new Exception("Response with Status Code [" . $status_code . "].", 500);
} catch(Exception $ex) {
if ($ch != null) curl_close($ch);
throw new Exception($ex);
}
if ($ch != null) curl_close($ch);
echo "raw response: " . $raw_response;
https://habr.com/ru/company/domclick/blog/548610/
Липкие сессии для самых маленьких [Часть 1] _ Блог компании ДомКлик _ Хабр
https://12factor.net/ru/
Understanding your Symfony app with Prometheus:
https://blog.4xxi.com/understanding-your-symfony-app-with-prometheus-fdb4b0124d99
Сбор и анализ логов с Fluentd:
https://habr.com/ru/company/selectel/blog/250969/
О сборке метриков:
https://www.youtube.com/watch?v=RPK5fp9-4yI
Fluentd
https://mcs.mail.ru/help/ru_RU/cases-logs/case-swarm
Fluentd docker
https://docs.docker.com/config/containers/logging/fluentd/
Про PUSHGATWAY очень мало написано в инете, особенно под PHP
Для установки локально PUSHGATWAY docker-compose.yml:
pushgateway:
image: prom/pushgateway
restart: always
container_name: app2022-pushgateway
ports:
- 9091:9091
- 9090:9090
networks:
- front
- backend
Есть библиотека для работы с pushgateway
https://github.com/PromPHP/prometheus_push_gateway_php -> promphp/prometheus_push_gateway_php
Однако, нашел хороший простой класс, который основан на GuzzleHttp\Client:
https://github.com/markarik/wnl-platform/blob/9f4383e850373e1849f04f6d1487268cf91fa615/app/Console/PrometheusPushgateway.php
Немного модифицировал его под свои нужды, и получилось вот такое
<?php
namespace App\Handler;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
class PrometheusPushgateway
{
public function notify($count, $code=200)
{
$url = 'http://pushgateway:9091/metrics/job/symfony/instance/sender';
$url = getenv('PUSHGATWAY_URL');
$client = new Client();
try {
$bodyLines = [
"# HELP response_symfony_code_count",
"# TYPE response_symfony_code_count",
"response_symfony_code_count {code=\"${code}\"} ${count}"
];
$body = implode("\n", $bodyLines) . "\n";
$client->request('POST', $url, [
'body' => $body
]);
} catch (GuzzleException $exception) {
exit('error');
}
}
}
#!/bin/bash php -i php bin/console debug:config framework profiler php bin/console debug:config web_profiler php bin/console debug:container profiler --show-arguments php bin/console debug:container web_profiler.debug_toolbar --show-arguments php bin/console debug:event-dispatcher kernel.response php bin/console about php bin/console debug:router