tobento/app

创建任何PHP项目的基应用程序。

1.0.7 2023-08-31 15:45 UTC

This package is auto-updated.

Last update: 2024-09-30 01:41:07 UTC


README

创建任何PHP项目的基应用程序。
您可以从App Skeleton开始,在那里您可以找到可用应用程序捆绑包的列表。

目录

入门

运行以下命令以添加应用程序项目的最新版本。

composer require tobento/app

要求

  • PHP 8.0或更高版本

文档

应用程序生命周期

首先,从提供的应用程序工厂创建应用程序。
接下来,在您的应用程序中注册您想要的任何启动。
最后,运行您的应用程序。

use Tobento\App\AppFactory;

// Create the app
$app = (new AppFactory())->createApp();

// Adding boots
$app->boot(\Tobento\App\Boot\App::class);
$app->boot(\Tobento\App\Boot\ErrorHandling::class);

// Run the app
$app->run();

应用程序工厂

use Tobento\App\AppFactory;
use Tobento\App\AppFactoryInterface;
use Tobento\App\AppInterface;
use Tobento\Service\Resolver\ResolverFactoryInterface;
use Tobento\Service\Booting\BooterInterface;
use Tobento\Service\Dir\DirsInterface;

$appFactory = new AppFactory();

var_dump($appFactory instanceof AppFactoryInterface);
// bool(true)

$app = $appFactory->createApp(
    resolverFactory: null, // null|ResolverFactoryInterface
    booter: null, // null|BooterInterface
    dirs: null, // null|DirsInterface
);

var_dump($app instanceof AppInterface);
// bool(true)

参数说明

应用程序解析

PSR-11

use Tobento\App\AppFactory;

class Foo {}

$app = (new AppFactory())->createApp();

var_dump($app->has(Bar::class));
// bool(false)

var_dump($app->get(Foo::class));
// object(Foo)#2 (0) { }

自动装配

应用程序通过自动装配解决任何依赖项,除了内置参数需要定义才能解决。

在联合类型参数上,如果未通过定义设置,则使用第一个可解决的参数。

定义

use Tobento\App\AppFactory;
use Tobento\Service\Resolver\DefinitionInterface;

class Foo
{
    public function __construct(
        protected string $name
    ) {} 
}

$app = (new AppFactory())->createApp();

$definition = $app->set(Foo::class)->construct('name');

var_dump($definition instanceof DefinitionInterface);
// bool(true)

查看Resolver Definitions以了解更多关于定义的一般信息。

制作

use Tobento\App\AppFactory;

class Foo
{
    public function __construct(
        private Bar $bar,
        private string $name
    ) {} 
}

class Bar {}

$app = (new AppFactory())->createApp();

$foo = $app->make(Foo::class, ['name' => 'value']);

查看Resolver Make以了解更多信息。

调用

use Tobento\App\AppFactory;

class Foo
{
    public function index(Bar $bar, string $name): string
    {
        return $name;
    } 
}

class Bar {}

$app = (new AppFactory())->createApp();

$name = $app->call([Foo::class, 'index'], ['name' => 'value']);

var_dump($name);
// string(5) "value"

查看Resolver Call以了解更多信息。

在...上

use Tobento\App\AppFactory;

class AdminUser {}
class GuestUser {}

$app = (new AppFactory())->createApp();

$app->on(AdminUser::class, GuestUser::class);

$user = $app->get(AdminUser::class);

var_dump($user);
// object(GuestUser)#16 (0) { }

查看Resolver On以了解更多信息。

应用程序启动

您可以调用启动方法来启动注册的启动,以便访问其功能,否则它将在运行方法上调用。

use Tobento\App\AppFactory;
use Tobento\App\Boot;

interface ServiceInterface {}
class Service implements ServiceInterface {}

class ServiceBoot extends Boot
{
    public function boot()
    {
        $this->app->set(ServiceInterface::class, Service::class);
    }
}

$app = (new AppFactory())->createApp();

$app->boot(ServiceBoot::class);

var_dump($app->has(ServiceInterface::class));
// bool(false)

// Do the booting.
$app->booting();

var_dump($app->has(ServiceInterface::class));
// bool(true)

// Run the app
$app->run();

应用程序目录

您可以添加目录以供以后使用。

use Tobento\App\AppFactory;
use Tobento\Service\Dir\DirsInterface;

$app = (new AppFactory())->createApp();

$app->dirs()
    ->dir(dir: 'path/to/config', name: 'config', group: 'config')
    ->dir(dir: 'path/to/view', name: 'view');
    
var_dump($app->dir(name: 'view'));
// string(13) "path/to/view/"

var_dump($app->dirs() instanceof DirsInterface);
// bool(true)

查看Dir Service以了解更多关于目录的一般信息。

应用程序时钟

use Tobento\App\AppFactory;
use Psr\Clock\ClockInterface;

$app = (new AppFactory())->createApp();

// Get the app clock:
var_dump($app->clock() instanceof ClockInterface);
// bool(true)

// or:
var_dump($app->get(ClockInterface::class) instanceof ClockInterface);
// bool(true)

应用程序宏

use Tobento\App\AppFactory;

$app = (new AppFactory())->createApp();

$app->addMacro('lowercase', function(string $string): string {
    return strtolower($string);
});

var_dump($app->lowercase('Lorem'));
// string(5) "lorem"

查看Macro Service以了解更多关于宏的一般信息。

可用的启动

应用程序启动

应用程序启动执行以下操作

  • 启动配置启动函数启动
  • 如果存在,则加载应用程序配置文件
  • 根据应用程序配置设置应用程序环境
  • 为环境添加特定的配置目录
  • 根据应用程序配置设置时区
  • 启动应用程序配置中指定的启动
use Tobento\App\AppFactory;

$app = (new AppFactory())->createApp();

$app->boot(\Tobento\App\Boot\App::class);

$app->run();

配置启动

配置启动执行以下操作

  • 实现配置接口
  • 添加配置宏

查看配置服务以了解更多关于它的一般信息。

use Tobento\App\AppFactory;
use Tobento\Service\Config\ConfigInterface;

$app = (new AppFactory())->createApp();

$app->dirs()->dir(
    dir: 'path/to/config',
    name: 'config',
    group: 'config'
);
    
$app->boot(\Tobento\App\Boot\Config::class);

$app->booting();

// using interface
$value = $app->get(ConfigInterface::class)->get(
    key: 'app.key',
    default: 'default',
    locale: 'de'
);

// using macro:
$value = $app->config('app.key', 'default');

var_dump($value);
// string(7) "default"

$app->run();

函数启动

函数启动执行以下操作

  • 注册应用程序函数
  • 提供注册方法
  • 添加应用程序函数宏

查看辅助函数服务以了解更多关于它的一般信息。

use Tobento\App\AppFactory;
use Tobento\App\AppInterface;

use function Tobento\App\{app, directory, config};

$app = (new AppFactory())->createApp();
    
$app->boot(\Tobento\App\Boot\Functions::class);
$app->booting();

// App function:
var_dump(app() instanceof AppInterface);
// bool(true)

// Directory function:
$app->dirs()->dir('dir/to/foo', 'foo');

var_dump(directory('foo'));
// string(11) "dir/to/foo/"

// Config function:
$app->boot(\Tobento\App\Boot\Config::class);
$app->booting();

var_dump(config(key: 'foo', default: 'foo'));
// string(3) "foo"

// using functions macro:
// $app->functions(__DIR__.'/my-functions.php');

// using boot method:
// $app->get(\Tobento\App\Boot\Functions::class)->register(__DIR__.'/my-functions.php');

$app->run();

错误处理启动

错误处理启动执行以下操作

  • 实现错误处理
use Tobento\App\AppFactory;

$app = (new AppFactory())->createApp();

$app->boot(\Tobento\App\Boot\ErrorHandling::class);

$app->run();

日期启动

日期启动执行以下操作

  • 使用 app.timezone 和 app.locale 配置来配置 DateFormatter

查看 Dater 服务 以了解更多关于一般信息。

use Tobento\App\AppFactory;
use Tobento\Service\Dater\DateFormatter;

$app = (new AppFactory())->createApp();

$app->boot(\Tobento\App\Boot\Dater::class);

$app->booting();

$df = $app->get(DateFormatter::class);

var_dump($df->date('now'));
// string(25) "Freitag, 11. Februar 2022"

$app->run();

处理启动错误

你可能需要处理由启动导致的错误,以便继续运行应用程序

use Tobento\App\AppFactory;
use Tobento\App\Boot;
use Tobento\App\BootErrorHandlersInterface;
use Tobento\App\BootErrorHandlers;
use Tobento\Service\ErrorHandler\AutowiringThrowableHandlerFactory;

class CausesErrorBoot extends Boot
{
    public function boot(): void
    {
        echo $test();
    }
}

$app = (new AppFactory())->createApp();

$app->set(BootErrorHandlersInterface::class, function() use ($app) {

    $handlers = new BootErrorHandlers(
        new AutowiringThrowableHandlerFactory($app->container())
    );

    $handlers->add(function(Throwable $t): mixed {
        return null;
    });

    return $handlers;
});

$app->boot(\Tobento\App\Boot\ErrorHandling::class);

$app->boot(CausesErrorBoot::class);

$app->run();

查看 Throwable 处理器 以了解关于处理器的一般信息。

自定义

某些启动可能在它们的启动方法上实现接口,例如 app http 启动。有几种方法可以更改其实现。但我们需要记住,其他启动可能有 依赖启动 定义。

使用 app.on 方法

use Tobento\App\Boot;
use Tobento\App\Http\Boot\Http;
use Psr\Http\Message\ResponseFactoryInterface;

class CustomBoot extends Boot
{
    public function boot(): void
    {
        $this->app->on(
            ResponseFactoryInterface::class,
            \Laminas\Diactoros\ResponseFactory::class
        );
    }
}

$app = (new AppFactory())->createApp();

$app->boot(CustomBoot::class);

$app->run();

启动扩展

use Tobento\App\Boot;
use Tobento\App\Http\Boot\Http;
use Tobento\App\Migration\Boot\Migration;
use Psr\Http\Message\ResponseFactoryInterface;

class CustomHttpBoot extends Http
{
    /**
     * Boot application services.
     *
     * @param Migration $migration
     * @return void
     */
    public function boot(Migration $migration): void
    {
        parent::boot($migration);
        
        // set your custom implementations.
        $this->app->set(
            ResponseFactoryInterface::class,
            \Laminas\Diactoros\ResponseFactory::class
        );
    }
}

$app = (new AppFactory())->createApp();

$app->on(Http::class, CustomHttpBoot::class);

$app->run();

启动实现覆盖

use Tobento\App\Boot;
use Tobento\App\Http\Boot\Http;
use Psr\Http\Message\ResponseFactoryInterface;

class CustomBoot extends Boot
{
    public const BOOT = [
        Http::class,
    ];
    
    public function boot(Http $http): void
    {
        // set your custom implementations.
        $this->app->set(
            ResponseFactoryInterface::class,
            \Laminas\Diactoros\ResponseFactory::class
        );
    }
}

$app = (new AppFactory())->createApp();

$app->boot(CustomBoot::class);

$app->run();

致谢