Push - message

 RabbitMQ

{

    "require": {

        "php-amqplib/php-amqplib": ">=3.0"

    }

}

Block docker-composer:

    rebbitmq:

      image: rabbitmq:3-management

      ports:

        - "5672:5672"

        - "15672:15672"

#      login: guest

#      password: guest

Отправка сообщения на PHP:

class Rabbit

{

    private string $host = '192.168.0.107';

    private int $port = 5672;

    private string $user = 'guest';

    private string $password = 'guest';

    private string $queueName = 'Testing';

    private string $exchangeName = 'test';

    private AMQPStreamConnection $connection;

    private AMQPMessage $message;

    private string $text;

    private function __construct()

    {

        $this->connection = new AMQPStreamConnection($this->host, $this->port, $this->user, $this->password);

        $this->message = new AMQPMessage($text??'', ['content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);

    }

    public static function send($text): void

    {

        $model = new self();

        $channel = $model->connection->channel();

        $channel->exchange_declare($model->exchangeName, 'direct', false, true, false);

        $channel->queue_declare($model->queueName, false, false, false, false);

        $channel->queue_bind($model->queueName, $model->exchangeName);

        $channel->basic_publish($model->message, '', $model->queueName);

        $channel->close();

        $model->connection->close();

}

}

Отправка сообщения на js:

Установка пакета:

npm install amqplib

Отправка сообщения с консоли:

const amqp = require('amqplib/callback_api');

process.stdin.on('readable', function() {

    const msg = process.stdin.read();

    if (msg !== null) {

        amqp.connect('amqp://192.168.0.107:5672', function(error0, connection) {});

        amqp.connect('amqp://192.168.0.107:5672', function(error0, connection) {

            if (error0) {

                throw error0;

            }

            connection.createChannel(function(error1, channel) {});

        });

        amqp.connect('amqp://192.168.0.107:5672', function(error0, connection) {

            if (error0) {

                throw error0;

            }

            connection.createChannel(function(error1, channel) {

                if (error1) {

                    throw error1;

                }

                const queue = 'TestQueue';


                channel.assertQueue(queue, {

                    durable: false

                });

                channel.sendToQueue(queue, Buffer.from(msg));

                console.log(" [x] Sent %s", msg);

                setTimeout(function() {

                    connection.close();

                    process.exit(0)

                }, 500);

            });

        });

    }

});

Прием на js:

const amqp = require('amqplib/callback_api');

amqp.connect('amqp://192.168.0.107:5672', function(error0, connection) {

    if (error0) {

        throw error0;

    }

    connection.createChannel(function(error1, channel) {

        if (error1) {

            throw error1;

        }

        var queue = 'TestQueue';

        channel.assertQueue(queue, {

            durable: false

        });

        console.log(" [*] Waiting for messages in %s. To exit press CTRL+C", queue);

        channel.consume(queue, function(msg) {

            console.log(" [x] Received %s", msg.content.toString());

        }, {

            noAck: true

        });

    });

});


Pusher

https://pusher.com/

Создаем сообщение на PHP:

class Pusher

{

private const app_id = "";

private const key = "";

private const secret = "";

private const options = ['cluster' => 'eu', 'useTLS' => true];

private static ?object $instance = null;

private function __construct()

{

}

private function __clone(): void

{

    // TODO: Implement __clone() method.

}


public static function getInstance(): ?object

{

    if (self::$instance === null) {

        self::$instance = new Push(

            self::key,

            self::secret,

            self::app_id,

            self::options

        );

    }

    return self::$instance;

}

public static function send(string $message = 'test'): void

{   \Yii::$app->redis->rpush('my-channel:my-event:string', $message);

    self::getInstance()->trigger('my-channel', 'my-event', $message);

}

Прослушиваем с помощью Vue3:

public function actionPusher(): string

{

if (Yii::$app->request->isPost) {

$object = (Yii::$app->request->post()['body']);

$text = Json::encode($object);

Pusher::send($text);

return 'ok';

} else {

return 'error';

}

}

const app = Vue.createApp({

    data() {

        return {

            status: 0,

            text: '',

            my_id: "<?= $user->id ?? '' ?>",

            messages: [],

        }

    },

    methods: {

        sendMessage() {

            let username = "<?= $user->username ?? '' ?>";

            let message = this.text;

            let id = this.my_id;

            let date = new Date();

            let csfr = "<?= Yii::$app->request->getCsrfToken() ?>";

            $.ajax(

                {

                    url: "<?= Yii::$app->request->baseUrl . '/chat/pusher' ?>",

                    type: 'POST',

                    data: {

                        body: {

                            id: id,

                            name: username,

                            message: message,

                            date: date

                        }, _csfr: csfr

                    },

                    success: function () {

                        console.log('200');

                    },

                    error: function (err) {

                        console.log(err.message);

                    }

                }

            );

            this.text = '';

        }

    }

}).mount('#app');

Ably


Установка js:
npm install ably

Установка PHP:
composer require ably/ably-php --update-no-dev

Добавление на страницу:
<script src="https://cdn.ably.com/lib/ably.min-1.js"></script>

Контролер:
Передаем запрос с помощью ajax.
Вызываем класс и передаем сообщение.
Также можно вызвать историю сообщений, список пользователей и статус канала.

public function actionAbly()
    {
        $model = new Ablys();
        $text = Yii::$app->request->post('text');
        $model->send($text);
//        foreach ($model->history() as $message) {
//            echo $message->data . PHP_EOL.'<br>';
//        }
//        $model->isOnline();
//        foreach ($model->isOnline() as $message) {
//            echo $message->clientId . PHP_EOL.'<br>';
//        }
//        var_dump($model->isStatus());
//        return $this->render('ably');
    }
    
class Ablys
{
    private string $user = 'g4C7HA.OqxAbQ:dtPmOoRhI-pZPEAhdfNN44QdlqNpCUa8syBZaA5Dxyo';
    private string|object $channel;
    private string $queueName = 'testing';
    private string $event = 'sending';
    private object $connection;

    public function __construct()
    {
        $this->connection= new AblyRest($this->user);
        $this->channel = $this->connection->channels->get($this->queueName);
    }

    public function send(string $text): void
    {
        $this->channel->publish($this->event, $text);
    }

    public function history(){
         $messagesPage = $this->channel->history();
         return $messagesPage->items;
    }
    public function isOnline(){
        $membersPage = $this->channel->presence->get();
        return $membersPage->items;
    }
    public function isStatus(){
        $channelStatus = $this->channel->status(); // => \Ably\Models\Status\ChannelDetails
        return $channelStatus;
    }
}

Прописываем на странице для считывания сообщений:

const ably = new Ably.Realtime('API');
const channel = ably.channels.get('testing');
channel.subscribe('sending', (message) => {
        console.log('Received a greeting message in realtime: ' + message.data)
    });

Признаки "плохого кода"

Кратко рассмотрим 12 признаков, когда код можно улучшить: 1. Duplicated Code  — иногда повторяющийся код не всегда несет в себе пользу. Выде...