這里寫問題描述
框架,結合了thinkphp和workerman的優(yōu)點,采用容器作為管理,將流程 分為 初始化,啟動,運行。三個階段。
每個階段均用接口進行了抽象,可以無縫追加業(yè)務和切換運行模式。階段內部均有事件支持,比如多語言加載事件,內容發(fā)送前,發(fā)送后事件。
目前 還是控制器解析部分沒有完成了。本人開發(fā)了大半了,
真的累,很多包說是可以無縫使用,其實有很多隱藏的bug并不適合worker的運行方式。
此前一直用springboot開發(fā),就想著把約定大于配置這一套帶到php去,而且現(xiàn)在的php也支持Attribute了,也希望這個特性能充分利用起來
比如我自己實現(xiàn)的容器管理,已經實現(xiàn)了自動注入#[Autowried] 和#[GetConfig]兩個了
有閑心的大佬可以評論區(qū)留言,拿去接著開發(fā)~
這是啟動類,也是一切的入口。
<?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: 應用類
*
* @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 啟動器
* @property Runner $runner 運行器
*/
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,
// 加載內置函數(shù)
LoadBuiltinFunctions::class,
// 加載配置文件
LoadConfigFiles::class,
// 合并環(huán)境配置到全局配置
MergeEnvConfigs::class,
// 初始化應用狀態(tài)
AppStatusInit::class,
];
// 啟動
protected array $bootstraps = [
// 加載容器配置
LoadProviders::class,
// 加載事件配置
LoadEvents::class,
// 加載系統(tǒng)多語言
LoadSystemLang::class,
// 加載多語言
LoadLang::class,
];
// 運行
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: 設置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: 設置時區(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: 啟動
*/
public function appBoot(): self
{
try {
// 啟動器開始事件
$this->event->trigger(BeforeBootstrap::class);
// 啟動
$this->boostrap->dispatcher();
// 應用啟動
$this->getRunClass()->appBoot();
// 啟動器結束
$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: 設置運行類
*/
public function setRunClass(string|AppInterface $runClass): self
{
$this->set(AppInterface::class, $runClass);
return $this;
}
/**
* @Data: 2023/2/7
* @Author: WasonCheung
* @Description: 運行
*/
public function appRun(): void
{
try {
// 應用開始
$this->event->trigger(BeforeAppRun::class);
// 啟動鏈
$this->runner->dispatcher();
// 應用運行
$this->getRunClass()->appRun();
// 應用結束
$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: 設置運行器
*/
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: 設置啟動器
*/
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);
}
// 注冊應用容器
$this
->set($this->getProviders())
->set($this->getRunClass()->getProviders());
// 注冊全局事件
$this->event
->pushListeners($this->getListeners())
->pushListeners($this->getRunClass()->getListeners())
->trigger(BeforeInitialize::class);
// 調用初始化器
$this->initializer->dispatcher();
// 應用初始化
$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: 設置環(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: 設置路徑
*/
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: 設置容器
*/
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: 設置事件
*/
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: 設置
*/
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);
}
}