PHP code example of chipslays / porter

1. Go to this page and download the library: Download chipslays/porter library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

chipslays / porter example snippets


use Porter\Events\Event;

0:3737');

server()->on('ping', function (Event $event) {
    $event->reply('pong');
});

server()->start();

use Workerman\Worker;

$worker = new Worker('websocket://0.0.0.0:3737');

use Workerman\Worker;

$context = [
    // More see http://php.net/manual/en/context.ssl.php
    'ssl' => [
        'local_cert' => '/path/to/cert.pem',
        'local_pk' => '/path/to/privkey.pem',
        'verify_peer' => false,
        // 'allow_self_signed' => true,
    ],
];
$worker = new Worker('websocket://0.0.0.0:3737', $context);
$worker->transport = 'ssl';

use Porter\Server;

$server = Server::getInstance();
$server->on(...);

server()->on(...);

$server = Server::getInstance();
$server->boot($worker);

// by helper function
server()->boot($worker);

use Workerman\Worker;

$worker = new Worker('websocket://0.0.0.0:3737');
server()->boot($worker); // booting server

$worker = new Worker('websocket://0.0.0.0:3737');
$worker->... // configure new worker

// change worker in already booted server
server()->setWorker($worker);

use Workerman\Worker;

$worker = new Worker('websocket://0.0.0.0:3737');
server()->setWorker($worker);

server()->getWorker();

use Porter\Server;
use Porter\Payload;
use Porter\Connection;
use Porter\Events\AbstractEvent;

class Ping extends AbstractEvent
{
    public static string $id = 'ping';

    public function handle(Connection $connection, Payload $payload, Server $server): void
    {
        $this->reply('pong');
    }
}

server()->addEvent(Ping::class);

server()->autoloadEvents(__DIR__ . '/Events');

$server->on('ping', function (Event $event) {
    $event->reply('pong');
});

server()->start();

use Porter\Terminal;
use Porter\Connection;

server()->onConnected(function (Connection $connection, string $header) {
    Terminal::print('{text:darkGreen}Connected: ' . $connection->getRemoteAddress());

    // Here also available vars: $_GET, $_COOKIE, $_SERVER.
    Terminal::print("Query from client: {text:darkYellow}foo={$_GET['foo']}");
});

use Porter\Terminal;
use Porter\Connection;

server()->onDisconnected(function (Connection $connection) {
    Terminal::print('{text:darkGreen}Connected: ' . $connection->getRemoteAddress());
});

use Porter\Terminal;
use Porter\Connection;

server()->onError(function (Connection $connection, $code, $message) {
    Terminal::print("{bg:red}{text:white}Error {$code} {$message}");
});

use Porter\Terminal;
use Workerman\Worker;

server()->onStart(function (Worker $worker) {
    //
});

use Porter\Terminal;
use Workerman\Worker;

server()->onStop(function (Worker $worker) {
    //
});

use Porter\Terminal;
use Workerman\Worker;

server()->onReload(function (Worker $worker) {
    //
});

server()->onRaw(function (string $payload, Connection $connection) {
    if ($payload == 'ping') {
        $connection->send('pong');
    }
});

server()->to($connection, 'ping');

server()->broadcast('chat message', [
    'nickname' => 'John Doe',
    'message' => 'Hello World!',
]);

server()->storage();

server()->storage()->put('foo', 'bar');

$storage = server()->storage();
$storage->get('foo');

// can also be a get as propperty
server()->storage()->put('foo', 'bar');
$storage = server()->storage;

server()->channels();

server()->channels()->create('secret channel');

$channels = server()->channels();
$channels->get('secret channel');

$connection = server()->connection(1);
server()->to($connection, 'welcome message', [
    'text' => 'Hello world!'
]);

// also can get like
$connection = server()->getWorker()->connections[1337] ?? null;

$connections = server()->connections();
server()->broadcast('update users count', ['count' => $connections->count()]);

// also can get like
$connections = server()->getWorker()->connections;

$v = server()->validator();

if ($v->email()->validate('[email protected]')) {
    //
}

// available as helper
if (validator()->contains('example.com')->validate('[email protected]')) {
    //
}

// by method
server()->channels();

// by property
server()->channels;

$channel = server()->channels()->create('secret channel', [
    'foo' => 'bar',
]);

$channel->join($connection)->broadcast('welcome message', [
    'foo' => $channel->data->get('foo'),
]);

$channel = server()->channels()->get('secret channel');

foreach (server()->channels()->all() as $id => $channel) {
    echo $channel->connections()->count() . ' connection(s) in channel: ' . $id . PHP_EOL;
}

$count = server()->channels()->count();

echo "Total channels: {$count}";

server()->channels()->delete('secret channel');

$channelId = 'secret channel';
if (!server()->channels()->exists($channelId)) {
    server()->channels()->create($channelId);
}

server()->channels()->join($connection);
server()->channels()->join([$connection1, $connection2, $connection3, ...]);

$channel = server()->channel('secret channel');
$channel->join($connection);
$channel->join([$connection1, $connection2, $connection3, ...]);

$channel = server()->channel('secret channel');
$channel->leave($connection);

$channel = server()->channel('secret channel');
$channel->exists($connection);

$channel = server()->channel('secret channel');

foreach($channel->connections()->all()) as $connection) {
    $connection->lastMessageAt = time();
}

$channel = server()->channel('secret channel');

$connection = $channel->connections()->get([1337]); // get connection with 1337 id

$channel = server()->channel('secret channel');
$channel->broadcast('welcome message', [
    'text' => 'Hello world',
]);

$channel->broadcast('welcome message', [
    'text' => 'Hello world',
], [$connection]);

$channel->broadcast('welcome message', [
    'text' => 'Hello world',
], [$connection1, $connection2, ...]);

$channel = server()->channel('secret channel');
$channel->destroy();

// now if use $channel, you get an error
$channel->data->get('foo');

$channel = channel('secret channel');
$connection->channel = &$channel;

$channel->data->set('foo');
$channel->data->get('foo', 'default value');
$channel->data->has('foo', 'default value');

$channel->data['foo'];
$channel->data['foo'] ?? 'default value';
isset($channel->data['foo']);

// see more examples here: https://github.com/chipslays/collection

$payload->get('foo', 'default value');

// can also use like:
$payload->data->get('foo', 'default value');
$payload->data['foo'] ?? 'default value';

$payload->is('StringType', 'username'); // return true if username is string
$payload->is(['contains', 'john'], 'username'); // return true if $payload->data['username'] contains 'john'

$payload->type; // string

$payload->data; // Collection

$payload->data->set('foo');
$payload->data->get('foo', 'default value');
$payload->data->has('foo', 'default value');

$payload->data['foo'];
$payload->data['foo'] ?? 'default value';
isset($payload->data['foo']);

// see more examples here: https://github.com/chipslays/collection

use Porter\Server;
use Porter\Payload;
use Porter\Connection;
use Porter\Events\AbstractEvent;

return new class extends AbstractEvent
{
    public static string $type = 'hello to';

    protected array $rules = [
        'username' => ['stringType', ['length', [3, 18]]],
    ];

    public function handle(Connection $connection, Payload $payload, Server $server): void
    {
        if (!$this->validate()) {
            $this->reply('bad request', ['errors' => $this->errors]);
            return;
        }

        $username = $this->payload->data['username'];
        $this->reply(data: ['message' => "Hello, {$username}!"]);
    }
};

use Porter\Server;
use Porter\Payload;
use Porter\Events\AbstractEvent;
use Porter\Connection;

class Ping extends AbstractEvent
{
    public static string $type = 'ping';

    public function handle(Connection $connection, Payload $payload, Server $server): void
    {
        $this->reply('pong');
    }
}

// and next you need add (register) this class to events:
server()->addEvent(Ping::class);

// this is a object of Channel, getted by `channel_id` from client.
$this->channel;
$this->channel();

$this->channel()->broadcast('new message', [
    'text' => $this->payload->get('text'),
    'from' => $this->connection->nickname,
]);

// this is a object of Channel, getted by `target_id` from client.
$this->target;
$this->target();

$this->to($this->target, 'new message', [
    'text' => $this->payload->get('text'),
    'from' => $this->connection->nickname,
]);

$this->to($connection, 'ping');

$this->reply('ping');

// analog for:
$this->to($this->connection, 'ping');

$username = $this->payload->data['username'];
$this->reply(data: ['message' => "Hello, {$username}!"]);

$this->raw('ping');

// now client will receive just a 'ping', not event object.

$this->broadcast('chat message', [
    'nickname' => 'John Doe',
    'message' => 'Hello World!',
]);

$this->broadcast('user join', [
    'text' => 'New user joined to chat.',
], [$this->connection]);

if (!$this->validate()) {
    return $this->reply(/** ... */);
}

if ($this->hasErrors()) {
    return $this->reply('bad request', ['errors' => $this->errors]);
}

public function handle(Connection $connection, Payload $payload, Server $server)
{
    $this->get('nickname');

    // as property
    $this->data['nickname'];
    $this->data->get('nickname');

    // form payload instance
    $payload->data['nickname'];
    $payload->data->get('nickname');

    $this->payload->data['nickname'];
    $this->payload->data->get('nickname');
}

use Porter\Events\Event;

server()->on('new message', function (Event $event) {
    // $event has all the same property && methods as in the example above

    $event->to($event->target, 'new message', [
        'text' => $this->payload->get('text'),
        'from' => $this->connection->nickname,
    ]);

    $event->channel()->broadcast('new message', [
        'text' => $this->payload->get('text'),
        'from' => $this->connection->nickname,
    ]);
});

$connection->firstName = 'John';
$connection->lastName = 'Doe';
$connection->getFullName = fn () => $connection->firstName . ' ' . $connection->lastName;

call_user_func($connection->getFullname); // John Doe

$connection->channels; // object of Porter\Connection\Channels

/**
 * Get connection channels.
 *
 * @return Channel[]
 */
public function all(): array

/**
 * Get channels count.
 *
 * @return int
 */
public function count(): int

/**
 * Method for when connection join to channel should detach channel id from connection.
 *
 * @param string $channelId
 * @return void
 */
public function delete(string $channelId): void

/**
 * Leave all channels for this connection.
 *
 * @return void
 */
public function leaveAll(): void

/**
 * When connection join to channel should attach channel id to connection.
 *
 * You don't need to use this method, it will automatically fire inside the class.
 *
 * @param string $channelId
 * @return void
 */
public function add(string $channelId): void

$client = new Client('ws://localhost:3737');
$client = new Client('wss://example.com:3737');

$client->on('ping', function (AsyncTcpConnection $connection, Payload $payload, Client $client) {
    $client->send('pong', ['time' => time()]);
});

$client->raw('simple message');

$client->onConnected(function (AsynTcpConnection $connection) {
    //
});

$client->onDisconnected(function (AsynTcpConnection $connection) {
    //
});

$client->onError(function (AsyncTcpConnection $connection, $code, $message) {
    //
});

$client->onRaw(function (string $payload, AsyncTcpConnection $connection) {
    if ($payload == 'ping') {
        $connection->send('pong');
    }
});

$client->on('pong', function (AsyncTcpConnection $connection, Payload $payload, Client $client) {
    //
});

$client->listen();

server()->storage()->load(__DIR__ . '/server-storage.data'); // you can use any filename

server()->storage();

// as standalone use without server
$store1 = new Porter\Storage(__DIR__ . '/path/to/file1');
$store2 = new Porter\Storage(__DIR__ . '/path/to/file2');
$store3 = new Porter\Storage(__DIR__ . '/path/to/file3');

server()->storage()->load(__DIR__ . '/path/to/file'); // you can use any filename

server()->storage()->put('foo', 'bar');

server()->storage()->get('foo', 'default value'); // foo
server()->storage()->get('baz', 'default value'); // default value

server()->storage()->remove('foo'); // true

server()->storage()->has('foo'); // true
server()->storage()->has('baz'); // false

server()->storage()->getPath();

server()->on(...);

// will be like:
use Porter\Server;
Server::getInstance()->on(...);

worker()->connections;

// will be like:
use Porter\Server;
Server::getInstance()->getWorker()->connections;

$channel = channel('secret channel'); // get channel instance
$channel = server()->channel('secret channel');
$channel = server()->channels()->get('secret channel');

server()->map('sum', fn(...$args) => array_sum($args));
echo server()->sum(1000, 300, 30, 5, 2); // 1337
echo server()->sum(1000, 300, 30, 5, 3); // 1338

server()->mapOnce('timestamp', fn() => time());
echo server()->timestamp(); // e.g. 1234567890
sleep(1);
echo server()->timestamp(); // e.g. 1234567890
bash
php server.php start
bash
php server.php start -d