首先看CRMEB駐留內存的bat
start cmd /c php think workerman start chat
start cmd /c php think workerman start admin
start cmd /c php think timer start
php think workerman start channel
程序啓動於think文件
#!/usr/bin/env php
<?php
namespace think;
// 加載基礎文件
require __DIR__ . '/vendor/autoload.php';
// 應用初始化
(new App())->console->run();
CRMEB基於ThinkPHP,ThinkPHP按composer的模式整理了程序的啓動過程,有空的小白應該可能去認真研讀一下autoload.php內部的相關代碼,這樣對學習進程會很有幫助
通過命名空間think找到vendor/topthink/framework/src/think/Console.php文件,Console類中,__construct函數通過loadCommands函數加載了配置
/**
* 加載指令
* @access protected
*/
protected function loadCommands(): void
{
$commands = $this->app->config->get('console.commands', []);
$commands = array_merge($this->defaultCommands, $commands);
$this->addCommands($commands);
}
注意到$this->app->config->get從console.commands讀配置,那配置文件在哪裏呢?這就需要回過頭來研讀一下App.php這個文件了(文章所限,省略掉不重要的代碼)
public function initialize()
{
......
// 加載全局初始化文件
$this->load();
......
}
protected function load(): void
{
......
foreach ($files as $file) {
$this->config->load($file, pathinfo($file, PATHINFO_FILENAME));
}
.....
}
通過代碼得知,程序加載時,即從/config目錄下,把所有配置文件都加載進來,console.commands配置項即是console.php配置文件中的commands配置項。那我們就可以知道,聊天相關的對象是在\crmeb\command\Workerman這個類中。
下面來看一下Workerman類的execute方法,workerServer屬性與chatWorkerServer長連接對象都是Worker對象實例,這個大家要學一下Workerman的資料了:
protected function execute(Input $input, Output $output)
{
$server = $this->init($input, $output);
Worker::$pidFile = app()->getRootPath().'workerman.pid';
if(!$server || $server == 'admin'){
var_dump('admin');
//創建 admin 長連接服務
$this->workerServer = new Worker($this->config['admin']['protocol'] . '://' . $this->config['admin']['ip'] . ':' . $this->config['admin']['port']);
$this->workerServer->count = $this->config['admin']['serverCount'];
}
if(!$server || $server == 'chat') {
var_dump('chat');
//創建 h5 chat 長連接服務
$this->chatWorkerServer = new Worker($this->config['chat']['protocol'] . '://' . $this->config['chat']['ip'] . ':' . $this->config['chat']['port']);
$this->chatWorkerServer->count = $this->config['chat']['serverCount'];
}
if(!$server || $server == 'channel') {
var_dump('channel');
//創建內部通訊服務
$this->channelServer = new Server($this->config['channel']['ip'], $this->config['channel']['port']);
}
$this->bindHandle();
try {
Worker::runAll();
} catch (\Exception $e) {
$output->warning($e->getMessage());
}
}
注意:配置是從$this->config[‘admin’][‘protocol’],查找配置文件的目錄workerman.php配置文件包含了這些配置項,配置項是通過config函數來讀的,config函數是在/vendor/topthink/framework/src/helper.php文件中,也是用Config類讀取配置的
從bindHandle方法中,得知ChatService是接收聊天對話的業務類
protected function bindHandle()
{
if(!is_null($this->workerServer)){
$server = new WorkermanService($this->workerServer, $this->channelServer);
// 連接時回調
$this->workerServer->onConnect = [$server, 'onConnect'];
// 收到客戶端信息時回調
$this->workerServer->onMessage = [$server, 'onMessage'];
// 進程啓動後的回調
$this->workerServer->onWorkerStart = [$server, 'onWorkerStart'];
// 斷開時觸發的回調
$this->workerServer->onClose = [$server, 'onClose'];
}
if(!is_null($this->chatWorkerServer)) {
$chatServer = new ChatService($this->chatWorkerServer, $this->channelServer);
$this->chatWorkerServer->onConnect = [$chatServer, 'onConnect'];
$this->chatWorkerServer->onMessage = [$chatServer, 'onMessage'];
$this->chatWorkerServer->onWorkerStart = [$chatServer, 'onWorkerStart'];
$this->chatWorkerServer->onClose = [$chatServer, 'onClose'];
}
}
/crmeb/service/workerman/chat/ChatService.php文件中,ChatService類用ChatHandle來進行業務相關操作,對於需要進行二次開發的小白來說,可以修改ChatHandle來完善業務功能,我感覺也可以通過傳入的參數調用不同業務對象的功能,這樣才能實現靈活擴展的目的。
好了,就聊到這