I am developing a scorecard application where certain group of members are playing and can update their score in chart which needs to be reflected in team members screen too.
For this purpose I am using cboden/ratchet
.
Each team have a common team code which I will pass using URL localhost:8000/{token}
which will be passed from controller to twig.
I have following in command:
$server = IoServer::factory(
new HttpServer(
new WsServer(
new ScoreHandler()
)
),
8080
);
$server->run();
public function __construct(EntityManagerInterface $entityManager)
{
$this->connections = new SplObjectStorage;
$this->entityManager = $entityManager;
}
This returns me Too few arguments to function App\Websocket\ScoreHandler::__construct(), 0 passed
error.
I am not sure how to fix this error here. As I am planning to insert into the db and fetch records based on token and return to certain user group.
Can anybody help me ?
It is strongly discouraged from using PHP with Symfony and/or Doctrine for any long-running background processes (daemon), that listens for WebSocket (or other) connections, using Ratchet/ReactPHP style features in any production/real-world environments. PHP was not designed to run as a daemon. As such, without proper planning, the process will crash with either a Doctrine Connection exception with the MySQL Server Has Gone Away error or from memory leaks caused by maintaining the Entity Manager, Symfony service definitions and logger overflows.
Using PHP as a daemon would require implementing unintuitive workarounds, such as a Messenger Queue (causes long delays between responses) or Lazy Proxy objects (causes code-level maintainability issues) and additional background processes, like supervisor and/or cron jobs to circumvent the inherent issues and recover from crashes.
Provided you are using the default autowire
configuration for your config/services.yaml and ScoreHandler
is not in one of the excluded paths, the following options are feasible using dependency injection.
# config/services.yaml
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# ...
ScoreHandler
as a ServiceThe recommended approach is to inject the ScoreHandler
service into the command, which will also automatically inject the EntityManagerInterface
into the ScoreHandler
.
class YourCommand extends Command
{
private $handler;
public function __construct(ScoreHandler $handler)
{
$this->handler = $handler;
parent::__construct();
}
//...
public function execute(InputInterface $input, OutputInterface $outpu)
{
//...
$server = IoServer::factory(
new HttpServer(
new WsServer($this->handler)
),
8080
);
$server->run();
}
}
EntityManagerInterface
and pass to ScoreHandler
Since you are creating a new instance of ScoreHandler
manually, it requires the EntityManagerInterface
to be supplied as an argument to the constructor.
This is not recommended, as a service already exists that is already autowired as in the previous example.
class YourCommand extends Command
{
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
parent::__construct();
}
//...
public function execute(InputInterface $input, OutputInterface $outpu)
{
//...
$server = IoServer::factory(
new HttpServer(
new WsServer(
new ScoreHandler($this->em)
)
),
8080
);
$server->run();
}
}
While PHP was not designed as a daemon, nodejs and several other platforms are able to facilitate listening for connections. They can be used to forward the request to your Symfony web application and send a response back to the client, as a request broker.
See https://stackoverflow.com/a/68027150/1144627 for an example of a WebSocket Broker Service.