PHP AMP Websocket: указание произвольных заголовков при рукопожатии

Задача: добавить произвольный заголовок клиенту при рукопожатии с сервером. Например Sec-WebSocket-Protocol

Решение:

use Amp\Delayed;
use Amp\Websocket\Client\Connection;
use Amp\Websocket\Client\Handshake;
use Amp\Websocket\Message;
use function Amp\Websocket\Client\connect;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\ConnectContext;

            Amp\Loop::run(function () use ($wss_url,$ip,$port,$pascket,&$answer,$wait_reseive) {                            
                $tlsc=new ClientTlsContext("");
                $tlw=$tlsc->withoutPeerVerification();
                $connectContext = (new ConnectContext)->withTlsContext($tlw);
                $handshake = (new Handshake("ws://1.18.24.70:$port/virtual_api_1c"))->withHeader('Sec-WebSocket-Protocol', 'virtual');  
                $connection = yield connect($handshake,$connectContext);   
                yield $connection->send($pascket);
                yield $connection->close();
            });  

Ошибка: as been blocked by CORS policy

В одной из задач возникла проблема: скрипт javascript «крутящийся» на localhost должен утянуть файл json с удаленного ресурса https. Вот тут и возникает ошибка:

Error: XMLHttpRequest error. As been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

Возникает она из-за политик CORS удаленного сайта.

Решение: добавить в скрипт который «выдает» данные, заголовок, что конкретно эти данные можно отдавать ну например ..всем.

<?php
header('Access-Control-Allow-Origin: *');
echo '{"UserId":"10","UserName":"Vasya Pukin 1"}';
?>

RabbitMQ: Отложеная доставка и время жизни пакета

Собрал наконец в одном классе, всё что мне нужно от RabbitMQ: а именно отправка сообщения в очередь, с отложеной доставкой, плюс уничтожение сообщения по прошествии какого то времени «не доставки».

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

<?php

//Необходимые классы
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPTable;


class TRabbit extends TLog{ 
    public $host="";
    public $login="";
    public $password="";
    public $port="";
    public $connection=null;
    public static $isInstance=false; 
    // настройки касающиеся очереди
    public $passive=false;      // может использоваться для проверки того, инициирован ли обмен, без того, чтобы изменять состояние сервера
    public $durable=true;       // убедимся, что RabbitMQ никогда не потеряет очередь при падении - очередь переживёт перезагрузку брокера
    public $exclusive=false;    // используется только одним соединением, и очередь будет удалена при закрытии соединения
    public $autodelete=false;   // очередь удаляется, когда отписывается последний подписчик
    public $ttl=3000;           // время жизни пакета, через которое оно при недоставке дропнется,в милисекундах
            
    public function __destruct(){
        if (self::$isInstance==false) {        
          $this->connection->close();  
        }
    }    
    public function __construct(){
        self::$isInstance=true;
        $this->host= TConfig::GetConfigKeyValue("rabbitmq_host");
        $this->login= TConfig::GetConfigKeyValue("rabbitmq_login");
        $this->host= "localhost";
        
        $this->password= TConfig::GetConfigKeyValue("rabbitmq_password");
        $this->password="guest";
        $this->port= TConfig::GetConfigKeyValue("rabbitmq_port");        
        $this->connection = new AMQPStreamConnection($this->host, $this->port, $this->login, $this->password);        
    }    
    /**
     * Поставить в очередь сообщение
     * @global type $db
     * @param type $queue   - имя очереди
     * @param type $message - сообщение в json формате
     * @param type $delay   - отсрочка доставки в секундах (необязательно)
     * @param type $ttl     - время жизни пакета, через которое оно при недоставке дропнется
     * @return type
     */
    public function  Producer($queue,$message,$delay=0,$ttl=null) {  
     global $db;
        try {    
          $answer = AnswerStrucNext(false, "Failed to queue a RabbitMQ message");             
             $channel = $this->connection->channel();      
            $channel->exchange_declare(
                'delay',
                'x-delayed-message',
                false,            /* не создается очереь если нет её */
                $this->durable,   /* гарантированная доставка */
                false,            /* удаление очереди если пустая и нет слушателей */
                false,            /* internal */
                false,            /* не ждать ответа от сервера (т. е. продолжать получение) */
                [
                    'x-delayed-type' => ['S', 'direct']                    
                ]);
             if (is_null($ttl)) $ttl=$this->ttl;
             $channel->queue_declare($queue, $this->passive, $this->durable, $this->exclusive, $this->autodelete,false,
                array(
                        "x-message-ttl" => array("I", $ttl)
                    )                     
                );
             $channel->queue_bind($queue, "delay", $queue);
               if ($delay==0){
                  $msg = new AMQPMessage($message);		        
               } else {
                   $msg = new AMQPMessage($message, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);		
                   $msg->set('application_headers', new AMQPTable(['x-delay' => $delay*1000]));        
               };
          $channel->basic_publish($msg,"delay",$queue);                  
          $channel->close();
          $answer = AnswerStrucNext(false, "ok");             
       } catch(Exception $err) {
           $this->InsertLog(TLog::PT_PLAIN,"Ошибка постановки в очередь $queue (RabbitMQ)", TLog::R_Error, $message);
       };          
     return $answer;
    }
}

PHP: работа с файлами Excel

Одним из вариантов работы с файлами Эксель является библиотека PhpSpreadsheet.

Установка:

composer require phpoffice/phpspreadsheet

Пример использования:


/require_once('vendor/autoload.php');
 
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\{Font, Border, Alignment};
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

$oSpreadsheet = IOFactory::load("akt.xlsx"); // шаблон с шапкой

$oSpreadsheet->getProperties()
   ->setCreator('SSK, OOO')
   ->setLastModifiedBy('SSK, OOO')
   ->setTitle('Акт сверки с клиентом') 
   ->setSubject('Акт сверки с клиентом')
   ->setKeywords('кцмукмц ')
   ->setCategory('узщшамыуозк ')
;

$oSpreadsheet->setActiveSheetIndex(0);
$wSheet = $oSpreadsheet->getActiveSheet();

$wSheet->setCellValueByColumnAndRow(1, 3, "Клиент: " . $res->result->user);
$wSheet->setCellValueByColumnAndRow(1, 4, "Дата с: " . $res->result->from);
$wSheet->setCellValueByColumnAndRow(1, 5, "Дата по: " . $res->result->from);

$totalrow=8;

$balance=0;
foreach($res->result->table as $row) {
    $source="";
    if ($row->doc_reservation>0){$source="уцкацук м №".$row->doc_reservation;};
    if ($row->doc_charge>0){$source="ы укмыу №".$row->doc_charge;};
    if ($row->doc_payment>0){
        $source="уфыкмыукм №".$row->doc_payment;
        if ($row->connector>0){$source=$source.",фыумукау №".$row->connector;};        
    }; 
    
    $wSheet->setCellValueByColumnAndRow(1, $totalrow, $row->date);    //дата
    $wSheet->setCellValueByColumnAndRow(2, $totalrow, $source);    // источник     
    $wSheet->setCellValueByColumnAndRow(3, $totalrow, $row->debit);    // дебет
    $wSheet->setCellValueByColumnAndRow(4, $totalrow, $row->credit);    // кредит
    $wSheet->setCellValueByColumnAndRow(5, $totalrow, $row->balance);    // баланс
    $wSheet->setCellValueByColumnAndRow(6, $totalrow, $row->ezs);    // ЭЗС
    $balance=$row->balance;
    $totalrow++;
}

$wSheet->setCellValueByColumnAndRow(1, $totalrow, "Текущий баланс: " . $balance);
$wSheet->getStyle('A'.$totalrow)->applyFromArray([
    'font' => [
      'name' => 'Arial',
      'bold' => true,
      'italic' => false,
      'underline' => Font::UNDERLINE_DOUBLE,
      'strikethrough' => false,
      'color' => [
          'rgb' => '808080' 
        ]
    ],
    'borders' => [
        'allBorders' => [
            'borderStyle' => Border::BORDER_THIN,
            'color' => [
                'rgb' => '808080'
            ]
        ],
    ],
    'alignment' => [
        'horizontal' => Alignment::HORIZONTAL_CENTER,
        'vertical' => Alignment::VERTICAL_CENTER,
        'wrapText' => true,
    ]
]);
// установить цвет фона ячейки
$wSheet->getStyle('A'.$totalrow)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('00FF7F');
 

$oWriter = IOFactory::createWriter($oSpreadsheet, 'Xlsx');
$oWriter->save('php://output');

PHP: как проверить, вызван ли метод класса из экземпляра, или статически

Задача: при вызове метода класса, использовать разный код в зависимости от того, как вызвана функция: статически или из класса. Т.е. результат выполнения кода:

 $tr=new TRabbit();
 $res= $tr->Producer("ocpi_queue", "Hello!");

и кода:

$res= TRabbit::Producer("ocpi_queue", "Hello!");

, должен быть разным.

Решение:

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

class TRabbit { 
    public static $isInstance=false;                 
    public function __construct(){
        self::$isInstance=true;
    }    
    public static function Producer($queue,$message,$delay=0) {  
      if (self::$isInstance==true) {
          echo "Код один\n";
      } else {
          echo "Код другой\n";
      }
    }
}
1 7 8 9 10 11 29