定制 milpa/live 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

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

milpa/live

Composer 安装命令:

composer require milpa/live

包简介

Render-target-agnostic live component primitives for the Milpa PHP framework: contracts, value objects, components, data sources, and the event-driven mount/handle/render lifecycle.

README 文档

README

Milpa

Milpa Live

Render-target-agnostic live components for the Milpa PHP framework — the same component definition renders to web AND terminal; state, data sources, and an event-driven interception seam, no HTML or ANSI in the component itself.

CI Packagist PHP License Docs

milpa/live is the render-target-agnostic core of Milpa's live component system: a component owns its contract (props/state schema, declared actions), its initial state (mount()), and how it reacts to client-originated actions (handle()) — but never how it turns into markup or terminal output. That's a ComponentRendererInterface's job, paired with the component at the call site. One component, any number of renderers.

Install

composer require milpa/live

Quick example

A minimal component plus two renderers — one for HTML, one for TUI — sharing the exact same mount()/handle() logic:

use Milpa\Live\Contracts\Component\ComponentDefinitionInterface;
use Milpa\Live\Contracts\Rendering\ComponentRendererInterface;
use Milpa\Live\ValueObjects\{
    ComponentContext, ComponentContract, InteractionRequest,
    InteractionResult, RenderRequest, RenderResult, RenderTarget, StateSnapshot,
};

final class CounterComponent implements ComponentDefinitionInterface
{
    public static function contract(): ComponentContract
    {
        return new ComponentContract(name: 'counter', contractVersion: '1.0.0', actions: ['increment' => []]);
    }

    public function mount(array $props, ComponentContext $context): StateSnapshot
    {
        return new StateSnapshot(
            componentId: $context->componentId,
            componentName: 'counter',
            version: '1.0.0',
            data: ['count' => (int) ($props['start'] ?? 0)],
        );
    }

    public function handle(InteractionRequest $request): InteractionResult
    {
        return new InteractionResult(state: new StateSnapshot(
            componentId: $request->state->componentId,
            componentName: $request->state->componentName,
            version: $request->state->version,
            data: ['count' => $request->state->data['count'] + 1],
        ));
    }
}

final class HtmlCounterRenderer implements ComponentRendererInterface
{
    public function supportsTarget(RenderTarget $target): bool
    {
        return $target === RenderTarget::HTML;
    }

    public function render(ComponentDefinitionInterface $component, RenderRequest $request): RenderResult
    {
        $state = $request->state ?? $component->mount($request->props, $request->context);

        return new RenderResult(
            output: sprintf('<button data-count="%d">Count: %d</button>', $state->data['count'], $state->data['count']),
            state: $state,
            format: RenderTarget::HTML,
        );
    }
}

final class TuiCounterRenderer implements ComponentRendererInterface
{
    public function supportsTarget(RenderTarget $target): bool
    {
        return $target === RenderTarget::TUI;
    }

    public function render(ComponentDefinitionInterface $component, RenderRequest $request): RenderResult
    {
        $state = $request->state ?? $component->mount($request->props, $request->context);

        return new RenderResult(output: "[ Count: {$state->data['count']} ]", state: $state, format: RenderTarget::TUI);
    }
}

$component = new CounterComponent();
$context = new ComponentContext('demo-1');

$html = (new HtmlCounterRenderer())->render($component, new RenderRequest(context: $context, target: RenderTarget::HTML));
echo $html->output; // <button data-count="0">Count: 0</button>

$tui = (new TuiCounterRenderer())->render($component, new RenderRequest(context: $context, target: RenderTarget::TUI));
echo $tui->output; // [ Count: 0 ]

CounterComponent never printed a single tag or escape code — both renderers turned the exact same StateSnapshot into their own output, independently.

Web + TUI from one component

That's the thesis this package is built around: a component definition is a pure description of state and behavior; rendering is a separate, swappable concern. A ComponentRendererInterface declares which RenderTarget(s) it supports (HTML, TUI, or the forward-looking ANSI) and turns a mounted StateSnapshot into output for that target — nothing in ComponentDefinitionInterface ever needs to know which renderer, or how many, will consume it.

milpa/live ships the component contracts, the mount/handle lifecycle, data sources, and the event-driven interception seam (component.mounting/mounted, component.handling/handled, component.rendering/rendered — see LiveEventEmitter) — but no HTML and no ANSI renderer. The web surface (AutocompleteHtmlRenderer and friends) lives in milpa/live-web; a TUI renderer is a live candidate in the Milpa lab. This package is the seam both build on, not either surface itself.

Requirements

  • PHP ≥ 8.3
  • milpa/core ^0.5
  • psr/log ^3

Documentation

Full API reference: getmilpa.github.io/live — generated straight from the source DocBlocks and dressed with the Milpa design system.

Contributing

Contributions are welcome — see CONTRIBUTING.md. Please report security issues via SECURITY.md, and note that this project follows a Code of Conduct.

License

Apache-2.0 © TeamX Agency.

Milpa is designed, built, and maintained by TeamX Agency.

统计信息

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

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: Apache-2.0
  • 更新时间: 2026-07-08

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固