Core

Component Service Provider

Reusable UI component registry for breadcrumbs, pagination and metadata.

Responsibility

Registers component-level services for reusable UI data and rendering: ComponentRegistry, breadcrumb services, pagination services and meta services. The provider also reads custom component class mappings from ComponentConfig.

Registry

ComponentRegistry maps component names to classes and resolves them through the container. Built-in names are breadcrumb, pagination and meta; convenience methods breadcrumb(), pagination() and meta() return typed framework components.

example.php
use Lemonade\Framework\Component\ComponentRegistry;
use Lemonade\Framework\Component\Breadcrumb\BreadcrumbComponent;

$registry = $container->get(ComponentRegistry::class);

if ($registry->has('breadcrumb')) {
    $breadcrumb = $registry->get('breadcrumb', BreadcrumbComponent::class);
}

$all = $registry->all();

Custom components

Applications can add reusable component services through app/Config/Components.yaml. Keys are component names and values are non-empty class strings. The loader validates the YAML and converts it into typed ComponentConfigDefinition; the component class must exist and is resolved through the container when requested from the registry.

example.php
module: components
config:
  example: App\Component\ExampleComponent

Breadcrumbs

BreadcrumbComponent creates BreadcrumbTrail instances and renders them through BreadcrumbRenderer. A trail supports add(), prepend(), clear(), count() and items(). frontend() and admin() use configurable root labels/URLs; empty() starts without a root item.

example.php
$trail = $components
    ->breadcrumb()
    ->empty()
    ->add('Home', '/')
    ->add('Articles', '/articles')
    ->add('Article detail', null, active: true);

$html = $components->breadcrumb()->render($trail);

Breadcrumb config

Breadcrumb defaults come from BreadcrumbsConfig, specifically frontend/admin root settings and the renderer class map. Class config is normalized before being passed to BreadcrumbRenderer.

Pagination

PaginationComponent can paginate an array through fromArray() or a database QueryBuilder through fromQueryBuilder(). It returns PaginationResult, which exposes paginated items() and state(). render() accepts PaginationResult, PaginationState or null.

example.php
$pagination = $components->pagination()->fromArray(
    items: $rows,
    page: 1,
    perPage: 20,
    pageName: 'page',
    basePath: '/articles',
);

$items = $pagination->items();
$html = $components->pagination()->render($pagination);

Pagination config

Pagination services use the current ServerRequestInterface to resolve the current page and query parameters when not supplied explicitly. Runtime behavior comes from PaginationConfig, including default/max per-page limits, visible page count, first/last buttons and renderer classes. PaginationRenderer uses TranslatorInterface for pagination.first, pagination.prev, pagination.next and pagination.last labels when translations exist.

Metadata

MetaComponent builds and renders page metadata from MetaData. Defaults come from config and rendered entities include standard meta tags, Dublin Core tags, Open Graph/Facebook tags and Twitter tags through MetaFactory.

example.php
use Lemonade\Framework\Component\Meta\MetaData;

$meta = new MetaData(
    title: 'Article detail',
    description: 'Short page description.',
    canonical: 'https://example.test/articles/example',
);

$html = $components->meta()->render($meta);

Meta config

MetaComponent applies defaults from MetaConfig, including website name, charset, viewport, rating and title separator. MetaData can also carry custom meta values, extra canonical query params and alternate links.

Controller usage

Controllers can inject ComponentRegistry or use the framework controller helper for components. Build component data in the controller and pass the resulting DTO/state objects or rendered HTML to a view according to the application template style.

example.php
use Lemonade\Framework\Component\ComponentRegistry;

final class ArticleController
{
    public function __construct(
        private readonly ComponentRegistry $components,
    ) {}

    public function detail(): ResponseInterface
    {
        $breadcrumbs = $this->components
            ->breadcrumb()
            ->empty()
            ->add('Home', '/')
            ->add('Article detail', null, active: true);

        // Pass $breadcrumbs to a template or render it before returning a response.
    }
}

View usage

Components can return data objects for templates or render small HTML fragments directly. The concrete page layout, CSS classes and final markup structure remain application/template responsibility.

example.php
<?= $components->breadcrumb()->render($breadcrumbs) ?>
<?= $components->pagination()->render($pagination) ?>
<?= $components->meta()->render($meta) ?>

Provider relations

ComponentServiceProvider supplies reusable component services. ViewServiceProvider renders templates and shares helpers; RoutingServiceProvider and localization can provide URLs/translations used around components; DatabaseServiceProvider is only involved when pagination uses QueryBuilder.

Provider boundary

Components are reusable UI/runtime helpers, not domain services. They should help controllers and views prepare breadcrumbs, pagination state or metadata, while business decisions and page-specific layout remain in application code.