| Home | Getting Started | Core Concepts | Helpers | Extensions | Repo |
The Component extension provides reusable view fragments. The pattern is simple: each component file registers a PHP callable under a name, and any view can render it.
The framework exposes Component as a global constant pointing to a TinyComponent instance, initialised with the path app/views/components/.
Component::register(string $name, callable $func): void
Component::render(string $name, ...$props): void // echoes
Component::return(string $name, ...$props): mixed // returns
Component::__call(string $name, array $args): void // magic-method render: Component::myComp($x)
Component::require(string|array $files): void // loads component file(s) without rendering
Each component lives in its own file under app/views/components/. The file registers the callable; it does not render anything by itself.
<!-- app/views/components/user-card.php -->
<?php
Component::register('userCard', function (array $user): void { ?>
<article class="user-card">
<img src="<?= htmlspecialchars($user['avatar']) ?>" alt="">
<h3><?= htmlspecialchars($user['name']) ?></h3>
<p><?= htmlspecialchars($user['bio'] ?? '') ?></p>
</article>
<?php });
From any view (or layout):
<?php foreach (tiny::get('users') as $user): ?>
<?php Component::render('userCard', $user); ?>
<?php endforeach; ?>
Three equivalent forms:
Component::render('userCard', $user); // echoes
echo Component::return('userCard', $user); // returns the string
Component::userCard($user); // magic-method shortcut for render()
Note: components are registered on first include. The framework auto-includes every PHP file in
app/views/components/whenComponentis first used, so you don’t need to require them manually.
...$props is spread into the callable’s arguments. You can take any positional or named arguments:
<!-- app/views/components/button.php -->
<?php
Component::register('button', function (string $label, string $href = '#', string $variant = 'primary'): void { ?>
<a href="<?= htmlspecialchars($href) ?>" class="btn btn--<?= $variant ?>">
<?= htmlspecialchars($label) ?>
</a>
<?php });
<?php Component::render('button', 'Save', '/users/save', 'primary'); ?>
<?php Component::button('Cancel', '/users', 'secondary'); ?>
Use Component::return() when you need the rendered output as a string (for embedding in another component, for emails, etc.):
<?php
Component::register('emailBody', function (array $user): string {
return '<p>Hello ' . htmlspecialchars($user['name']) . '</p>';
});
$html = Component::return('emailBody', $user);
tiny::mailgun()->send($user['email'], 'Welcome', $html);
Components can render other components:
<?php
Component::register('postCard', function (array $post): void {
Component::render('userAvatar', $post['author']);
?>
<h2><?= htmlspecialchars($post['title']) ?></h2>
<p><?= htmlspecialchars($post['excerpt']) ?></p>
<?php
Component::render('tagList', $post['tags']);
});
If you have a component file outside the standard directory (for example a shared component library), include it with Component::require():
<?php Component::require('admin/data-table'); ?>
require() accepts either a string or an array of paths. The file is loaded once; subsequent calls are no-ops.
The callable can return early or branch:
<?php
Component::register('badge', function (string $label, ?string $color = null): void {
if (!$label) return;
?>
<span class="badge"<?= $color ? ' style="background:' . htmlspecialchars($color) . '"' : '' ?>>
<?= htmlspecialchars($label) ?>
</span>
<?php });
htmlspecialchars().Component::render() over the magic-method shortcut in shared code — it’s more grep-friendly.