busarm/armie

一个优雅的PHP框架,旨在提供高性能并优化开发者体验

v2.0.9 2023-09-18 16:20 UTC

This package is auto-updated.

Last update: 2024-09-19 07:11:07 UTC


README

Armie_Logo_256px

Test Test Latest Stable Version PHP Version Require

目录

简介

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服务器,支持多个事件循环提供者,如:swoolelibeventevlibuvreact。提供以下功能

  • 后台工作进程处理多进程、异步任务和定时任务处理
  • 套接字工作进程处理Web套接字连接
  • 使用Promise和内置(asyncawaitconcurrent)函数进行并发
  • 使用内置(listendispatch)函数处理实时事件
  • 使用内置(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.phpmyapp/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许可证。有关更多信息,请参阅许可证文件