busarm / armie
一个优雅的PHP框架,旨在提供高性能并优化开发者体验
v2.0.9
2023-09-18 16:20 UTC
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.5
- laravel/serializable-closure: ^1.3
- nyholm/psr7: ^1.5
- psr/cache: ^3.0
- psr/container: ^2.0
- psr/http-message: ^1.0
- psr/http-server-middleware: ^1.0
- psr/log: ^2.0
- symfony/console: ^6.0
- symfony/process: ^6.0
- workerman/workerman: ^4.1
Requires (Dev)
- fakerphp/faker: ^1.20
- middlewares/firewall: ^2.0
- phpstan/phpstan: ^1.8
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: 3.*
README
目录
简介
Armie是一个具有表现力和可扩展性的轻量级PHP框架,旨在提供高性能,同时具备快速应用开发所需的所有基本功能。
它更适合小型应用或微服务,但可以轻松处理需要最小扩展或抽象的大型应用开发。
它支持不同的设计范式和架构模式
- 模型-视图-控制器 (MVC)
- 面向服务
- 微服务
- 事件驱动
- 异步队列
安装
composer require busarm/armie
使用
传统HTTP服务器
使用PHP-FPM和NGINX或Apache的传统HTTP服务器。
单应用
运行单个应用
# ../myapp/public/index.php define('APP_START_TIME', floor(microtime(true) * 1000)); require __DIR__ . '/../vendor/autoload.php'; $config = (new Config()) ->setAppPath(dirname(__DIR__)) ->setConfigPath('Configs') ->setViewPath('Views'); $app = new App($config); $app->get('/product/{id}')->to(ProductController::class, 'get'); $app->run()->send();
多租户应用
托管多个应用或模块。支持路径和域名路由
# ../index.php require __DIR__ . '/../vendor/autoload.php'; $server = (new Server()) // Use `myapp` for requests with path `v1/....` ->addRoutePath('v1', __DIR__ . '/myapp/public') // Use `mydevapp` for requests with domain name `dev.myapp.com` ->addDomainPath('dev.myapp.com', __DIR__ . '/mydevapp/public'); $server->run()->send(); # ../myapp/public/index.php /** * @var \Psr\Http\Message\ServerRequestInterface|null $request Capture Server request * @var \Armie\Interfaces\ServiceDiscoveryInterface|null $discovery Capture Service discovery */ require __DIR__ . '/../vendor/autoload.php'; $config = (new Config()) ->setAppPath(dirname(__DIR__)) ->setConfigPath('Configs') ->setViewPath('Views'); $app = new App($config); $app->setServiceDiscovery($discovery ?? new LocalServiceDiscovery([])); $app->get('/product/{id}')->to(ProductController::class, 'get'); return $app->run(Request::capture($request ?? null, $config));
异步HTTP服务器 (由 workerman 提供)
高性能异步HTTP服务器,支持多个事件循环提供者,如:swoole
、libevent
、ev
、libuv
、react
。提供以下功能
- 后台工作进程处理多进程、异步任务和定时任务处理
- 套接字工作进程处理Web套接字连接
- 使用Promise和内置(
async
、await
、concurrent
)函数进行并发 - 使用内置(
listen
、dispatch
)函数处理实时事件 - 使用内置(
enqueue
)函数处理异步队列
# ./start.php $config = (new Config()) ->setAppPath(dirname(__DIR__)) ->setConfigPath('Configs') ->setViewPath('Views'); $app = new App($config); $app->get('/product/{id}')->to(ProductController::class, 'get'); $app->start("localhost", 8080, (new HttpServerConfig) ->setLooper(Looper::EV) ->setHttpWorkers(8) ->setTaskWorkers(4) ->addJob(function () { log_debug("Testing EVERY_MINUTE Cron Job"); }, Cron::EVERY_MINUTE) ->addJob(function () { log_debug("Testing Custom Seconds Cron Job"); }, 600) ->addJob(function () { log_debug("Testing One-Time Only Job"); }, (new DateTime('+30 seconds'))) // MessengerSocketController implements SocketControllerInterface ->addSocket(2222, MessengerSocketController::class));
运行命令以启动应用
# Windows php start.php # Unix (Linux or Mac) [Recommended] php start.php start
配置
配置应用
$config = (new Config()) ->setAppPath(__DIR__) ->setConfigPath('Configs') ->setViewPath('Views') ->setSecret("mysamplesecret123456") ->setCookieEncrypt(true) ->setHttp((new HttpConfig) ->setCheckCors(true) ->setAllowAnyCorsDomain(true) ->setAllowedCorsHeaders(['*']) ->setAllowedCorsMethods(['GET'])) ->setLogRequest(false) ->setSessionEnabled(true) ->setSessionLifetime(60) ->setDb((new PDOConfig) ->setConnectionDriver("mysql") ->setConnectionHost("127.0.0.1") ->setConnectionDatabase('default') ->setConnectionPort(3310) ->setConnectionUsername("root") ->setConnectionPassword("root") ->setConnectionPersist(true) ->setConnectionErrorMode(true) ->setConnectionPoolSize(10) ); $app = new App($config); ...
使用配置文件
可以使用单独的配置文件附加配置。
创建配置文件
将配置文件添加到您的配置路径。例如 myapp/Configs/database.php
# database.php // Use constant define("DB_NAME", "my-db-dev"); define("DB_HOST", "localhost"); // Use dynamic configs return [ 'db_name'=>'my-db-dev', 'db_host'=>'localhost', ]; // Access dynamic configs // Set app()->config->set('db_name', 'my-db-dev-2'); // Get app()->config->get('db_name');
添加配置文件
.... $config->addFile('database') $app = new App($config); ....
路由
添加HTTP路由。
控制器路由
.... $app = new App($config); $app->get('/user/{id}')->to(UserController::class, 'get'); $app->get('/user/{id}')->to(UserController::class, 'get'); $app->post('/user/{id}')->to(UserController::class, 'create'); $app->put('/user/{id}')->to(UserController::class, 'update'), $app->delete('/user/{id}')->to(UserController::class, 'delete'), $app->run()->send();
匿名路由
.... $app = new App($config); $app->get('/user/{id}')->call(function (RequestInterface $request, string $id) { // Perform action ... }); $app->run()->send();
视图路由
.... $app = new App($config); $app->get('/user/{id}')->view(UserPage::class); $app->run()->send();
自定义路由类
.... $app = new App($config); // Using Custom Route Class - Single $app->router->addRoute(MyRoute::get('/user/{id}')->to(UserController::class, 'get')); // Using Custom Route Class - List $app->router->addRoutes([ MyRoute::get('/user/{id}')->to(UserController::class, 'get'), MyRoute::post('/user')->to(UserController::class, 'create'), MyRoute::put('/user/{id}')->to(UserController::class, 'update'), MyRoute::delete('/user/{id}')->to(UserController::class, 'delete'), ]); $app->run()->send();
服务提供者
扩展应用功能和配置。
创建服务提供者
class CustomProvider implements ProviderInterface { /** * @inheritDoc */ public function process(App $app): void { // Perform custom action.... } }
附加服务提供者
... $app = new App($config); $app->addProvider(new CustomProvider()); ...
中间件
拦截HTTP请求和响应。支持PSR中间件。
创建中间件
class AuthenticateMiddleware implements MiddlewareInterface { public function process(RequestInterface|RouteInterface $request, RequestHandlerInterface $handler): ResponseInterface { // Perform custom action.... // Or forward to next request handler return $handler->handle($request); } }
附加中间件
# Attach global middleware .... $app = new App($config); $app->addMiddleware(new AuthenticateMiddleware()) .... # Attach middleware to specific route .... $app->put('/user/{id}')->to(UserController::class, 'update')->middlewares([ new AuthenticateMiddleware() ]); $app->router->addRoute( Route::put('/user/{id}')->to(UserController::class, 'update')->middlewares([ new AuthenticateMiddleware() ]) ); ....
绑定
将接口绑定到特定类。因此,在解析依赖项时将使用指定的类对象。
添加绑定
.... $app = new App($config); $app->addBinding(CacheInterface::class, RedisCache::class) ....
解析绑定
// Manually $cache = app()->make(CacheInterface::class) // Automatically class UserController { public function __construct(private CacheInterface $cache) { } }
视图
通用组件
将视图文件添加到您的视图路径。例如 myapp/Views/login.php
# In Controller (or anywhere you wish to load view) // Using app instance app()->loader->view('login', ['username' => $uname, 'password' => $pass]); // Using helpers view('login', ['username' => $uname, 'password' => $pass]);
专用视图模型
将视图文件添加到您的视图路径。例如 myapp/Views/LoginPage.php
、myapp/Views/components/login.php
# In-line rendering class LoginPage extends View { public function __construct(protected LoginPageDto|BaseDto|array|null $data = null, protected $headers = array()) { } public function render() { $header = new HeaderComponent; return <<<HTML <html> <body> <div>{$header}</div> <div>Username: {$this->get("username")}</div> </body> </html> HTML; } } # Component rendering class LoginPage extends View { public function __construct(protected LoginPageDto|BaseDto|array|null $data = null, protected $headers = array()) { } public function render() { return $this->include('components/login', true); } }
数据库 (Armie ORM)
基于PHP数据对象(PDO)的简单但具有表现力的数据库对象关系映射器(ORM)
定义模型
class ProductModel extends Model { /** * @inheritDoc */ public function getFields(): array { return [ new Field('id', DataType::INT), new Field('name', DataType::STRING), new Field('type', DataType::STRING), new Field('qty', DataType::INT), new Field('categoryId', DataType::INT), new Field('createdAt', DataType::DATETIME), new Field('updatedAt', DataType::DATETIME), new Field('deletedAt', DataType::DATETIME) ]; } /** * @inheritDoc */ public function getRelations(): array { return [ new OneToOne('category', $this, new Reference(CategoryTestModel::class, ['categoryId' => 'id'])) ]; } /** * @inheritDoc */ public function getTableName(): string { return 'products'; } /** * @inheritDoc */ public function getKeyName(): ?string { return 'id'; } /** * @inheritDoc */ public function getCreatedDateName(): ?string { return 'createdAt'; } /** * @inheritDoc */ public function getUpdatedDateName(): ?string { return 'updatedAt'; } /** * @inheritDoc */ public function getSoftDeleteDateName(): ?string { return 'deletedAt'; } }
保存模型
$model = ProductModel::create(['name' => 'IPhone 14', 'qty' => 3, 'type' => 'Mobile Phone', 'categoryId' => 1]); $model = ProductModel::update(1, ['name' => 'IPhone 14', 'qty' => 3, 'type' => 'Mobile Phone', 'categoryId' => 1]); // Or ... $product = new ProductModel; $product->load(['name' => 'IPhone 14', 'qty' => 3, 'type' => 'Mobile Phone', 'categoryId' => 1]); $product->save();
查找项
... $model = ProductModel::findById(1); // Or $model = (new ProductModel)->find(1);
获取列表
... $model = ProductModel::getAll(); // Or $model = (new ProductModel)->all();
定义仓库
class ProductRepository extends Repository { public function __construct() { parent::__construct(new ProductModel); } } // Or - Use Generic Repository $productRepo = new Repository(new ProductModel)
获取分页列表
... $productRepo = new ProductRepository(); $result = $productRepo->paginate(1, 3);
测试
要执行测试套件,您需要安装所有开发依赖项。
$ git clone https://github.com/busarm/armie
$ composer install
$ composer test
您可以使用PHP服务器内置服务器进行测试
$ php -S localhost:8181 -t tests/app/v1
许可证
Armie框架采用MIT许可证。有关更多信息,请参阅许可证文件。