Components

Components are reusable view snippets that can be included in multiple views or layouts. They help keep your code DRY (Don't Repeat Yourself) and make maintenance easier.

What are Components?

Components are PHP files stored in app/Views/components/ that contain reusable HTML/PHP code. Common use cases include:

  • Navigation bars
  • Footers
  • Cards and widgets
  • Forms and form fields
  • Buttons and badges
  • Modal dialogs
  • Any repeated UI element

Creating Components

Using CLI (Recommended)

php mini make:component Navbar

This creates: app/Views/components/navbar.php

Manual Creation

Create a PHP file in app/Views/components/:

<?php
// app/Views/components/navbar.php
?>
<nav class="bg-white shadow-md">
    <div class="max-w-7xl mx-auto px-4 py-4">
        <a href="/" class="text-xl font-bold">My App</a>
    </div>
</nav>

Using Components

Include components in your views using the View::component() method:

Basic Usage

<?php
// In any view file
use Core\View;

// Include component
View::component('navbar');
?>

With Data

<?php
use Core\View;

// Pass data to component
View::component('navbar', [
    'siteName' => 'My Awesome App',
    'currentPage' => 'home'
]);

Component Examples

Navigation Bar Component

<?php
// app/Views/components/navbar.php
$siteName = $siteName ?? 'My App';
$currentPage = $currentPage ?? '';
?>
<nav class="bg-white shadow-md">
    <div class="max-w-7xl mx-auto px-4 py-4 flex justify-between items-center">
        <a href="/" class="text-xl font-bold text-blue-600"><?php echo htmlspecialchars($siteName); ?></a>
        <div class="space-x-4">
            <a href="/" 
               class="<?php echo $currentPage === 'home' ? 'text-blue-600 font-semibold' : 'text-gray-700 hover:text-blue-600'; ?>">
                Home
            </a>
            <a href="/about" 
               class="<?php echo $currentPage === 'about' ? 'text-blue-600 font-semibold' : 'text-gray-700 hover:text-blue-600'; ?>">
                About
            </a>
            <a href="/contact" 
               class="<?php echo $currentPage === 'contact' ? 'text-blue-600 font-semibold' : 'text-gray-700 hover:text-blue-600'; ?>">
                Contact
            </a>
        </div>
    </div>
</nav>

Card Component

<?php
// app/Views/components/card.php
$title = $title ?? '';
$content = $content ?? '';
$footer = $footer ?? null;
?>
<div class="bg-white rounded-lg shadow-md p-6 mb-4">
    <?php if ($title): ?>
    <h3 class="text-xl font-semibold mb-3"><?php echo htmlspecialchars($title); ?></h3>
    <?php endif; ?>
    
    <div class="text-gray-700">
        <?php echo $content; ?>
    </div>
    
    <?php if ($footer): ?>
    <div class="mt-4 pt-4 border-t">
        <?php echo $footer; ?>
    </div>
    <?php endif; ?>
</div>

Using the Card Component

<?php
use Core\View;

// In your view
View::component('card', [
    'title' => 'User Profile',
    'content' => '<p>Welcome to your profile page!</p>',
    'footer' => '<a href="/edit" class="text-blue-600">Edit Profile</a>'
]);

// Or with user data
foreach ($users as $user) {
    View::component('card', [
        'title' => $user['name'],
        'content' => '<p>' . htmlspecialchars($user['email']) . '</p>',
        'footer' => '<a href="/users/' . $user['id'] . '">View Details</a>'
    ]);
}
?>

Components in Layouts

Components are commonly used in layouts to create consistent page structures:

<?php
// app/Views/layouts/main.php
use Core\View;
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php echo $title ?? 'My App'; ?></title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-50">
    <!-- Include navbar component -->
    <?php View::component('navbar', [
        'siteName' => $siteName ?? 'My App',
        'currentPage' => $currentPage ?? ''
    ]); ?>
    
    <!-- Main content -->
    <main class="max-w-7xl mx-auto px-4 py-8">
        <?php echo $content ?? ''; ?>
    </main>
    
    <!-- Include footer component -->
    <?php View::component('footer'); ?>
</body>
</html>

Advanced Components

Form Input Component

<?php
// app/Views/components/input.php
$name = $name ?? '';
$label = $label ?? '';
$type = $type ?? 'text';
$value = $value ?? '';
$error = $error ?? null;
$required = $required ?? false;
?>
<div class="mb-4">
    <label for="<?php echo $name; ?>" class="block text-sm font-medium text-gray-700 mb-1">
        <?php echo htmlspecialchars($label); ?>
        <?php if ($required): ?><span class="text-red-500">*</span><?php endif; ?>
    </label>
    <input 
        type="<?php echo $type; ?>" 
        id="<?php echo $name; ?>" 
        name="<?php echo $name; ?>" 
        value="<?php echo htmlspecialchars($value); ?>"
        class="w-full px-3 py-2 border rounded-md <?php echo $error ? 'border-red-500' : 'border-gray-300'; ?>"
        <?php if ($required): ?>required<?php endif; ?>
    >
    <?php if ($error): ?>
    <p class="text-red-500 text-sm mt-1"><?php echo htmlspecialchars($error); ?></p>
    <?php endif; ?>
</div>

Using Form Components

<?php
// app/Views/users/create.php
use Core\View;

View::layout('main');
?>

<form method="POST" action="/users" class="max-w-md mx-auto">
    <?php 
    View::component('input', [
        'name' => 'name',
        'label' => 'Full Name',
        'value' => $old['name'] ?? '',
        'error' => $errors['name'] ?? null,
        'required' => true
    ]);
    
    View::component('input', [
        'name' => 'email',
        'label' => 'Email Address',
        'type' => 'email',
        'value' => $old['email'] ?? '',
        'error' => $errors['email'] ?? null,
        'required' => true
    ]);
    ?>
    
    <button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700">
        Create User
    </button>
</form>

Best Practices

  • Keep components focused: Each component should have a single responsibility.
  • Use default values: Always provide defaults for component variables using the null coalescing operator (??).
  • Escape output: Always use htmlspecialchars() when outputting user data.
  • Name components clearly: Use descriptive names like navbar, user-card, form-input.
  • Document component props: Add comments explaining what data the component expects.

Next Steps

Now that you understand components, learn about: