jeremeamia/xstatic

此包已被 废弃 并不再维护。作者建议使用 lhsazevedo/restatic 包。

无静态陷阱的静态接口

1.0.1 2014-04-19 04:15 UTC

This package is auto-updated.

Last update: 2020-07-06 18:27:49 UTC


README

请考虑使用 ReStatic

XStatic

No Maintenance Intended

XStatic 是一个 PHP 库,用于启用 静态代理接口——类似于 Laravel 4+ 的 "Facades",但适用于任何 PHP 项目。XStatic 由 Jeremy Lindblom 创建。

注意:请考虑使用 ReStatic,这是该库的维护分支。XStatic 已不再积极支持。

介绍(问答)

Facades?静态代理?使用静态方法不是一种坏习惯吗?

使用静态方法和类使您的代码更难测试。这是因为您的代码变得与静态引用的类紧密耦合,并且对单元测试中的静态方法进行模拟是困难的。出于这个和其他原因,面向对象编程(OOP)专家通常不鼓励使用静态方法。通常,涉及如 服务定位器依赖注入(DI)的设计模式的技巧被首选用于管理对象依赖和组合。

但是...使用静态方法真的很简单。

是的,喜欢使用 CodeIgniter、Laravel、Kohana 和 FuelPHP 等框架的 PHP 开发者非常习惯在应用程序开发中使用静态方法。在这些社区中,这是一种鼓励的做法,他们认为这使代码更易于阅读,并有助于 快速应用开发(RAD)。

那么,有什么妥协的方法吗?

是的!Laravel 4 有一个名为 "facades" 的概念(注意:这不同于 外观设计模式)。这些充当存储在服务容器中的实际对象实例的静态接口或代理。静态代理通过一些技巧与容器链接,包括通过 PHP 的 class_alias() 函数定义类别名,以及使用魔法 __callStatic() 方法。我们应该感谢 Taylor Otwell 开发这项技术。

那么 XStatic 的目的是什么?

XStatic 使用与 Laravel 的 "facades" 系统相同的技巧,但提供了两个额外的、但重要的特性

  1. 它与任何框架的服务容器兼容 - XStatic 依赖于 container-interop 项目的 ContainerInterface。您可以使用 Acclimate 库将任何第三方容器适配到 XStatic 所依赖的标准化容器接口。
  2. 它在任何命名空间中工作 - XStatic 在堆栈中注入了一个自动加载器,因此无论您尝试从什么命名空间或作用域引用您别名的静态代理,它都会通过 XStatic 自动加载器。您可以配置 XStatic 以在全局命名空间、当前命名空间或特定命名空间中创建别名。

那么,为什么叫 XStatic 呢?

有两个原因

  1. 它消除了静态方法调用的静态性,因为方法调用被代理到实际对象实例。潜在的标语:"没有静态陷阱的静态接口"
  2. 它的发音像单词"ecstatic",因为它的目的是给开发者(至少是其中一些人)带来快乐。

使用方法

为了向您展示如何使用XStatic,我将向您展示一个简单的Silex应用程序。

您的应用程序引导程序

<?php

// Include the Composer autoloader, of course
require 'vendor/autoload.php';

use Acclimate\Container\ContainerAcclimator;
use XStatic\ProxyManager;
use Silex\Application;
use Silex\Provider\TwigServiceProvider;

// Setup your Silex app/container
$app = new Application;
$app->register(new TwigServiceProvider, array(
    'twig.path' => __DIR__ . '/templates',
));
$app['db'] = function () {
    return new PDO('mysql:dbname=testdb;host=127.0.0.1', 'dbuser', 'dbpass');
};
$app->get('/', 'MyApp\Controller\Home::index'); // Routes "/" to a controller object

// Setup and enable XStatic
$acclimator = new ContainerAcclimator();
$proxyManager = new ProxyManager($acclimator->acclimate($app));
$proxyManager->addProxy('View', 'MyApp\Proxy\Twig');
$proxyManager->addProxy('DB', 'MyApp\Proxy\Pdo');
$proxyManager->enable(ProxyManager::ROOT_NAMESPACE_ANY);

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

您的静态代理类

namespace MyApp\Proxy
{
    use XStatic\StaticProxy;

    class Pdo extends StaticProxy
    {
        public static function getInstanceIdentifier()
        {
            return 'db';
        }
    }

    class Twig extends StaticProxy
    {
        public static function getInstanceIdentifier()
        {
            return 'twig';
        }
    }
}

您的控制器类

namespace MyApp\Controller;

class Home
{
    public function index()
    {
        // It just works!
        View::render('home.index', array(
            'articles' => DB::query('SELECT * FROM articles')
        );
    }
}

非常酷,对吧?关于这个例子的一些有趣的事情是,我们实际上隐藏了我们在控制器中使用PDO和Twig的事实。我们可以轻松地替换使用相同接口的其他东西,而控制器代码则不需要更改。我们唯一需要做的是将不同的对象放入应用程序容器中。实际上,测试控制器就是这样工作的。测试可以使用放入容器的模拟或存根对象进行引导。

没有静态陷阱的静态接口。

XStatic 概念

  • 静态代理 – 将静态方法调用代理到其 代理主题 实例方法上的静态类。
  • 代理主题(实例) – 存储在 容器 中并与 静态代理 链接的对象实例。
  • 代理管理器 – 用于将 静态代理别名加载器容器 关联的中介对象。
  • 别名 – 用作 静态代理 类完全限定类名的别名的可记忆的类名。
  • 别名加载器 – 维护 别名静态代理 之间的关联。它被注入到自动加载堆栈中,以处理引用时出现的别名。
  • 容器 – 提供 代理主题 实例的 IoC 容器(例如,服务定位器或 DIC)。它必须实现 container-interop 项目中的 ContainerInterface
  • 实例标识符 – 用于从 容器 中获取 代理主题 的标识符。每个 静态代理 必须指定获取其代理主题所需的实例标识符。
  • 根命名空间 – 可以引用 别名 的命名空间。这可以配置为全局命名空间(默认)、特定命名空间或 任何 命名空间(即,别名可以在任何命名空间中工作)。

工作原理

以下图表显示了当引用静态代理时会发生什么,假设它之前已添加到代理管理器中。

XStatic Diagram

灵感

这个库深受 Facades 系统的启发,该系统在 Laravel 4 框架 中。

免责声明

我不会把自己定位为支持或反对使用静态代理接口(或Laravel的“门面”),但我确实认为这是一个有趣且独特的想法,而且非常酷的是,你可以这样编写代码,同时它仍然能够正常工作并且可测试。我很想看看开发者,尤其是库和框架的开发者,是否能够找到方法来使用,但不强制要求,这些静态代理接口,以便让他们的项目吸引更广泛的PHP开发者。