這里寫問題描述
框架,結(jié)合了thinkphp和workerman的優(yōu)點(diǎn),采用容器作為管理,將流程 分為 初始化,啟動(dòng),運(yùn)行。三個(gè)階段。
每個(gè)階段均用接口進(jìn)行了抽象,可以無縫追加業(yè)務(wù)和切換運(yùn)行模式。階段內(nèi)部均有事件支持,比如多語言加載事件,內(nèi)容發(fā)送前,發(fā)送后事件。
目前 還是控制器解析部分沒有完成了。本人開發(fā)了大半了,
真的累,很多包說是可以無縫使用,其實(shí)有很多隱藏的bug并不適合worker的運(yùn)行方式。
此前一直用springboot開發(fā),就想著把約定大于配置這一套帶到php去,而且現(xiàn)在的php也支持Attribute了,也希望這個(gè)特性能充分利用起來
比如我自己實(shí)現(xiàn)的容器管理,已經(jīng)實(shí)現(xiàn)了自動(dòng)注入#[Autowried] 和#[GetConfig]兩個(gè)了
有閑心的大佬可以評(píng)論區(qū)留言,拿去接著開發(fā)~
這是啟動(dòng)類,也是一切的入口。
<?php
declare(strict_types=1);
namespace panda;
use panda\Bootstraps\LoadEvents;
use panda\Bootstraps\LoadLang;
use panda\Bootstraps\LoadProviders;
use panda\Bootstraps\LoadSystemLang;
use panda\container\Container;
use panda\Contract\AppInterface;
use panda\Events\AfterAppRun;
use panda\Events\AfterBoostrap;
use panda\Events\AfterInitialize;
use panda\Events\BeforeAppRun;
use panda\Events\BeforeBootstrap;
use panda\Events\BeforeInitialize;
use panda\Exception\AppRunException;
use panda\Exception\BootstrapException;
use panda\Exception\InitializerException;
use panda\Initializers\AppStatusInit;
use panda\Initializers\LoadBuiltinFunctions;
use panda\Initializers\LoadConfigFiles;
use panda\Initializers\LoadEnvFiles;
use panda\Initializers\LoadFunctions;
use panda\Initializers\MergeEnvConfigs;
/**
* @Data: 2023/2/7
* @Author: WasonCheung
* @Description: 應(yīng)用類
*
* @property Config $config 配置 down
* @property Env $env 配置環(huán)境 down
* @property Event $event 事件管理 down
* @property Path $path 路徑信息 down
* @property Classes $classes 系統(tǒng)信息 down
* @property Lang $lang 多語言 down
* @property Log $log 日志 down
* @property Cache $cache 緩存 down
* @property ErrorHandler $errorHandler 異常處理
* @property Initializer $initializer 初始化器
* @property Boostrap $boostrap 啟動(dòng)器
* @property Runner $runner 運(yùn)行器
*/
class Panda extends Container implements AppInterface
{
// debug
protected static bool $debug = false;
// 容器別名
protected array $providers = [
'config' => Config::class,
'env' => Env::class,
'event' => Event::class,
'path' => Path::class,
'classes' => Classes::class,
'panda' => Panda::class,
'lang' => Lang::class,
'log' => Log::class,
'cache' => Cache::class,
'errorHandler' => ErrorHandler::class,
'initializer' => Initializer::class,
'boostrap' => Boostrap::class,
'runner' => Runner::class,
];
// 初始化器
protected array $initializers = [
// 環(huán)境配置加載
LoadEnvFiles::class,
// 加載公共函數(shù)
LoadFunctions::class,
// 加載內(nèi)置函數(shù)
LoadBuiltinFunctions::class,
// 加載配置文件
LoadConfigFiles::class,
// 合并環(huán)境配置到全局配置
MergeEnvConfigs::class,
// 初始化應(yīng)用狀態(tài)
AppStatusInit::class,
];
// 啟動(dòng)
protected array $bootstraps = [
// 加載容器配置
LoadProviders::class,
// 加載事件配置
LoadEvents::class,
// 加載系統(tǒng)多語言
LoadSystemLang::class,
// 加載多語言
LoadLang::class,
];
// 運(yùn)行
protected array $runners = [];
// 事件
protected array $listeners = [];
/**
* @return bool
* @Data: 2023/2/11
* @Author: WasonCheung
* @Description: 是否是debug
*/
public static function isDebug(): bool
{
return self::$debug;
}
/**
* @param bool $debug
* @return $this
* @Data: 2023/2/13
* @Author: WasonCheung
* @Description: 設(shè)置debug狀態(tài)
*/
public function setDebug(bool $debug): self
{
self::$debug = $debug;
return $this;
}
/**
* @param string $timezone
* @return $this
* @Data: 2023/2/13
* @Author: WasonCheung
* @Description: 設(shè)置時(shí)區(qū)
*/
public function setTimezone(string $timezone): self
{
date_default_timezone_set($timezone);
return $this;
}
/**
* @return $this
* @throws AppRunException
* @throws \Throwable
* @Data: 2023/2/12
* @Author: WasonCheung
* @Description: 啟動(dòng)
*/
public function appBoot(): self
{
try {
// 啟動(dòng)器開始事件
$this->event->trigger(BeforeBootstrap::class);
// 啟動(dòng)
$this->boostrap->dispatcher();
// 應(yīng)用啟動(dòng)
$this->getRunClass()->appBoot();
// 啟動(dòng)器結(jié)束
$this->event->trigger(AfterBoostrap::class);
} catch (\Throwable $e) {
$this->errorHandler->resolve(new BootstrapException($e));
}
return $this;
}
/**
* @return AppInterface
*/
public function getRunClass(): AppInterface
{
if (!$this->has(AppInterface::class)) {
$this->setRunClass(Command::class);
}
return $this->get(AppInterface::class);
}
/**
* @param string $runClass
* @return $this
* @Data: 2023/2/13
* @Author: WasonCheung
* @Description: 設(shè)置運(yùn)行類
*/
public function setRunClass(string|AppInterface $runClass): self
{
$this->set(AppInterface::class, $runClass);
return $this;
}
/**
* @Data: 2023/2/7
* @Author: WasonCheung
* @Description: 運(yùn)行
*/
public function appRun(): void
{
try {
// 應(yīng)用開始
$this->event->trigger(BeforeAppRun::class);
// 啟動(dòng)鏈
$this->runner->dispatcher();
// 應(yīng)用運(yùn)行
$this->getRunClass()->appRun();
// 應(yīng)用結(jié)束
$this->event->trigger(AfterAppRun::class);
} catch (\Throwable $e) {
$this->errorHandler->resolve(new AppRunException($e));
}
}
/**
* @return array
* @Data: 2023/2/17
* @Author: WasonCheung
* @Description: 獲取
*/
public function getRunners(): array
{
return $this->runners;
}
/**
* @param array $runners
* @return $this
* @Data: 2023/2/17
* @Author: WasonCheung
* @Description: 設(shè)置運(yùn)行器
*/
public function setRunners(array $runners): self
{
$this->runners = $runners;
return $this;
}
/**
* @return array|string[]
* @Data: 2023/2/17
* @Author: WasonCheung
* @Description: 獲取
*/
public function getBootstraps(): array
{
return $this->bootstraps;
}
/**
* @param array $bootstraps
* @Data: 2023/2/17
* @Author: WasonCheung
* @Description: 設(shè)置啟動(dòng)器
*/
public function setBootstraps(array $bootstraps): void
{
$this->bootstraps = $bootstraps;
}
/**
* @return $this
* @throws AppRunException
* @throws \Throwable
* @Data: 2023/2/12
* @Author: WasonCheung
* @Description: 初始化
*/
public function appInit(): self
{
try {
ini_set('display_errors', 'on');
error_reporting(E_ALL);
// 環(huán)境配置初始化
if (!$this->has(Env::class)) {
$this->setEnv('dev');
}
// 路徑初始化
if (!$this->has(Path::class)) {
$this->setPath(\dirname(__DIR__, 3) . DIRECTORY_SEPARATOR);
}
// 注冊(cè)應(yīng)用容器
$this
->set($this->getProviders())
->set($this->getRunClass()->getProviders());
// 注冊(cè)全局事件
$this->event
->pushListeners($this->getListeners())
->pushListeners($this->getRunClass()->getListeners())
->trigger(BeforeInitialize::class);
// 調(diào)用初始化器
$this->initializer->dispatcher();
// 應(yīng)用初始化
$this->getRunClass()->appInit();
$this->event->trigger(AfterInitialize::class);
} catch (\Throwable $e) {
$this->errorHandler->resolve(new InitializerException($e));
}
return $this;
}
/**
* @param string|Env $env
* @return $this
* @Data: 2023/2/13
* @Author: WasonCheung
* @Description: 設(shè)置環(huán)境變量
*/
public function setEnv(string|Env $env): self
{
$this->set(Env::class, $env instanceof Env ? $env : [$env]);
return $this;
}
/**
* @param string|Path $path
* @return $this
* @Data: 2023/2/13
* @Author: WasonCheung
* @Description: 設(shè)置路徑
*/
public function setPath(string|Path $path): self
{
$this->set(Path::class, $path instanceof Path ? $path : [$path]);
return $this;
}
/**
* @return array|string[]
* @Data: 2023/2/17
* @Author: WasonCheung
* @Description: 獲取容器定義
*/
public function getProviders(): array
{
return $this->providers;
}
/**
* @param array $providers
* @Data: 2023/2/17
* @Author: WasonCheung
* @Description: 設(shè)置容器
*/
public function setProviders(array $providers): void
{
$this->providers = array_merge($this->providers, $providers);
}
/**
* @return array
* @Data: 2023/2/17
* @Author: WasonCheung
* @Description: 獲取監(jiān)聽器
*/
public function getListeners(): array
{
return $this->listeners;
}
/**
* @param array $listeners
* @return $this
* @Data: 2023/2/17
* @Author: WasonCheung
* @Description: 設(shè)置事件
*/
public function setListeners(array $listeners): self
{
$this->listeners = $listeners;
return $this;
}
/**
* @return array|string[]
* @Data: 2023/2/17
* @Author: WasonCheung
* @Description: 初始化器
*/
public function getInitializers(): array
{
return $this->initializers;
}
/**
* @param array $initializers
* @return $this
* @Data: 2023/2/17
* @Author: WasonCheung
* @Description: 設(shè)置
*/
public function setInitializers(array $initializers): self
{
$this->initializers = $initializers;
return $this;
}
public function __get(string $name)
{
return $this->get($name);
}
public function __set(string $name, $value): void
{
$this->set($name, $value);
}
}