Jak nakonfigurovat spuštění skritu jako službu ?
- FilipStudený
- Člen | 8
Zdravím, potřeboval bych poradit jak zprovoznit skript v adesáři
/bin
.
Mám vytvořený skript v PHP, který používá knihovnu Ratchet pro
vytvoření real-time chatovacího serveru.
Potřeboval bych poradit jak ho zprovoznit v Nette, bylo mi řečeno, že je
možné tento skript vložit do adresáře /bin
a poté
nakonfigurovat Nette tak aby ho spustilo, bohužel nevím jak to provést.
Je možné něco takového provést, bez toho aniž bych musel vytvářet různé Presentery ?
Skript jsem doposud spouštěl z příkazové řádky pomocí:
php server.php
Zde je skript, který chci spustit:
<?php
require 'vendor/autoload.php';
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
class Chat implements MessageComponentInterface
{
protected $clients;
protected $users;
protected $userConnections;
protected $database;
protected $rooms;
public function __construct()
{
$this->clients = new \SplObjectStorage();
$this->users = [];
$this->userConnections = [];
$this->database = new PDO('mysql:host=localhost;dbname=socialapp', 'root', '');
$this->rooms = [];
}
public function onOpen(ConnectionInterface $conn)
{
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
}
public function onMessage(ConnectionInterface $from, $msg)
{
$data = json_decode($msg, true);
if ($data['action'] === 'registerUser') {
$this->registerUser($from, $data['username']);
$this->loadMessages($from, $data['username']);
return;
}
if ($data['action'] === 'createRoom') {
$recipient = $data['recipient'];
$this->createRoom($from, $recipient);
$this->loadPreviousMessages($from, $data['room']);
return;
}
if ($data['action'] === 'sendMessage') {
$room = $data['room'];
$message = $data['message'];
$recipient = $data['recipient'];
$sender = $this->users[$from->resourceId];
if ($this->roomExists($room) && $this->userInRoom($from, $room)) {
$this->sendMessage($room, $sender, $message);
$this->saveMessage($room, $sender, $recipient, $message);
} else {
$this->sendMessage($room, $sender, "Room not found or you are not a member of the room: {$room}");
}
return;
}
}
public function onClose(ConnectionInterface $conn)
{
$this->clients->detach($conn);
$this->removeUser($conn);
$this->leaveRoom($conn);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e)
{
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
protected function registerUser(ConnectionInterface $conn, $username)
{
$this->users[$conn->resourceId] = $username;
$this->userConnections[$username] = $conn;
echo "User {$username} registered\n";
$this->loadMessages($conn, $username); // Load messages for the user
}
protected function removeUser(ConnectionInterface $conn)
{
if (isset($this->users[$conn->resourceId])) {
$username = $this->users[$conn->resourceId];
unset($this->users[$conn->resourceId]);
unset($this->userConnections[$username]);
echo "User {$username} removed\n";
}
}
protected function createRoom(ConnectionInterface $conn, $recipient)
{
$sender = $this->users[$conn->resourceId];
$room = $this->generateRoomId($sender, $recipient);
if (!$this->roomExists($room)) {
$this->rooms[$room] = new \SplObjectStorage();
}
$this->rooms[$room]->attach($conn);
$conn->room = $room;
echo "Room created: {$room}\n";
}
protected function leaveRoom(ConnectionInterface $conn)
{
if (isset($conn->room) && isset($this->rooms[$conn->room])) {
$this->rooms[$conn->room]->detach($conn);
echo "Connection {$conn->resourceId} has left room: {$conn->room}\n";
}
}
protected function roomExists($room)
{
return isset($this->rooms[$room]);
}
protected function userInRoom(ConnectionInterface $conn, $room)
{
return isset($conn->room) && $conn->room === $room;
}
protected function generateRoomId($userId1, $userId2)
{
$userIds = [$userId1, $userId2];
sort($userIds);
return implode('_', $userIds);
}
protected function sendMessage($room, $sender, $message)
{
foreach ($this->rooms[$room] as $client) {
if ($client !== $sender) {
$client->send(json_encode([
'sender' => $sender,
'message' => $message
]));
}
}
}
protected function saveMessage($room, $sender, $recipient, $message)
{
$query = "INSERT INTO messages (room, sender, recipient, message) VALUES (:room, :sender, :recipient, :message)";
$statement = $this->database->prepare($query);
$statement->bindValue(':room', $room);
$statement->bindValue(':sender', $sender);
$statement->bindValue(':recipient', $recipient);
$statement->bindValue(':message', $message);
$statement->execute();
}
protected function loadPreviousMessages(ConnectionInterface $connection, string $roomID){
$query = "SELECT sender, message, room FROM messages WHERE room = :room";
$statement = $this->database->prepare($query);
$statement->bindValue(':room', $roomID);
$statement->execute();
$messages = $statement->fetchAll(PDO::FETCH_ASSOC);
foreach ($messages as $message) {
$sender = $message['sender'];
$content = $message['message'];
$room = $message['room'];
if ($this->userInRoom($connection, $room)) {
$connection->send(json_encode([
'sender' => $sender,
'message' => $content
]));
}
}
}
protected function loadMessages(ConnectionInterface $conn, $username)
{
$query = "SELECT sender, message, room FROM messages WHERE recipient = :username";
$statement = $this->database->prepare($query);
$statement->bindValue(':username', $username);
$statement->execute();
$messages = $statement->fetchAll(PDO::FETCH_ASSOC);
foreach ($messages as $message) {
$sender = $message['sender'];
$content = $message['message'];
$room = $message['room'];
if ($this->userInRoom($conn, $room)) {
$conn->send(json_encode([
'sender' => $sender,
'message' => $content
]));
}
}
}
}
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
echo "Server started\n";
$server->run();
- Marek Bartoš
- Nette Blogger | 1274
Nette ti ho samo nespustí, ale můžeš si jej snadno integrovat do DI, zhruba takto.
Neon
services:
- Ratchet\Server\IoServer::factory(
Ratchet\Http\HttpServer(
Ratchet\WebSocket\WsServer(
App\Example\Chat()
)
),
8080
)
Spouštěcí skript, např. /bin/websocket-server
#!/usr/bin/env php
<?php declare(strict_types = 1);
use App\Bootstrap;
use Ratchet\Server\IoServer;
require __DIR__ . '/../vendor/autoload.php';
$configurator = Bootstrap::boot();
$container = $configurator->createContainer();
$server = $container->getByType(IoServer::class);
$server->run();