- 作為一個PHPer一直思考PHP怎麼做高效能(個人基礎比較弱),怎麼微服務,之前真不知道,不是概念而是怎麼落地,談概念有用但是不落地有點扯
- Swoole沒有實際專案用過,swoole相關框架也沒了解過也不知道,獲取知道了可能對於之前的問題就可能有一些答案了
- Hyperf的出現簡直就是太及時了,文件清晰,框架靈活等等等,簡直不要太好
- 雖然Hyperf已經這麼好了,但是還是希望把它稍微按著自己喜歡的規範改造一下,這裡就把多有對它的改造都定義為自己的開發規範,如果大家覺得有道理可以沿用
- 感謝swoole團隊(韓老師等……),感謝Hyperf團隊(黃老師等……)
工欲善其事,必先利其器,它有個名字
HyperfCMS
-
定義目錄結構
├─app 應用目錄 │ …… 框架其它目錄 │ ├─Core 核心目錄(都在這裡面)框架的修改,業務的核心都放在這個目錄下處理 │ │ ├─Facade 服務容器中可用的類提供了一個「靜態」介面的類放在這個地方 │ │ ├─HF hyperf框架相關修改放於此 │ │ ├─LogHandler 日誌處理 │ │ ├─Repositories 倉庫目錄,業務邏輯處理,區分業務模組 │ │ │ ├─Admin 後臺業務 │ │ │ ├─Home 前臺業務 │ │ │ ├─Api 介面業務 │ │ ├─Services 服務目錄,業務邏輯處理,所有業務模組公用 │ │ ├─common.php 公共函式檔案 │ │ ├─Response.php 統一響應處理出口
-
呼叫邏輯設計
- 控制器----->倉庫----->服務----->模型(Model),解釋:http請求過來,通過路由找到控制器,控制器找到對應的倉庫,倉庫找到對應的服務,服務找到對應的模型,注意:為了規範,倉庫不可直接操作模型。
- 雖然hyperf提供了多種方法注入,但是個人覺的還是比較麻煩,如果引用類過多需要寫很多看著沒有實際用途的程式碼。所以進行了修改,隱式注入。
- 隱式注入需要遵循約定的規範,如下:
- Controller需要繼承BaseController,且如果用到哪個倉庫需要在註釋裡
@property \APP\Core\Repositories\TestRepository $testRepo
目的是可以讓phpstorm可以函式間跳轉。- 控制器呼叫倉庫的變數需要
Repo
或Repository
結尾,如:$testRepo
- 倉庫的命名必須用Repository結尾,如:
TestRepository
,需要繼承BaseRepository,如果用到服務需要@property \APP\Core\Services\TestService $testService
目的是可以讓phpstorm可以函式間跳轉- 倉內呼叫服務的變數需要
Service
結尾,如:$testService
- 服務的命名必須用Service結尾,如:
TestService
,需要繼承BaseService,如果用到model需要@property \APP\Models\Category $categoryModel
, 目的是可以讓phpstorm可以函式間跳轉。- 服務呼叫model的變數需要
Model
結尾,如:$categoryModel
-
貼程式碼
class BaseController extends AbstractController { /** * __get * 隱式注入倉庫類 * User:YM * Date:2019/11/21 * Time:上午9:27 * @param $key * @return \Psr\Container\ContainerInterface|void */ public function __get($key) { if ($key == 'app') { return $this->container; } else { $suffix = strstr($key,'Repo'); if ($suffix && ($suffix == 'Repo' || $suffix == 'Repository')) { $repoName = $suffix == 'Repo' ? $key.'sitory':$key; return $this->getRepositoriesInstance($repoName); } else { throw new \RuntimeException("倉庫{$key}不存在,書寫錯誤!", StatusCode::ERR_SERVER); } } /** * getRepositoriesInstance * 獲取倉庫類例項 * User:YM * Date:2019/11/21 * Time:上午10:30 * @param $key * @return mixed */ public function getRepositoriesInstance($key) { $key = ucfirst($key); $module = $this->getModuleName(); if (!empty($module)) { $module = "{$module}"; } else { $module = ""; } if ($module) { $filename = BASE_PATH."/app/Core/Repositories/{$module}/{$key}.php"; $classname = "App\\Core\\Repositories\\{$module}\\{$key}"; } else { $filename = BASE_PATH."/app/Core/Repositories/{$key}.php"; $classname = "App\\Core\\Repositories\\{$key}"; } if (file_exists($filename)) { return $this->container->get($classname); } else { throw new \RuntimeException("倉庫{$key}不存在,檔案不存在!", StatusCode::ERR_SERVER); } } /** * getModuleName * 獲取所屬模組 * User:YM * Date:2019/11/21 * Time:上午9:32 * @return string */ private function getModuleName() { $classname = get_called_class(); $name = substr($classname, 15); $space = explode('\\', $name); if(count($space) > 1){ return $space[0]; }else{ return ''; } } }
/** * IndexController * 類簡介 * @package App\Controller * User:YM * Date:2019/11/12 * Time:下午5:03 * @property \APP\Core\Repositories\TestRepository $testRepo */ class IndexController extends BaseController { public function index() { $this->testRepo->test(); } }
namespace App\Core\Repositories; use Psr\Container\ContainerInterface; use Hyperf\Di\Annotation\Inject; use App\Constants\StatusCode; /** * BaseRepository * 倉庫基類 * @package App\Core\Repositories * User:YM * Date:2019/11/21 * Time:下午2:36 */ class BaseRepository { /** * @Inject * @var ContainerInterface */ protected $container; /** * __get * 隱式注入服務類 * User:YM * Date:2019/11/21 * Time:上午9:27 * @param $key * @return \Psr\Container\ContainerInterface|void */ public function __get($key) { if ($key == 'app') { return $this->container; } elseif (substr($key, -7) == 'Service') { return $this->getServiceInstance($key); } else { throw new \RuntimeException("服務{$key}不存在,書寫錯誤!", StatusCode::ERR_SERVER); } } /** * getServiceInstance * 獲取服務類例項 * User:YM * Date:2019/11/21 * Time:上午10:30 * @param $key * @return mixed */ public function getServiceInstance($key) { $key = ucfirst($key); $fileName = BASE_PATH."/app/Core/Services/{$key}.php"; $className = "App\\Core\\Services\\{$key}"; if (file_exists($fileName)) { return $this->container->get($className); } else { throw new \RuntimeException("服務{$key}不存在,檔案不存在!", StatusCode::ERR_SERVER); } } }
namespace App\Core\Repositories; /** * TestRepository * 類的介紹 * @package App\Core\Repositories * User:YM * Date:2019/11/21 * Time:上午10:25 * @property \APP\Core\Services\TestService $testService */ class TestRepository extends BaseRepository { public function test() { $tmp = $this->testService->test(); return $tmp; } }
namespace App\Core\Services; use Psr\Container\ContainerInterface; use Hyperf\Di\Annotation\Inject; use App\Constants\StatusCode; /** * BaseService * 服務基類 * @package App\Core\Services * User:YM * Date:2019/11/21 * Time:下午3:21 */ class BaseService { /** * @Inject * @var ContainerInterface */ protected $container; /** * __get * 隱式注入服務類 * User:YM * Date:2019/11/21 * Time:上午9:27 * @param $key * @return \Psr\Container\ContainerInterface|void */ public function __get($key) { if ($key == 'app') { return $this->container; } elseif (substr($key, -5) == 'Model') { $key = strstr($key,'Model',true); return $this->getModelInstance($key); } elseif (substr($key, -7) == 'Service') { return $this->getServiceInstance($key); } else { throw new \RuntimeException("服務/模型{$key}不存在,書寫錯誤!", StatusCode::ERR_SERVER); } } /** * getModelInstance * 獲取資料模型類例項 * User:YM * Date:2019/11/21 * Time:上午10:30 * @param $key * @return mixed */ public function getModelInstance($key) { $key = ucfirst($key); $fileName = BASE_PATH."/app/Models/{$key}.php"; $className = "App\\Models\\{$key}"; if (file_exists($fileName)) { return $this->container->get($className); } else { throw new \RuntimeException("服務/模型{$key}不存在,檔案不存在!", StatusCode::ERR_SERVER); } } /** * getServiceInstance * 獲取服務類例項 * User:YM * Date:2019/11/21 * Time:上午10:30 * @param $key * @return mixed */ public function getServiceInstance($key) { $key = ucfirst($key); $fileName = BASE_PATH."/app/Services/{$key}.php"; $className = "App\\Services\\{$key}"; if (file_exists($fileName)) { return $this->container->get($className); } else { throw new \RuntimeException("服務/模型{$key}不存在,檔案不存在!", StatusCode::ERR_SERVER); } } }
namespace App\Core\Services;
/**
- TestServices
- 類的介紹
- @package App\Services
- User:YM
- Date:2019/11/21
- Time:下午2:46
- @property \APP\Models\Category $categoryModel
*/
class TestService extends BaseService
{
public function test()
{
$tmp = $this->categoryModel->getList();
return $tmp;
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結