Getting Started
Getting Started
This guide will help you understand the basics of Minimal Boot and create your first application components.
Project Structure
After installation, your project structure looks like this:
minimal-boot/
├── config/ # Configuration files
│ ├── autoload/ # Auto-loaded configuration
│ └── config.php # Main configuration aggregator
├── public/ # Web root directory
│ └── index.php # Application entry point
├── src/ # Application source code
│ ├── Core/ # Core infrastructure
│ ├── Page/ # Page management module
│ ├── Contact/ # Contact form module
│ ├── Auth/ # Authentication module
│ ├── Session/ # Session management
│ ├── Shared/ # Shared templates and components
│ └── Assets/ # Frontend asset build systems
├── var/ # Variable data (cache, logs)
└── vendor/ # Composer dependencies
Understanding Modules
Minimal Boot uses a modular architecture. Each module is self-contained with:
- Handlers - HTTP request handlers
- Domain - Business logic and entities (for complex modules)
- Templates - View templates
- Factories - Dependency injection factories
- Configuration - Module-specific configuration
Module Structure Example
src/Page/
├── Domain/ # Domain layer (DDD)
│ ├── Entity/ # Domain entities
│ ├── Repository/ # Data access interfaces
│ └── Service/ # Business logic services
├── Handler/ # HTTP handlers
├── Factory/ # DI factories
├── templates/ # Templates
├── ConfigProvider.php # Module configuration
└── RoutesDelegator.php # Route definitions
Creating Your First Page
Let’s create a simple “Hello World” page:
Step 1: Create a Handler
Create src/Page/Handler/HelloHandler.php
:
<?php
declare(strict_types=1);
namespace Minimal\Page\Handler;
use Laminas\Diactoros\Response\HtmlResponse;
use Mezzio\Template\TemplateRendererInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class HelloHandler implements RequestHandlerInterface
{
public function __construct(
private readonly TemplateRendererInterface $template
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
return new HtmlResponse(
$this->template->render('page::hello', [
'name' => $request->getQueryParams()['name'] ?? 'World'
])
);
}
}
Step 2: Create a Factory
Create src/Page/Factory/HelloHandlerFactory.php
:
<?php
declare(strict_types=1);
namespace Minimal\Page\Factory;
use Minimal\Page\Handler\HelloHandler;
use Mezzio\Template\TemplateRendererInterface;
use Psr\Container\ContainerInterface;
use function assert;
class HelloHandlerFactory
{
public function __invoke(ContainerInterface $container): HelloHandler
{
$template = $container->get(TemplateRendererInterface::class);
assert($template instanceof TemplateRendererInterface);
return new HelloHandler($template);
}
}
Step 3: Create a Template
Create src/Page/templates/hello.phtml
:
<?php
$layout('layout::default', [
'title' => 'Hello Page',
'description' => 'A simple hello world page',
]);
?>
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-body text-center">
<h1 class="card-title">Hello, <?= $this->escapeHtml($name) ?>!</h1>
<p class="card-text">Welcome to Minimal Boot framework.</p>
<a href="/" class="btn btn-primary">Go Home</a>
</div>
</div>
</div>
</div>
</div>
Step 4: Register the Handler
Update src/Page/ConfigProvider.php
:
// Add to the use statements
use Minimal\Page\Factory\HelloHandlerFactory;
use Minimal\Page\Handler\HelloHandler;
// Add to the factories array
'factories' => [
// ... existing factories
HelloHandler::class => HelloHandlerFactory::class,
],
Step 5: Add the Route
Update src/Page/RoutesDelegator.php
:
// Add to the use statements
use Minimal\Page\Handler\HelloHandler;
// Add the route in the __invoke method
$app->get('/hello', [HelloHandler::class], 'page::hello');
Step 6: Test Your Page
- Clear the configuration cache:
php bin/clear-config-cache.php
- Visit
http://localhost:8080/hello
in your browser - Try with a name parameter:
http://localhost:8080/hello?name=John
Working with Domain Layer
For more complex business logic, use the Domain layer:
Creating a Domain Entity
<?php
declare(strict_types=1);
namespace Minimal\Page\Domain\Entity;
class Article
{
public function __construct(
private readonly string $id,
private readonly string $title,
private readonly string $content,
private readonly \DateTimeImmutable $publishedAt
) {
}
public function getId(): string
{
return $this->id;
}
public function getTitle(): string
{
return $this->title;
}
public function getContent(): string
{
return $this->content;
}
public function getPublishedAt(): \DateTimeImmutable
{
return $this->publishedAt;
}
public function isPublished(): bool
{
return $this->publishedAt <= new \DateTimeImmutable();
}
}
Creating a Repository Interface
<?php
declare(strict_types=1);
namespace Minimal\Page\Domain\Repository;
use Minimal\Page\Domain\Entity\Article;
interface ArticleRepositoryInterface
{
public function findById(string $id): ?Article;
/**
* @return array<Article>
*/
public function findPublished(): array;
public function save(Article $article): void;
}
Template System
Minimal Boot uses native PHP templates with a layout system:
Layout Usage
<?php
// At the top of your template
$layout('layout::default', [
'title' => 'Page Title',
'description' => 'SEO description',
'author' => 'Author Name'
]);
?>
<!-- Your content here -->
<h1><?= $this->escapeHtml($title) ?></h1>
Available Layouts
layout::default
- Bootstrap layout with navigationlayout::tailwind
- TailwindCSS layout with Alpine.jslayout::bootstrap
- Pure Bootstrap layout
Configuration
Module Configuration
Each module has a ConfigProvider.php
that defines:
- Dependencies (factories, aliases)
- Routes (via RoutesDelegator)
- Templates paths
- Module-specific configuration
Global Configuration
Configuration files in config/autoload/
are automatically loaded:
*.global.php
- Global configuration*.local.php
- Local/environment-specific configuration*.production.php
- Production-specific configuration
Next Steps
- Architecture - Deep dive into the framework architecture
- Modules - Advanced module development
- Templates - Template system details
- Domain Layer - Domain-Driven Design patterns