问题描述
我正在开发一个记分卡应用程序,其中某些成员正在玩,并且可以在图表中更新他们的分数,这也需要反映在团队成员屏幕中。
为此,我使用了 cboden/ratchet
。
每个团队都有一个通用的团队代码,我将使用 URL localhost:8000/{token}
传递该代码,该代码将从控制器传递到 twig。
我有以下命令:
$server = IoServer::factory(
new HttpServer(
new WsServer(
new scoreHandler()
)
),8080
);
$server->run();
scoreHandler
public function __construct(EntityManagerInterface $entityManager)
{
$this->connections = new SplObjectStorage;
$this->entityManager = $entityManager;
}
这会返回 Too few arguments to function App\Websocket\scoreHandler::__construct(),0 passed
错误。
我不知道如何在此处修复此错误。因为我打算插入数据库并根据令牌获取记录并返回到某个用户组。
有人可以帮我吗?
解决方法
注意事项
强烈建议不要将 PHP 与 Symfony 和/或 Doctrine 一起用于任何长时间运行的后台进程(守护进程),它侦听 WebSocket(或其他)连接,在任何生产/现实世界中使用 Ratchet/ReactPHP 风格的功能环境。 PHP 并非设计为作为守护程序运行。因此,如果没有适当的计划,该过程将因 Doctrine Connection 异常和 MySQL Server Has Gone Away 错误或由维护实体管理器、Symfony 服务定义和记录器溢出而导致的内存泄漏而崩溃。
使用 PHP 作为守护进程需要实施不直观的解决方法,例如 Messenger Queue(导致响应之间的长时间延迟)或 Lazy Proxy objects(导致代码级可维护性问题)和额外的后台进程,如主管和/或 cron 作业来规避固有问题并从崩溃中恢复。
如果您对 config/services.yaml 使用默认的 autowire
配置并且 ScoreHandler
不在排除路径之一中,则以下选项可以使用依赖项注入。
# 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
即服务
推荐的方法是将 ScoreHandler
服务注入到命令中,这也会自动将 EntityManagerInterface
注入到 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
并传递给ScoreHandler
由于您要手动创建 ScoreHandler
的新实例,因此需要将 EntityManagerInterface
作为参数提供给构造函数。
不推荐这样做,因为已经存在一个服务,并且如前一个示例中那样已经自动装配。
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();
}
}
NodeJS 替代方案
虽然 PHP 不是作为守护进程设计的,但 nodejs 和其他几个平台能够促进监听连接。它们可用于将请求转发到您的 Symfony Web 应用程序并将响应发送回客户端,作为请求代理。
有关 WebSocket 代理服务的示例,请参阅 https://stackoverflow.com/a/68027150/1144627。