mattferris/application

一个 PHP 应用程序加载器

1.0 2020-02-03 06:25 UTC

This package is auto-updated.

Last update: 2024-09-18 15:51:33 UTC


README

Build Status

一个 PHP 应用程序引导框架。

框架基于组件的概念构建。每个组件负责配置自身、注册服务、订阅事件等。这意味着您只需将所需的组件添加到应用程序中并运行它!配置应用程序所需的所有内容只是一个实现了 MattFerris\Di\ContainerInterface 的依赖注入容器(它反过来扩展了 Interop\Container\ContainerInterface)。

一个简单的 HTTP 应用程序可能看起来像这样

use MattFerris\Application\Application;
use MattFerris\Di\Di;

// setup your application by adding components to it
$app = new Application(new Di(), [
    '\MattFerris\Events\EventsComponent', // event handling
    '\MattFerris\Http\Routing\HttpRoutingComponent' // HTTP request handling
]);

// then run it by passing a startup callable to run()
$app->run(['\MattFerris\Http\Routing\HttpRoutingComponent', 'run']);

HttpRoutingComponent 有一个名为 run() 的静态方法,它提供了额外的引导以启动请求处理过程。如果您想的话,也可以向 $app->run() 提供自己的 callable

组件

组件可能从单个函数到整个库。在应用程序的术语中,一个项目(即代码)只有在项目的配置和初始化被封装成一个整洁的包,并作为实现了 MattFerris\Component\ComponentInterface 的类表示时,才成为组件。通常,这个组件类会位于您项目的顶级命名空间中。

为了简化,您的组件类可以直接扩展 MattFerris\Application\Component

namespace My\Project;

use MattFerris\Application\Component;

class MyProjectComponent extends Component
{
}

当扩展 MattFerris\Application\Component 时,您将获得一个组件,它将自动加载同一命名空间内的提供者。所以给定的组件,您可以在 My\Project 命名空间内创建提供者。

namespace My\Project;

use MattFerris\Provider\ProviderInterface;

class EventsProvider implements ProviderInterface
{
    public function provides($consumer)
    {
        // register events, etc...
    }
}

EventsProvider 现在将在应用程序引导时自动加载。

提供者

组件的唯一真实工作是将在框架中插入提供者。提供者是重载发生的地方,负责将服务注册到服务容器中,将事件监听器注册到事件调度器中,向 HTTP 请求调度器提供路由信息等。提供者必须实现 MattFerris\Provider\ProviderInterface,该接口要求存在一个名为 provides() 的方法。

默认情况下,没有提供者类型。组件必须在初始化期间注册提供者类型。

// provided by mattferris/bridge-components
use MattFerris\Bridge\Components\Di\DiComponent;
use MattFerris\Di\Di;
use MattFerris\Application\Application;
use My\Project\MyProjectComponent;

$app = new Application(new Di(), [
    DiComponent::class,
    MyProjectComponent::class
]);

DiComponent 注册一个 Services 提供者类型。您现在可以定义一个 ServicesProvider 来注册服务。

namespace My\Project;

use MattFerris\Provider\ProviderInterface;

class ServicesProvider implements ProviderInterface
{
    public function provides($consumer)
    {
        // $consumer will contain an instance of the service container
        $container = $consumer;

        // register a service
        $container->set('MyProjectService', new MyProjectService());
    }
}

ServicesProvider::provides() 总是传递配置的服务容器的实例。同样,EventsProvider 将传递事件调度器的实例,依此类推。

提供者类型

到目前为止,我们讨论了 全局 提供者类型。可以通过两种方式在组件中注册 全局 提供者类型。对于扩展 MattFerris\Application\Components 的组件,这就像在组件的类定义中定义 $provides 属性一样简单。

namespace My\Project;

use MattFerris\Application\Component;

class MyProjectComponent extends Component
{
    protected $providers = [
        [
            'MyProjectType' => [
                'consumer' => MyProjectConsumer::class,
                'scope' => 'global'
            ]
        ]
    ];

    // ...
}

消费者 是传递到提供者 provides() 方法的实例类型。在这种情况下,它将是 My\Project\MyProjectConsumer 的实例。因为作用域设置为 global,组件将自动注册提供者。

对于独立组件(那些不扩展 MattFerris\Application\Component 的组件),提供者类型的注册是通过让组件类实现 MattFerris\Provider\ProviderInterface 并使用 provides() 手动注册类型来完成的。

namespace My\Project;

use MattFerris\Component\ComponentInterface;
use MattFerris\Provider\ProviderInterface;

class MyProjectComponent implements ComponentInterface, ProviderInterface
{
    public function provides($consumer)
    {
        // $consumer will contain an instance of MattFerris\Application\Application
        $consumer->addProvider('MyProjectType', MyProjectConsumer::class);
    }

    // ...
}

对于扩展 MattFerris\Application\Component 的组件,您还可以为组件的作用域内定义 局部 提供者。这为您提供了隔离组件初始化的灵活性,如所需。

namespace My\Project;

use MattFerris\Application\Component;

class MyProjectComponent extends Component
{
    protected $providers = [
        [
            'MyLocalType' => [
                'consumer' => MyLocalProjectConsumer::class,
                'scope' => 'local'
            ]
        ]
    ];

    // ...
}

高级组件初始化

在某些情况下,组件之间可能存在相互依赖。可以通过定义不同的初始化步骤,使组件能够以这种方式初始化,从而满足这些依赖关系。

use MattFerris\Application\Application;

$app = new Application($di, [
    [ 'Component\Satisfying\DependenciesComponent' ], // pass 1
    [ 'Another\Component\DependingOnFirstComponent' ] // pass 2
]);

通过简单地传递一个数组数组,可以将组件初始化分解为所需步骤,以成功引导您的应用程序。