PHP code example of kode / facade

1. Go to this page and download the library: Download kode/facade library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

kode / facade example snippets


namespace Kode\Facade;

use Psr\Container\ContainerInterface;

abstract class Facade
{
    /**
     * 获取当前门面对应的服务名(在容器中的 key)
     */
    abstract protected static function id(): string;

    /**
     * 设置服务容器
     */
    public static function setContainer(ContainerInterface $container): void;

    /**
     * 清除当前门面的代理实例(用于测试或重置)
     */
    public static function clear(): void;

    /**
     * 清除所有门面的缓存实例
     */
    public static function clearAll(): void;

    /**
     * 检查门面是否已解析
     */
    public static function isResolved(): bool;

    /**
     * 获取此门面的服务ID
     */
    public static function getServiceId(): string;

    /**
     * 使用参数数组调用门面实例上的方法
     */
    public static function call(string $method, array $args = []): mixed;

    /**
     * 检查门面实例上是否存在指定方法
     */
    public static function hasMethod(string $method): bool;

    /**
     * 启用上下文安全模式
     */
    public static function enableContextSafeMode(): void;

    /**
     * 禁用上下文安全模式
     */
    public static function disableContextSafeMode(): void;

    /**
     * 检查是否启用了上下文安全模式
     */
    public static function isContextSafeMode(): bool;

    /**
     * 动态静态调用转发
     */
    public static function __callStatic(string $method, array $args): mixed;
}

namespace Kode\Facade;

final class FacadeProxy
{
    /**
     * 绑定门面到服务ID
     */
    public static function bind(string $facade, string $serviceId): void;

    /**
     * 批量绑定门面
     */
    public static function bindMany(array $bindings): void;

    /**
     * 解除门面绑定
     */
    public static function unbind(string $facade): void;

    /**
     * 检查门面是否已绑定
     */
    public static function isBound(string $facade): bool;

    /**
     * 获取门面对应的服务ID
     */
    public static function getServiceId(string $facade): ?string;

    /**
     * 获取所有门面绑定
     */
    public static function getBindings(): array;

    /**
     * 模拟门面实例(用于测试)
     */
    public static function mock(string $facade, object|Closure $mock): void;

    /**
     * 检查门面是否被模拟
     */
    public static function isMocked(string $facade): bool;

    /**
     * 获取门面实例
     */
    public static function getInstance(string $facade): object;

    /**
     * 清除所有数据
     */
    public static function clearAll(): void;
}

namespace Kode\Facade;

final class ContextualFacadeManager
{
    /**
     * 设置服务容器
     */
    public static function setContainer(ContainerInterface $container): void;

    /**
     * 获取门面实例
     */
    public static function getInstance(string $facadeClass): object;

    /**
     * 检查门面实例是否存在于当前上下文
     */
    public static function hasInstance(string $facadeClass): bool;

    /**
     * 清除当前上下文的所有门面实例
     */
    public static function clearInstances(): void;
}

namespace App\Service;

interface MailerInterface
{
    public function send(string $to, string $subject, string $body): bool;
    public function getDriver(): string;
}

namespace App\Service;

class SmtpMailer implements MailerInterface
{
    public function send(string $to, string $subject, string $body): bool
    {
        // 发送逻辑...
        return true;
    }

    public function getDriver(): string
    {
        return 'smtp';
    }
}

namespace App\Facade;

use Kode\Facade\Facade;

/**
 * 邮件门面
 *
 * @method static bool send(string $to, string $subject, string $body)
 * @method static string getDriver()
 *
 * @see \App\Service\MailerInterface
 */
class Mail extends Facade
{
    protected static function id(): string
    {
        return 'mailer'; // 对应容器中的服务 key
    }
}

use App\Facade\Mail;
use Kode\Facade\FacadeProxy;

// 绑定门面到服务ID
FacadeProxy::bind(\App\Facade\Mail::class, 'mailer');

// 设置容器
Mail::setContainer($container);

// 使用静态调用
Mail::send('[email protected]', 'Hello', 'Welcome!');
echo Mail::getDriver(); // 输出: smtp

// 检查门面是否已解析
if (Mail::isResolved()) {
    // 门面已解析
}

// 检查门面是否绑定到服务ID
if (FacadeProxy::isBound(\App\Facade\Mail::class)) {
    // 门面已绑定
}

// 获取门面的服务ID
$serviceId = Mail::getServiceId();

// 获取门面的服务ID(通过代理)
$serviceId = FacadeProxy::getServiceId(\App\Facade\Mail::class);

// 获取所有绑定的门面
$bindings = FacadeProxy::getBindings();

// 使用 call 方法调用,参数以数组形式传递
$result = Mail::call('send', ['[email protected]', 'Subject', 'Body']);

// 检查门面实例上是否存在指定方法
if (Mail::hasMethod('send')) {
    // 方法存在
}

// 启用上下文安全模式
Mail::enableContextSafeMode();

// 现在每个协程将拥有独立的门面实例缓存
// 避免不同协程间的实例污染问题

// 检查是否启用了上下文安全模式
if (Mail::isContextSafeMode()) {
    // 上下文安全模式已启用
}

// 禁用上下文安全模式
Mail::disableContextSafeMode();

// 模拟门面实例
$mockMailer = new class implements \App\Service\MailerInterface {
    public function send(string $to, string $subject, string $body): bool {
        echo "[MOCK] Sending email to {$to}";
        return true;
    }

    public function getDriver(): string {
        return 'mock-driver';
    }
};

Mail::mock($mockMailer);

// 现在调用将使用模拟实例
Mail::send('[email protected]', 'Test', 'Body'); // 输出: [MOCK] Sending email to [email protected]

interface ResponseFactory
{
    public function make(): Response; // 返回基类
}

interface JsonResponseFactory extends ResponseFactory
{
    public function make(): JsonResponse; // 子类返回更具体的类型(协变)
}

interface EventDispatcher
{
    public function dispatch(object $event): void;
}

interface SpecificEventDispatcher extends EventDispatcher
{
    public function dispatch(SpecificEvent $event): void; // 参数更具体(逆变)
}

$reflector = new ReflectionMethod($instance, $method);
$reflector->invokeArgs($instance, $args);

vendor/kode/facade/
├── src/
│   ├── Facade.php                 # 门面抽象基类
│   ├── FacadeProxy.php            # 门面代理管理器
│   ├── ContextualFacadeManager.php # 上下文安全门面管理器
│   └── Exception/
│       └── FacadeException.php    # 门面异常类
├── tests/
│   └── Unit/
│       ├── FacadeTest.php         # 门面测试
│       └── ContextualFacadeTest.php # 上下文门面测试
├── composer.json
├── LICENSE
└── README.md