baraja-core/service-method-invoker 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

baraja-core/service-method-invoker

Composer 安装命令:

composer require baraja-core/service-method-invoker

包简介

Invoke method by service, name and arguments.

README 文档

README

Integrity check

A robust PHP library for safely invoking methods on services with automatic parameter validation, type coercion, and entity hydration. Perfect for API endpoints, command handlers, and any scenario where you need to dynamically call methods with user-provided data.

🎯 Key Features

  • Safe method invocation with automatic parameter validation and type checking
  • Automatic type coercion for scalar types (bool, int, float, string, array)
  • Entity hydration - automatically converts array data to typed objects/DTOs
  • PHP 8.1+ enum support with case-insensitive matching
  • Nullable parameter handling with proper default value support
  • Tracy Debugger integration with custom BlueScreen panels for debugging
  • Circular reference detection in nested entity hydration
  • Custom entity repository support for resolving entities by ID
  • Detailed exception messages with context about the failing service and method

🏗️ Architecture

The package consists of several components working together to provide safe method invocation:

┌─────────────────────────────────────────────────────────────────┐
│                    ServiceMethodInvoker                         │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  invoke(service, method, params)                        │   │
│  │  getInvokeArgs(service, method, params)                 │   │
│  └─────────────────────────────────────────────────────────┘   │
│           │                    │                    │           │
│           ▼                    ▼                    ▼           │
│  ┌─────────────┐    ┌─────────────────┐    ┌──────────────┐    │
│  │Type Coercion│    │Entity Hydration │    │Enum Handling │    │
│  │ fixType()   │    │hydrateDataTo..()│    │processEnum..()│   │
│  └─────────────┘    └─────────────────┘    └──────────────┘    │
└─────────────────────────────────────────────────────────────────┘
         │                       │
         ▼                       ▼
┌─────────────────┐    ┌─────────────────────────┐
│     Helpers     │    │ ProjectEntityRepository │
│ - Type parsing  │    │ - Find entities by ID   │
│ - Annotations   │    │ (optional interface)    │
│ - Use statements│    └─────────────────────────┘
└─────────────────┘
         │
         ▼
┌─────────────────┐    ┌─────────────────────────┐
│   BlueScreen    │    │  RuntimeInvokeException │
│ Tracy panel     │    │  Contextual exceptions  │
└─────────────────┘    └─────────────────────────┘

🔧 Components

Component Description
ServiceMethodInvoker Main class responsible for invoking methods with validated and hydrated parameters
Service Interface for services that extends Stringable for user-friendly error messages
RuntimeInvokeException Exception class that carries service context, method name, and parameters for debugging
BlueScreen Tracy Debugger integration that renders detailed error panels with source code
Helpers Utility class for type resolution, annotation parsing, and use statement extraction
ProjectEntityRepository Interface for custom entity resolution by ID (e.g., Doctrine integration)

📦 Installation

It's best to use Composer for installation, and you can also find the package on Packagist and GitHub.

To install, simply use the command:

$ composer require baraja-core/service-method-invoker

You can use the package manually by creating an instance of the internal classes, or register a DIC extension to link the services directly to the Nette Framework.

Requirements: PHP 8.1 or higher

🚀 Basic Usage

Simple Method Invocation

Think of a simple service as an API endpoint with a public method for hydrating your data:

$invoker = new \Baraja\ServiceMethodInvoker;
$apiEndpoint = new \Baraja\MyApiEndpoint;

$data = $invoker->invoke($apiEndpoint, 'actionDetail', ['id' => 42]);

var_dump($data); // return "My id is: 42"

And your endpoint can be:

class MyApiEndpoint
{
    public function actionDetail(int $id): string
    {
        return 'My id is: ' . $id;
    }
}

Getting Invoke Arguments Without Execution

If you need to prepare the arguments without actually invoking the method:

$invoker = new \Baraja\ServiceMethodInvoker;
$args = $invoker->getInvokeArgs($service, 'methodName', $params);

// $args is now a validated and hydrated array ready for method invocation

🎭 Type Coercion

The invoker automatically handles type conversion based on method parameter types:

Scalar Types

class MyService
{
    public function process(
        int $count,      // "42" -> 42, "null" -> null (if nullable)
        float $price,    // "19.99" -> 19.99
        bool $active,    // "true", "1", "yes" -> true; others -> false
        string $name,    // kept as-is
        array $items,    // kept as-is
    ): void {
        // ...
    }
}

$invoker->invoke($service, 'process', [
    'count' => '42',
    'price' => '19.99',
    'active' => 'yes',
    'name' => 'Test',
    'items' => ['a', 'b'],
]);

Nullable Parameters

When a parameter is nullable and receives an empty or falsy value, it's converted to null:

public function find(?int $id): void
{
    // '' or '0' with nullable type -> null
    // '0' with non-nullable int -> 0
}

Boolean Conversion

The following string values are treated as true: "1", "true", "yes" (case-insensitive). All other values are converted to false.

📊 Entity Hydration

One of the most powerful features is automatic entity/DTO hydration from array data:

Simple Entity

class CreateUserRequest
{
    public function __construct(
        public string $email,
        public string $name,
        public ?int $age = null,
    ) {}
}

class UserController
{
    public function create(CreateUserRequest $request): User
    {
        // $request is automatically hydrated from the params array
        return new User($request->email, $request->name);
    }
}

$invoker->invoke($controller, 'create', [
    'email' => 'john@example.com',
    'name' => 'John Doe',
    'age' => 25,
]);

Nested Entities

The invoker supports nested entity hydration:

class Address
{
    public function __construct(
        public string $street,
        public string $city,
    ) {}
}

class Order
{
    public function __construct(
        public string $product,
        public Address $shippingAddress,
    ) {}
}

$invoker->invoke($service, 'createOrder', [
    'product' => 'Widget',
    'shippingAddress' => [
        'street' => '123 Main St',
        'city' => 'Prague',
    ],
]);

Property Hydration via Setters

If an entity has setter methods, they will be used for hydration:

class UserEntity
{
    private string $email;

    public function setEmail(string $email): void
    {
        $this->email = strtolower($email);
    }
}

Circular Reference Detection

The invoker detects and prevents circular references in entity hydration:

class NodeA
{
    public NodeB $child;
}

class NodeB
{
    public NodeA $parent; // This would cause a circular reference
}

// RuntimeInvokeException: Circular reference detected...

🔢 PHP 8.1+ Enum Support

The invoker fully supports PHP enums with case-insensitive matching:

enum Status: string
{
    case Active = 'active';
    case Inactive = 'inactive';
    case Pending = 'pending';
}

class OrderService
{
    public function updateStatus(int $orderId, Status $status): void
    {
        // ...
    }
}

// All of these work:
$invoker->invoke($service, 'updateStatus', ['orderId' => 1, 'status' => 'active']);
$invoker->invoke($service, 'updateStatus', ['orderId' => 1, 'status' => 'ACTIVE']);
$invoker->invoke($service, 'updateStatus', ['orderId' => 1, 'status' => 'Active']);

If an invalid enum value is provided, a helpful error message is shown:

Value "unknown" is not possible option of enum "Status". Did you mean "active", "inactive", "pending"?

🔍 Custom Entity Repository

For integrating with ORMs like Doctrine, implement the ProjectEntityRepository interface:

use Baraja\ServiceMethodInvoker\ProjectEntityRepository;

class DoctrineEntityRepository implements ProjectEntityRepository
{
    public function __construct(
        private EntityManagerInterface $em,
    ) {}

    public function find(string $className, int|string $id): ?object
    {
        return $this->em->find($className, $id);
    }
}

$invoker = new ServiceMethodInvoker(
    projectEntityRepository: new DoctrineEntityRepository($entityManager),
);

This allows automatic entity resolution from IDs:

class ArticleController
{
    public function show(Article $article): Response
    {
        // $article is automatically loaded from the database using the ID
    }
}

$invoker->invoke($controller, 'show', ['article' => 42]);
// Article with ID 42 is automatically loaded via the repository

📑 The Data Parameter

When dataMustBeArray is true, a parameter named data must be typed as array and will receive all input parameters:

class BatchProcessor
{
    public function process(array $data): void
    {
        // $data contains all the input parameters
    }
}

$invoker->invoke($processor, 'process', [
    'item1' => 'value1',
    'item2' => 'value2',
], dataMustBeArray: true);

// $data = ['item1' => 'value1', 'item2' => 'value2']

🐛 Tracy Debugger Integration

When Tracy Debugger is available, the package automatically registers a custom BlueScreen panel that provides:

  • Service class name and the exact method being called
  • Source code highlighting of the failing method
  • Input parameters table showing all passed values
  • Direct editor link to open the file at the exact line

This integration is automatic when Tracy is installed - no configuration needed.

⚠️ Exception Handling

The RuntimeInvokeException provides rich context for debugging:

try {
    $invoker->invoke($service, 'method', $params);
} catch (RuntimeInvokeException $e) {
    $e->getService();  // The service object that failed
    $e->getMethod();   // The method name that was being called
    $e->getParams();   // The parameters that were passed
    $e->getMessage();  // Detailed error message
}

Common Exceptions

Scenario Exception Type
Method doesn't exist InvalidArgumentException
Method is not callable InvalidArgumentException
Required parameter missing RuntimeInvokeException
Invalid enum value RuntimeInvokeException
Type incompatibility RuntimeInvokeException
Circular reference in entities RuntimeInvokeException
Entity class doesn't exist RuntimeInvokeException

🎨 Service Interface

Implement the Service interface on your services for better error messages:

use Baraja\Service;

class UserApiEndpoint implements Service
{
    public function __toString(): string
    {
        return 'User API Endpoint';
    }

    public function getUser(int $id): array
    {
        // ...
    }
}

// Error messages will now show "User API Endpoint" instead of the class name

📋 DateTime Handling

DateTimeInterface implementations are automatically instantiated:

class EventService
{
    public function schedule(
        string $name,
        \DateTimeImmutable $startDate,
    ): void {
        // $startDate is automatically created from the string value
    }
}

$invoker->invoke($service, 'schedule', [
    'name' => 'Conference',
    'startDate' => '2024-06-15 10:00:00',
]);

🔒 Default Values for Empty Inputs

When a non-nullable parameter receives an empty value, appropriate defaults are used:

Type Default Value
string "" (empty string)
int 0
float 0.0
bool false
array []

👤 Author

Jan Barasek - https://baraja.cz

📄 License

baraja-core/service-method-invoker is licensed under the MIT license. See the LICENSE file for more details.

baraja-core/service-method-invoker 适用场景与选型建议

baraja-core/service-method-invoker 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 230.83k 次下载、GitHub Stars 达 2, 最近一次更新时间为 2020 年 04 月 23 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 baraja-core/service-method-invoker 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 baraja-core/service-method-invoker 我们能提供哪些服务?
定制开发 / 二次开发

基于 baraja-core/service-method-invoker 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 230.83k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 2
  • 点击次数: 3
  • 依赖项目数: 4
  • 推荐数: 0

GitHub 信息

  • Stars: 2
  • Watchers: 1
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: Unknown
  • 更新时间: 2020-04-23