mpoiriert/nucleus

dev-master 2014-12-02 15:18 UTC

This package is auto-updated.

Last update: 2024-09-09 13:38:00 UTC


README

小学习曲线PHP框架,适用于专业应用程序开发。

Build Status

Nucleus希望建立一个独立自足的框架,同时,借助适配器,也可以在任何其他PHP框架中使用。使用依赖注入,它主要使用JSON配置文件进行初始化(默认为nucleus.json)。因此,任何基于nucleus的项目都应该在其根目录中有一个nucleus.json文件。

nucleus.json

在文件中,你可以找到任何服务的配置,以及如果需要导入其他文件,还可以找到导入部分。这个概念基于Symfony项目的配置系统。主要区别在于,系统只支持JSON文件,并主要依赖于注释来实现所有其他“配置”。

以下是一个配置文件的示例

{
    "imports": [
        "/src/Nucleus/Framework/nucleus.json",
        "/src/Nucleus/Dashboard/nucleus.json"
    ],
     "services": {
        "customService": {
            "class": "My\\Namespace\\CustomService"
        },
        "assetManager": {
            "configuration": {
                "rootDirectory": "<?php echo str_replace('\\','/',__DIR__) . '/web' ?>"
            }
        }
     }
}

如你所见,文件中有一个PHP标签(),因此在解析JSON文件时,PHP将被解释。

从文件中可以看出,它需要2个其他文件才能工作

  • /src/Nucleus/Framework/nucleus.json
  • /src/Nucleus/Dashboard/nucleus.json

在Framework/nucleus.json中,你可以找到框架运行所需的所有服务的配置。所有服务都有自己的配置文件,因此你可以构建自己的自定义配置文件,而不必加载所有内容。我稍后会详细介绍这一点。你也可以看到Dashboard/nucleus.json文件,这个文件更多是这个应用程序的定制服务,就像第三方所做的那样。注意,导入中指定的文件路径可以是相对于该文件的相对路径

在文件中,你可以看到一个名为“customService”的服务的定义,以及它将用于实例化该服务的类。

此外,在它下面,你还有“assetManager”,但没有指定“class”属性。在特定情况下,如果你加载其他导入的文件,你将在某个地方找到这个服务的“class”属性。我们在特定文件中覆盖了“configuration” -> “rootDirectory”的asset manager值,而不是使用默认值。

加载配置

要加载配置,你必须使用Nucleus\Framework\Nucleus类中的静态方法。

$nucleus = \Nucleus\Framework\Nucleus::factory('/path/to/your/config/file/nucleus.json')

这将返回一个完整的Nucleus\Framework\Nucleus对象,但从那里,唯一可用的方法是"getServiceContainer"。你还有

// ... //
$service = \Nucleus\Framework\Nucleus::serviceFactory('/path/to/your/config/file/nucleus.json',$serviceName):
// ... //

这将只返回指定的服务。你将失去对服务容器的直接引用以及可能已初始化的其他服务(除非你请求的服务本身需要服务容器并且有方法来访问它)。这个示例是初始化你想要在另一个项目中作为独立对象使用的服务的正确方法,而不需要知道如何实例化它。

此外,作为一个快捷方式,如果你不需要覆盖任何默认值,Nucleus中实现的一些服务有“工厂”方法。以IEventDispatcher实现为例

$eventDispatcher = \Nucleus\EventDispatcher\EventDipatcher::factory();

这将实例化一个Nucleus\EventDispatcher\EventDispatcher,其默认配置在Nucleus\EventDispatcher命名空间文件夹中的nucleus.json文件中指定。

Nucleus\IService命名空间

存在一个通用的命名空间,用于定义服务接口。你应该始终在服务内部引用这些接口,而不是特定的类。这将允许你使用第三方服务的实现,并根据自己的需求构建自己的实现,同时与其他库兼容。除了服务接口外,你还可能找到异常类,因此你的实现抛出的异常将遵循定义的约定。

为了帮助您构建自己的服务实现,可以在特定服务文件夹中找到单元测试(基于PHPUnit)。"PHPUnit_Framework_TestCase" 是抽象的,通常需要您实现一个针对要测试的服务的特定 getter 方法。这样,如果您想自己实现一个服务,就不需要编写完整的单元测试。您可能需要测试自己的自定义方法,但通用服务接口将由抽象测试完全测试。即使我们将其称为单元测试,也应该将其视为集成测试,因为我们试图尽可能少地使用模拟对象

您应该了解的服务

显然,我建议您检查所有可用的服务和它们自己的文档,但我特别推荐的是

  • DependencyInjection
  • EventDispatcher
  • Routing
  • FrontController
  • View

创建自己的小型REST应用

现在您已经对概念有了基本了解(或者没有,但需要例子来理解)。假设您想创建一个小型的web服务API,您需要一个 nucleus.json 文件,它看起来像这样

{
  "imports": [
    "vendor/mpoiriert/nucleus/src/Nucleus/DependencyInjection/nucleus.json",
    "vendor/mpoiriert/nucleus/src/Nucleus/Routing/nucleus.json",
    "vendor/mpoiriert/nucleus/src/Nucleus/FrontController/nucleus.json"
  ],
  "services": {
    "myApi": {
      "class": "My\\Api"
    }
  }
}

类 My\Api 将看起来像这样(显然您会在API中添加更多有用的方法)

namespace My;

class Api 
{
  /**
   * @Route(name="getTime", path="/myApi/time")
   */
  public function getTime()
  {
    return time();
  }
}

如果您使用的是具有 accept application/json 头的应用或浏览器,它将相应地渲染。 我使用带有JsonView插件的firefox,并通过firefox的about:config地址编辑accept头以将application/json添加到列表中

在您应用程序的根目录中(您可能希望使用modrewrite来完成此操作),您必须放置

<?php

require_once(__DIR__ . '/../vendor/autoload.php');

$request = Symfony\Component\HttpFoundation\Request::createFromGlobals();

\Nucleus\Framework\Nucleus::serviceFactory(
  __DIR__ . '/../nucleus.json',              //The path to you json file
  "frontController"
)->handleRequest($request);

如您所见,系统基于composer,并且还使用symfony/httpfoundation组件来处理请求。

您应该获得如下所示的响应(result是默认根属性)

//url   http://domain.com/myApi/time
{"result":1369244261}

如果您的API需要其他服务(比如说,您有一个时钟服务),您可以在配置文件中添加该服务并将其注入到API中

// nucleus.json
{
  /* ... */
  "services": {
    /* ... */
    "myClock": {
      "class": "My\\Clock"
    }
  }
}

// My\Clock class

namespace My;

class Clock 
{
  public function getTime()
  {
    return time();
  }
}

// My\Api class with the clock injection

namespace My;

class Api 
{
  private $clock;
  /**
   * @Inject
   */
  public function initiliaze(Clock $myClock)
  {
    $this->clock = $myClock;
  }

  /**
   * @Route(name="getTime", path="/myApi/time")
   */
  public function getTime()
  {
    return $this->clock->getTime();
  }
}

如果您还没有阅读“您应该了解的服务”部分中的文档,可能无法理解所有内容,这是一个很好的时间去看看。