PHPackages                             kalimeromk/slim-mvc-starter - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. kalimeromk/slim-mvc-starter

ActiveProject[Framework](/categories/framework)

kalimeromk/slim-mvc-starter
===========================

A production-ready Slim 4 MVC Starter Kit with Eloquent ORM, database migrations, JWT authentication, role-based permissions, and modular architecture

v2.1.1(1mo ago)35MITPHPPHP &gt;=8.3

Since Nov 14Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/KalimeroMK/Slim4MVC)[ Packagist](https://packagist.org/packages/kalimeromk/slim-mvc-starter)[ RSS](/packages/kalimeromk-slim-mvc-starter/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (6)Dependencies (24)Versions (14)Used By (0)

Slim 4 MVC Starter Kit
======================

[](#slim-4-mvc-starter-kit)

A modern, production-ready starter kit for building web applications with Slim Framework 4, featuring Eloquent ORM, Blade templating, comprehensive authentication, and a robust testing suite.

🚀 Features
----------

[](#-features)

- **MVC Architecture** - Clean separation of concerns with Slim 4
- **Eloquent ORM** - Laravel's powerful database toolkit
- **Blade Templating** - Lightweight BladeOne engine with custom directives (@auth, @guest, @csrf, @method, @can, @role)
- **Authentication System** - JWT-based API auth and session-based web auth
- **Authorization** - Role and permission-based access control with middleware and policies
- **Form Request Validation** - Laravel-style validation with automatic error handling
- **Rate Limiting** - Built-in protection against brute force attacks with trusted proxy support
- **Security Headers** - Automatic `X-Frame-Options`, `X-Content-Type-Options`, `Referrer-Policy`, `HSTS` and more via `SecurityHeadersMiddleware`
- **CORS Support** - Configurable CORS middleware for API endpoints
- **Error Logging** - PSR-3 compatible logging with Monolog
- **API Resources** - Consistent API response formatting with Resource classes
- **Consistent API Responses** - Standardized JSON responses with enums and helper methods
- **Repository Pattern** - Clean data access layer abstraction for better testability and maintainability
- **Exception Handling** - Custom exception classes with centralized exception handling middleware
- **Caching Layer** - Multi-driver cache system (File, Redis, Null) with helper functions
- **Cookie Helper** - Encrypted cookie management with AES-256-CBC
- **API Query Builder** - Filter, sort, search with operators and pagination
- **Testing Suite** - Comprehensive test coverage with PHPUnit (286+ tests, 599+ assertions)
- **CLI Commands** - Artisan-like commands for scaffolding (modules, models, controllers, requests)
- **Modular Architecture** - Feature-based module organization for better scalability
- **Automatic Dependency Registration** - Dependencies automatically registered when creating modules
- **PHP 8.4 Ready** - Modern PHP features and Rector automated refactoring
- **Docker Ready** - Complete Docker setup for development
- **Environment Validation** - Fail-fast configuration validation
- **Auto-Discovery** - Automatic DI registration with caching
- **Generic CRUD** - Reusable CRUD with 87% less code

📋 Requirements
--------------

[](#-requirements)

- PHP &gt;= 8.4
- Composer
- Docker &amp; Docker Compose (for development)
- MySQL/MariaDB (or SQLite for testing)

🛠️ Installation
---------------

[](#️-installation)

1. **Clone the repository:**

    ```
    git clone https://github.com/KalimeroMK/Slim4MVC
    cd Slim4MVC
    ```
2. **Install dependencies:**

    ```
    composer install
    ```
3. **Configure environment:**

    ```
    cp .env.example .env
    ```

    Edit `.env` and configure:

    - Database credentials
    - JWT\_SECRET (generate a strong secret key)
    - Mail settings
    - CORS origins (if needed)
    - Cache driver (file/redis) and Redis settings (if using Redis)
    - Cookie settings (encryption, secure flags for production)
4. **Start Docker containers:**

    ```
    docker-compose up -d
    ```
5. **Clear cache (if you encounter namespace errors):**

    ```
    php clear-cache.php
    docker compose restart
    ```
6. **Run migrations:**

    ```
    php run_migrations.php
    ```
7. **Seed database (optional):**

    ```
    php slim seed:database
    ```
8. **Setup storage permissions:**

    ```
    # Using PHP script (recommended)
    php setup-storage.php

    # Or using bash script
    ./setup-storage.sh

    # Or manually
    chmod -R 775 storage
    chown -R www-data:www-data storage  # Adjust user/group as needed
    ```

The application will be available at

📁 Project Structure
-------------------

[](#-project-structure)

The project uses a **modular architecture** where each feature is organized as an independent module:

```
├── app/
│   ├── Console/               # CLI Commands
│   │   └── Commands/         # Console commands (make:module, make:request, etc.)
│   ├── Modules/              # Feature modules
│   │   ├── Core/             # Core module (base classes, middleware, support)
│   │   │   ├── Application/
│   │   │   │   ├── Actions/  # Core actions (Auth actions)
│   │   │   │   ├── DTOs/     # Core DTOs
│   │   │   │   ├── Enums/    # Enums (HttpStatusCode, ApiResponseStatus)
│   │   │   │   └── Interfaces/
│   │   │   └── Infrastructure/
│   │   │       ├── Events/   # Event system
│   │   │       ├── Exceptions/ # Custom exceptions
│   │   │       ├── Http/
│   │   │       │   ├── Controllers/ # Base controllers
│   │   │       │   ├── Middleware/  # Middleware
│   │   │       │   ├── Requests/    # Base FormRequest
│   │   │       │   └── Resources/   # Base Resource
│   │   │       ├── Jobs/     # Queue jobs
│   │   │       ├── Policies/ # Base Policy
│   │   │       ├── Providers/ # Service providers
│   │   │       ├── Queue/    # Queue system
│   │   │       ├── Repositories/ # Base repositories
│   │   │       ├── Support/  # Helper classes (Auth, Logger, Mailer, Cookie)
│   │   │       ├── Cache/    # Cache system (File, Redis, Null drivers)
│   │   │       ├── Query/    # API Query Builder (filter, sort, search)
│   │   │       └── View/     # Blade integration
│   │   ├── Auth/             # Authentication module
│   │   │   ├── Application/
│   │   │   │   ├── Actions/Auth/  # Login, Register, PasswordRecovery, etc.
│   │   │   │   ├── DTOs/Auth/    # Auth DTOs
│   │   │   │   └── Interfaces/Auth/
│   │   │   └── Infrastructure/
│   │   │       ├── Http/
│   │   │       │   ├── Controllers/
│   │   │       │   │   ├── Api/    # API AuthController (JWT)
│   │   │       │   │   └── Web/    # Web AuthController (Session)
│   │   │       │   └── Requests/Auth/
│   │   │       ├── Providers/ # AuthServiceProvider
│   │   │       └── Routes/    # API and Web routes
│   │   ├── User/             # User module
│   │   ├── Role/             # Role module
│   │   └── Permission/      # Permission module
│   └── Support/             # Legacy support (backward compatibility)
├── bootstrap/                # Application bootstrap files
│   ├── modules.php          # Module loader
│   └── modules-register.php # Module registration
├── database/
│   ├── migrations/           # Database migrations
│   └── seed/                 # Database seeders
├── public/                   # Web root
├── resources/
│   ├── views/                # Blade templates
│   └── lang/                 # Translation files
├── routes/                   # Main route files (web.php, api.php)
├── stubs/                    # Code generation stubs
│   └── Module/              # Module structure stubs
├── storage/
│   ├── cache/                # Application cache
│   │   ├── data/             # File cache storage
│   │   └── view/             # Blade compiled views
│   ├── logs/                 # Application logs
│   ├── queue/                # Queue storage (file driver)
│   └── sessions/             # Session storage (file driver)
└── tests/                    # PHPUnit tests
    ├── Unit/                  # Unit tests
    └── Feature/               # Feature tests

```

### Module Structure

[](#module-structure)

Each module follows a consistent structure:

```
app/Modules/Example/
├── Application/              # Business logic layer
│   ├── Actions/             # Business logic actions
│   ├── DTOs/                # Data Transfer Objects
│   ├── Services/            # Service classes
│   └── Interfaces/          # Service contracts
├── Infrastructure/          # Infrastructure layer
│   ├── Models/              # Eloquent models
│   ├── Repositories/        # Data access layer
│   ├── Http/
│   │   ├── Controllers/     # Request handlers
│   │   ├── Requests/       # Form request validation
│   │   └── Resources/      # API resource transformers
│   ├── Providers/          # Service providers
│   └── Routes/             # Module routes (api.php, web.php)
├── Exceptions/             # Module-specific exceptions
├── Observers/              # Eloquent observers
└── Policies/               # Authorization policies

```

🎯 Usage
-------

[](#-usage)

### Creating Modules

[](#creating-modules)

The recommended way to create new features is using the **modular architecture**:

```
# Create a new module
php slim make:module Product

# Create module with custom model name
php slim make:module Product --model=Item

# Create module with migration
php slim make:module Product --migration
```

This will automatically create:

- Complete module structure (Application, Infrastructure layers)
- Actions (Create, Update, Delete, Get, List)
- DTOs (Create, Update)
- Interfaces (CreateActionInterface, UpdateActionInterface)
- Model and Repository
- Controller with CRUD methods
- Form Requests (Create, Update)
- API Resource
- Policy
- Service Provider
- API Routes
- **Automatic dependency registration** in `bootstrap/dependencies.php`
- **Automatic module registration** in `bootstrap/modules-register.php`

**Example:**

```
php slim make:module Blog --model=Post --migration
```

This creates:

- `app/Modules/Blog/` with complete structure
- `CreatePostAction`, `UpdatePostAction`, etc.
- `PostRepository` automatically registered in Service Provider
- `CreatePostActionInterface` and `UpdatePostActionInterface` automatically registered in `bootstrap/dependencies.php`
- Module automatically registered in `bootstrap/modules-register.php`

### Creating Models and Migrations

[](#creating-models-and-migrations)

```
# Create a model
php slim make:model Product

# Create a model with migration
php slim make:model Product -m
```

### Creating Controllers

[](#creating-controllers)

```
php slim make:controller Product
```

This will create:

- Controller
- Actions (Create, Update, Delete, Get, List)
- DTOs (Create, Update)
- Form Requests (Create, Update)

### Creating Form Requests

[](#creating-form-requests)

```
# Create a basic request
php slim make:request User/CreateUserRequest

# Create request with auto-generated rules from model
php slim make:request User/CreateUserRequest --model=User

# Create update request with model
php slim make:request User/UpdateUserRequest --model=User --type=update

# Short syntax
php slim make:request User/CreateUserRequest -m User -t create
```

The `--model` option automatically generates validation rules based on the model's `$fillable` fields and `$casts`.

### Running Migrations

[](#running-migrations)

```
# Run migrations
php run_migrations.php

# Rollback last migration
php run_migrations.php rollback

# Refresh all migrations
php run_migrations.php refresh
```

### Available Commands

[](#available-commands)

```
# Module creation
php slim make:module  [--model=] [--migration]

# Model creation
php slim make:model  [-m]

# Controller creation
php slim make:controller

# Request creation
php slim make:request  [--model=] [--type=]

# Database seeding
php slim seed:database

# Queue processing
php slim queue:work [--stop-when-empty] [--max-jobs=]

# Cache management
php slim cache:clear [--tag=] [--driver=]

# List all routes
php slim list-routes
```

### Running Tests

[](#running-tests)

```
# Run all tests
./vendor/bin/phpunit
# or
composer test

# Run with detailed output
./vendor/bin/phpunit --testdox

# Run specific test suite
./vendor/bin/phpunit tests/Unit
```

🔐 Authentication
----------------

[](#-authentication)

The application includes a dedicated **Auth module** that handles both API and Web authentication.

### Auth Module

[](#auth-module)

The Auth module (`app/Modules/Auth/`) provides:

- **API Authentication** - JWT-based authentication for API endpoints
- **Web Authentication** - Session-based authentication for web routes
- **Password Recovery** - Token-based password reset functionality
- **Event-driven** - Dispatches events for user registration and password reset

### API Authentication (JWT)

[](#api-authentication-jwt)

The API uses JWT tokens for authentication. After successful login, include the token in requests:

```
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" http://localhost:81/api/v1/users
```

### Web Authentication (Session)

[](#web-authentication-session)

Web routes use session-based authentication. The `AuthWebMiddleware` handles authentication for web routes.

🛡️ Authorization
----------------

[](#️-authorization)

### Using Middleware

[](#using-middleware)

**Role-based access:**

```
$app->get('/admin/dashboard', [DashboardController::class, 'index'])
    ->add(new CheckRoleMiddleware())
    ->setArgument('roles', 'admin');

// Multiple roles (user needs one of these)
$app->get('/reports', [ReportController::class, 'index'])
    ->add(new CheckRoleMiddleware())
    ->setArgument('roles', ['admin', 'manager']);
```

**Permission-based access:**

```
$app->post('/users', [UserController::class, 'store'])
    ->add(new CheckPermissionMiddleware())
    ->setArgument('permissions', 'create-users');

// Multiple permissions
$app->put('/posts/{id}', [PostController::class, 'update'])
    ->add(new CheckPermissionMiddleware())
    ->setArgument('permissions', ['edit-posts', 'publish-posts']);
```

### Using Policies

[](#using-policies)

Create a policy:

```
// app/Policies/PostPolicy.php
class PostPolicy extends Policy
{
    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id ||
               $user->hasPermission('edit-posts');
    }
}
```

Use in controller:

```
public function update(Request $request, Response $response, int $id): Response
{
    $post = Post::find($id);

    if (!$this->authorize('update', $post)) {
        return $this->respondUnauthorized();
    }

    // Update logic...
}
```

⚡ Rate Limiting
---------------

[](#-rate-limiting)

Rate limiting is automatically applied to authentication endpoints (5 requests per minute). You can apply it to any route:

```
use App\Modules\Core\Infrastructure\Http\Middleware\RateLimitMiddleware;

$rateLimit = new RateLimitMiddleware(10, 60); // 10 requests per 60 seconds
$app->post('/api/endpoint', [Controller::class, 'method'])
    ->add($rateLimit);
```

When running behind a load balancer or reverse proxy, set `TRUSTED_PROXIES` in `.env` so the real client IP is used for rate limiting instead of the proxy IP:

```
TRUSTED_PROXIES=10.0.0.1,10.0.0.2
```

`X-Forwarded-For` is only trusted when `REMOTE_ADDR` matches a listed proxy, and the extracted IP is validated before use.

🌐 CORS Configuration
--------------------

[](#-cors-configuration)

CORS is configured globally in `bootstrap/middleware.php`. Configure allowed origins in `.env`:

```
CORS_ORIGINS=*
# or specific origins
CORS_ORIGINS=http://localhost:3000,https://example.com
```

📝 Logging
---------

[](#-logging)

The application uses Monolog for logging. Use the Logger helper:

```
use App\Modules\Core\Infrastructure\Support\Logger;

Logger::error('Something went wrong', ['user_id' => 123]);
Logger::warning('Suspicious activity detected');
Logger::info('User logged in', ['email' => $email]);
Logger::debug('Debug information', $data);
```

Logs are written to `storage/logs/slim.log`. Log level is automatically set based on `APP_ENV`:

- `production`: Warning and above
- `local`/`development`: Debug and above

🎨 Blade Templating
------------------

[](#-blade-templating)

This project uses **BladeOne** - a lightweight, standalone Blade engine optimized for Slim 4. It provides the same Blade syntax as Laravel but without the heavy dependencies.

### Custom Blade Directives

[](#custom-blade-directives)

The following Laravel-like directives are available:

#### Authentication Directives

[](#authentication-directives)

```
@guest
    Login
    Register
@endguest

@auth
    Welcome, {{ AuthHelper::user()['name'] }}!

        @csrf
        Logout

@endauth
```

#### CSRF Protection

[](#csrf-protection)

```

    @csrf

```

#### HTTP Method Spoofing

[](#http-method-spoofing)

```

    @csrf
    @method('DELETE')
    Delete User

```

#### Authorization Directives

[](#authorization-directives)

```
@can('edit-posts')
    Edit Post
@endcan

@role('admin')
    Admin Panel
@endrole
```

### AuthHelper Class

[](#authhelper-class)

The `AuthHelper` class provides static methods for authentication:

```
use App\Modules\Core\Infrastructure\Support\AuthHelper;

// Check authentication
if (AuthHelper::check()) {
    // User is logged in
}

// Check if guest
if (AuthHelper::guest()) {
    // User is not logged in
}

// Get current user
$user = AuthHelper::user();
echo $user['name'];

// Get user ID
$userId = AuthHelper::id();

// Check permissions and roles
if (AuthHelper::can('create-posts')) {
    // User can create posts
}

if (AuthHelper::hasRole('admin')) {
    // User is admin
}

// Set user data after login
AuthHelper::setUser([
    'id' => $user->id,
    'name' => $user->name,
    'email' => $user->email,
    'roles' => ['user', 'editor'],
    'permissions' => ['view-posts', 'create-posts']
]);

// Logout user
AuthHelper::logout();
```

### Standard Blade Syntax

[](#standard-blade-syntax)

All standard Blade directives work as expected:

```
@extends('layouts.app')

@section('content')
    {{ $title }}

    @foreach($users as $user)
        {{ $user->name }}
    @endforeach

    @if($condition)
        {{ $message }}
    @elseif($otherCondition)
        Other message
    @else
        Default message
    @endif

    @include('partials.footer')
@endsection
```

🧪 Testing
---------

[](#-testing)

The project includes a comprehensive test suite covering:

### Test Suites

[](#test-suites)

SuiteTestsDescription**Unit**404+Isolated component tests**Integration**63+Database and service integration**Feature**21+End-to-end API tests**Edge Cases**18+Boundary and unusual scenarios### New in v2.0 (173 additional tests)

[](#new-in-v20-173-additional-tests)

#### Environment Validation Tests (48 tests)

[](#environment-validation-tests-48-tests)

- Production environment validation
- Local/development environment validation
- Weak secret detection
- Missing configuration detection
- Edge cases (unicode, special chars, boundary values)

#### JWT Service Tests (51 tests)

[](#jwt-service-tests-51-tests)

- Token generation and validation
- Refresh token rotation
- Fingerprint-based security
- Token theft detection
- Multiple algorithms (HS256, HS384, HS512)
- Edge cases (expired tokens, tampered tokens)

#### Auto-Discovery Tests (35 tests)

[](#auto-discovery-tests-35-tests)

- Module scanning
- Cache warming and clearing
- Production vs development behavior
- Statistics generation

#### Generic CRUD Tests (39 tests)

[](#generic-crud-tests-39-tests)

- Create, Read, Update, Delete operations
- Pagination
- Action factory
- Integration with real database

### Running Tests

[](#running-tests-1)

```
# Run all tests
composer test

# Run specific test suites
./vendor/bin/phpunit --testsuite Unit
./vendor/bin/phpunit --testsuite Integration
./vendor/bin/phpunit --testsuite Feature
./vendor/bin/phpunit --testsuite EdgeCases

# Run with coverage
./vendor/bin/phpunit --coverage-html coverage

# Run specific test file
./vendor/bin/phpunit tests/Unit/EnvironmentValidatorTest.php
```

### Test Coverage

[](#test-coverage)

- ✅ 475+ tests
- ✅ 900+ assertions
- ✅ All new features tested
- ✅ Edge cases covered
- ✅ Integration with real database
- ✅ PHP 8.4 optimized with Rector

### Code Quality Tools

[](#code-quality-tools)

**Laravel Pint** (Code formatting):

```
# Check code style
./vendor/bin/pint --test

# Fix code style
./vendor/bin/pint
```

**Rector** (Automated refactoring):

```
# Check what would be changed
./vendor/bin/rector process --dry-run

# Apply refactoring
./vendor/bin/rector process
```

**Combined (CI/CD ready):**

```
./vendor/bin/pint && ./vendor/bin/rector process && ./vendor/bin/phpunit
```

🔧 Configuration
---------------

[](#-configuration)

### Environment Variables

[](#environment-variables)

Key environment variables in `.env`:

```
# Application
APP_ENV=local
APP_URL=http://localhost:81

# Database
DB_CONNECTION=mysql
DB_HOST=slim_db
DB_PORT=3306
DB_DATABASE=slim
DB_USERNAME=slim
DB_PASSWORD=secret

# JWT
JWT_SECRET=your-secret-key-here

# Mail
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=your_email@example.com
MAIL_PASSWORD=your_password
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="Your App Name"
MAIL_ENCRYPTION=tls

# CORS
CORS_ORIGINS=*

# Trusted Proxies (comma-separated IPs — set when behind a load balancer/reverse proxy)
TRUSTED_PROXIES=

# Cache
CACHE_DRIVER=redis
CACHE_PREFIX=slim_cache
CACHE_PATH=/var/www/html/storage/cache/data
REDIS_CACHE_DATABASE=1

# Queue
QUEUE_DRIVER=redis
QUEUE_RETRY_AFTER=90

# Session
SESSION_DRIVER=redis
SESSION_LIFETIME=120

# Cookies
COOKIE_TTL=3600
COOKIE_PATH=/
COOKIE_DOMAIN=
COOKIE_SECURE=true
COOKIE_HTTP_ONLY=true
COOKIE_SAME_SITE=Lax
COOKIE_ENCRYPT=true
```

📦 API Resources
---------------

[](#-api-resources)

The application uses Resource classes to format API responses consistently:

```
use App\Modules\User\Infrastructure\Http\Resources\UserResource;

// Single resource
return ApiResponse::success(UserResource::make($user));

// Collection
return ApiResponse::success(UserResource::collection($users));
```

Available Resources:

- `UserResource` - Formats user data (hides password, includes roles)
- `RoleResource` - Formats role data (includes permissions)
- `PermissionResource` - Formats permission data (includes roles)

📊 API Response Format
---------------------

[](#-api-response-format)

All API responses follow a consistent format using the `ApiResponse` helper:

**Success Response:**

```
{
  "status": "success",
  "data": {...},
  "message": "Optional message"
}
```

**Error Response:**

```
{
  "status": "error",
  "message": "Error message",
  "code": "ERROR_CODE",
  "errors": {
    "field": ["Error message"]
  }
}
```

**Usage in Controllers:**

```
use App\Support\ApiResponse;
use App\Enums\HttpStatusCode;

// Success
return ApiResponse::success($data);
return ApiResponse::success($user, HttpStatusCode::CREATED);

// Errors
return ApiResponse::error('Error message');
return ApiResponse::unauthorized();
return ApiResponse::notFound('User not found');
return ApiResponse::validationError(['email' => ['Invalid email']]);
```

📚 API Endpoints
---------------

[](#-api-endpoints)

### Authentication

[](#authentication)

- `POST /api/v1/register` - Register new user
- `POST /api/v1/login` - Login and get JWT token
- `POST /api/v1/password-recovery` - Request password reset
- `POST /api/v1/reset-password` - Reset password with token

### Users (requires authentication)

[](#users-requires-authentication)

- `GET /api/v1/users` - List all users
- `POST /api/v1/users` - Create user
- `GET /api/v1/users/{id}` - Get user
- `PUT /api/v1/users/{id}` - Update user
- `DELETE /api/v1/users/{id}` - Delete user

### Roles (requires authentication)

[](#roles-requires-authentication)

- `GET /api/v1/roles` - List all roles
- `POST /api/v1/roles` - Create role
- `GET /api/v1/roles/{id}` - Get role
- `PUT /api/v1/roles/{id}` - Update role
- `DELETE /api/v1/roles/{id}` - Delete role

### Permissions (requires authentication)

[](#permissions-requires-authentication)

- `GET /api/v1/permissions` - List all permissions
- `POST /api/v1/permissions` - Create permission
- `GET /api/v1/permissions/{id}` - Get permission
- `PUT /api/v1/permissions/{id}` - Update permission
- `DELETE /api/v1/permissions/{id}` - Delete permission

🏗️ Architecture
---------------

[](#️-architecture)

The project follows a **modular clean architecture** pattern:

### Modular Architecture

[](#modular-architecture)

The application is organized into **independent modules**, each containing:

1. **Application Layer** - Business logic

    - **Actions** - Business logic operations
    - **DTOs** - Data Transfer Objects for type-safe data handling
    - **Interfaces** - Service contracts for dependency injection
    - **Services** - Complex business logic services
2. **Infrastructure Layer** - Technical implementation

    - **Models** - Eloquent models for database interaction
    - **Repositories** - Data access layer abstraction (Repository pattern)
    - **Controllers** - Thin controllers that delegate to Actions
    - **Requests** - Form request validation
    - **Resources** - API response transformers
    - **Providers** - Service providers for dependency registration
    - **Routes** - Module-specific routes
3. **Cross-cutting Concerns**

    - **Middleware** - Request/response processing
    - **Policies** - Authorization logic
    - **Exceptions** - Custom exception classes for better error handling
    - **Events** - Event-driven architecture
    - **Jobs** - Asynchronous task processing

### Module Registration

[](#module-registration)

Modules are automatically registered via `bootstrap/modules-register.php`:

```
return [
    // Core module must be loaded first
    App\Modules\Core\Infrastructure\Providers\CoreServiceProvider::class,

    // Auth module
    App\Modules\Auth\Infrastructure\Providers\AuthServiceProvider::class,

    // Feature modules
    App\Modules\User\Infrastructure\Providers\UserServiceProvider::class,
    App\Modules\Role\Infrastructure\Providers\RoleServiceProvider::class,
    App\Modules\Permission\Infrastructure\Providers\PermissionServiceProvider::class,
];
```

### Dependency Injection

[](#dependency-injection)

The application uses **PHP-DI** with automatic dependency registration:

- **Repositories** - Automatically registered in Service Providers
- **Action Interfaces** - Automatically registered in `bootstrap/dependencies.php` when using `make:module`
- **Autowiring** - PHP-DI automatically resolves constructor dependencies

**How it works:**

1. **When creating a module** with `make:module`:

    - Repository is registered in `ServiceProvider::register()`
    - Action Interfaces are registered in `bootstrap/dependencies.php`
    - Use statements are automatically added
2. **PHP-DI Autowiring**:

    - Automatically resolves concrete classes (no registration needed)
    - Resolves constructor dependencies via type hints
    - Example: `LoginAction` needs `UserRepository` → automatically injected
3. **Interface-based injection**:

    - Controllers use interfaces (e.g., `CreateUserActionInterface`)
    - PHP-DI resolves to implementation via `dependencies.php`
    - Allows for easy mocking in tests

### Repository Pattern

[](#repository-pattern)

The application uses the Repository pattern to abstract data access logic:

```
use App\Modules\User\Infrastructure\Repositories\UserRepository;

class UserController extends Controller
{
    public function __construct(
        private readonly UserRepository $repository
    ) {}

    public function show(int $id): Response
    {
        $user = $this->repository->findOrFail($id);
        return ApiResponse::success(UserResource::make($user));
    }
}
```

**Automatic Registration:**When you create a module with `make:module`, the Repository is automatically registered in the Service Provider:

```
// ServiceProvider::register()
$container->set(UserRepository::class, \DI\autowire(UserRepository::class));
```

Available Repositories:

- `UserRepository` - User data access with methods like `findByEmail()`, `findByPasswordResetToken()`
- `RoleRepository` - Role data access with methods like `findByName()`, `paginateWithPermissions()`
- `PermissionRepository` - Permission data access with methods like `findByName()`, `paginateWithRoles()`

### Action Pattern with Interfaces

[](#action-pattern-with-interfaces)

Actions implement interfaces for better testability and flexibility:

```
// Interface
interface CreateUserActionInterface
{
    public function execute(CreateUserDTO $dto): User;
}

// Implementation
final class CreateUserAction implements CreateUserActionInterface
{
    public function __construct(
        private readonly UserRepository $repository
    ) {}

    public function execute(CreateUserDTO $dto): User
    {
        return $this->repository->create([...]);
    }
}
```

**Automatic Registration:**When you create a module, Action Interfaces are automatically registered in `bootstrap/dependencies.php`:

```
CreateUserActionInterface::class => \DI\autowire(CreateUserAction::class),
```

### Working with Modules

[](#working-with-modules)

**Creating a new module:**

```
php slim make:module Product --migration
```

This creates a complete module structure. After creation:

1. **Update the Model** (`app/Modules/Product/Infrastructure/Models/Product.php`):

    - Add `$fillable` fields
    - Add `$casts` for type casting
    - Add relationships if needed
2. **Update the DTOs** (`app/Modules/Product/Application/DTOs/`):

    - Add properties to `CreateProductDTO`
    - Add optional properties to `UpdateProductDTO`
3. **Update the Actions** (`app/Modules/Product/Application/Actions/`):

    - Map DTO properties to model attributes in `CreateProductAction`
    - Add business logic as needed
4. **Update the Controller** (`app/Modules/Product/Infrastructure/Http/Controllers/ProductController.php`):

    - Map request data to DTOs in `store()` and `update()` methods
5. **Update the Resource** (`app/Modules/Product/Infrastructure/Http/Resources/ProductResource.php`):

    - Add fields to the resource output
6. **Update the Requests** (`app/Modules/Product/Infrastructure/Http/Requests/`):

    - Add validation rules as needed
7. **Update the Policy** (`app/Modules/Product/Policies/ProductPolicy.php`):

    - Add authorization logic

**Module is ready to use!** Routes are automatically loaded from `app/Modules/Product/Infrastructure/Routes/api.php`.

### Exception Handling

[](#exception-handling)

Custom exception classes provide consistent error handling:

```
use App\Modules\Core\Infrastructure\Exceptions\NotFoundException;
use App\Modules\Core\Infrastructure\Exceptions\InvalidCredentialsException;
use App\Modules\Core\Infrastructure\Exceptions\UnauthorizedException;
use App\Modules\Core\Infrastructure\Exceptions\ForbiddenException;
use App\Modules\Core\Infrastructure\Exceptions\BadRequestException;

// In Actions
throw new NotFoundException('User not found');
throw new InvalidCredentialsException('Invalid email or password');
```

The `ExceptionHandlerMiddleware` automatically converts exceptions to appropriate API responses.

🆕 New Features
--------------

[](#-new-features)

### Environment Validation (Fail-Fast)

[](#environment-validation-fail-fast)

Environment validation runs automatically at application startup to catch configuration errors early.

```
# Validate configuration
php slim discovery --validate
```

**Features:**

- Validates `JWT_SECRET` length (minimum 32 characters)
- Checks database connectivity
- Validates `APP_ENV` settings
- Production-specific checks (Redis, Mail, Cache)

**Example Output:**

```
🔒 Environment Validation
═══════════════════════════════════════════════════════════════

✅ Environment configuration is valid

 ------------------- ----------
  Setting             Value
 ------------------- ----------
  Environment         local
  JWT Configured      Yes
  JWT Secret Length   42 chars
  DB Connection       mysql
 ------------------- ----------

```

### Auto-Discovery for Dependency Injection

[](#auto-discovery-for-dependency-injection)

Automatically discovers and registers Interface → Implementation bindings.

```
# View discovery statistics
php slim discovery --stats

# Warm cache for production
php slim discovery --warm

# Refresh cache
php slim discovery --refresh
```

**Before (Manual Registration):**

```
// bootstrap/dependencies.php
return [
    CreateUserActionInterface::class => autowire(CreateUserAction::class),
    UpdateUserActionInterface::class => autowire(UpdateUserAction::class),
    // ... 80+ more lines
];
```

**After (Auto-Discovery):**

```
// bootstrap/dependencies.php
$discovery = new OptimizedDiscovery();
return $discovery->buildDefinitions();
```

### JWT Service with Refresh Tokens

[](#jwt-service-with-refresh-tokens)

Enhanced JWT implementation with security best practices.

```
use App\Modules\Core\Infrastructure\Support\AdvancedJwtService;

$jwtService = new AdvancedJwtService(
    secret: $_ENV['JWT_SECRET'],
    algorithm: 'HS256',
    issuer: 'my-app',
    audience: 'my-api'
);

// Generate access token
$token = $jwtService->generateAccessToken(
    userId: 123,
    claims: ['role' => 'admin'],
    ttl: 3600 // 1 hour
);

// Generate token pair (access + refresh)
$tokenPair = $jwtService->generateRefreshToken(userId: 123);
// Returns: access_token, refresh_token, expires_in

// Rotate refresh token (security best practice)
$newPair = $jwtService->rotateRefreshToken($tokenPair->getRefreshToken());

// Validate token
if ($jwtService->verify($token)) {
    $payload = $jwtService->decode($token);
    $userId = $payload->sub;
}

// Get token info
$info = $jwtService->getTokenInfo($token);
// Returns: algorithm, type, issuer, expires_at, is_expired, etc.
```

**Features:**

- Access tokens (short-lived)
- Refresh tokens (long-lived with rotation)
- Fingerprint-based theft detection
- Issuer and audience validation
- Token blacklisting support

### Generic CRUD Controller

[](#generic-crud-controller)

Build complete CRUD APIs with minimal code.

**Before (150 lines):**

```
class UserController extends Controller
{
    public function __construct(
        private CreateUserAction $createAction,
        private UpdateUserAction $updateAction,
        // ... 5 more actions
    ) {}

    public function index(Request $request): Response { /* 20 lines */ }
    public function store(Request $request): Response { /* 15 lines */ }
    public function show(Request $request, array $args): Response { /* 10 lines */ }
    public function update(Request $request, array $args): Response { /* 15 lines */ }
    public function destroy(Request $request, array $args): Response { /* 10 lines */ }
}
```

**After (20 lines):**

```
class UserController extends GenericCrudController
{
    protected string $repositoryClass = UserRepository::class;
    protected ?string $resourceClass = UserResource::class;
    protected array $defaultRelations = ['roles'];
    protected array $fillable = ['name', 'email', 'password'];
}
```

**Benefits:**

- **87% less code**
- **67% faster development**
- Automatic pagination, relations, and validation
- Backwards compatible with existing controllers

See [Migration Guide](docs/MIGRATION_GUIDE.md) for detailed migration instructions.

🔒 Security Features
-------------------

[](#-security-features)

- ✅ Password hashing with bcrypt
- ✅ JWT token authentication (API)
- ✅ Session-based authentication (Web)
- ✅ CSRF protection for web routes
- ✅ Rate limiting on auth endpoints (5 requests/minute)
- ✅ Rate limiting on all API endpoints (configurable)
- ✅ Input validation with FormRequest
- ✅ SQL injection protection (Eloquent ORM)
- ✅ XSS protection (Blade templating)
- ✅ Secure session handling
- ✅ Cookie encryption (AES-256-CBC) for sensitive data
- ✅ Centralized exception handling with proper error responses
- ✅ Modular architecture for better code organization
- ✅ Automatic dependency registration
- ✅ Custom Blade directives (@auth, @guest, @csrf, @method, @can, @role)

💾 Caching
---------

[](#-caching)

The application includes a powerful caching layer with multiple driver support:

### Features

[](#features)

- **Multiple Drivers**: File, Redis, and Null (for testing)
- **Simple API**: Laravel-like helper functions
- **Repository Integration**: Built-in trait for easy model caching
- **Tag-based Cache Clearing**: Flush cache by tags
- **PSR-16 Compatible**: Standard caching interface

### Configuration

[](#configuration)

Configure caching in your `.env` file:

```
# Cache Driver: file, redis, null
CACHE_DRIVER=redis
CACHE_PREFIX=slim_cache
CACHE_PATH=/var/www/html/storage/cache/data

# Redis Cache Database (separate from queue/session)
REDIS_CACHE_DATABASE=1
```

### Usage

[](#usage)

#### Helper Functions

[](#helper-functions)

```
// Store a value
cache_put('key', 'value', 3600); // TTL in seconds (null = forever)

// Retrieve a value
$value = cache('key');
$value = cache('key', 'default'); // With default

// Remember pattern (cache or compute)
$users = cache_remember('users', 300, function () {
    return User::all();
});

// Check existence
if (cache_has('key')) {
    // ...
}

// Delete a value
cache_forget('key');

// Clear all cache
cache_flush();

// Clear by tag
cache_flush('users');
cache_flush(['users', 'posts']);
```

#### Dependency Injection

[](#dependency-injection-1)

```
use App\Modules\Core\Infrastructure\Cache\CacheInterface;

class UserController extends Controller
{
    public function __construct(
        private readonly CacheInterface $cache
    ) {}

    public function index(): Response
    {
        $users = $this->cache->remember('users', 300, function () {
            return User::all();
        });

        return ApiResponse::success($users);
    }
}
```

#### Repository Caching

[](#repository-caching)

```
use App\Modules\Core\Infrastructure\Cache\RepositoryCacheExample;
use App\Modules\Core\Infrastructure\Repositories\EloquentRepository;

class UserRepository extends EloquentRepository
{
    use RepositoryCacheExample;

    protected string $cacheTag = 'users';
    protected int $repositoryCacheTtl = 600; // 10 minutes

    protected function model(): string
    {
        return User::class;
    }

    // Use cached methods
    public function findCached(int $id): ?User
    {
        return $this->findCached($id);
    }

    // Custom cached query
    public function findByEmailCached(string $email): ?User
    {
        return $this->remember("email:{$email}", function () use ($email) {
            return $this->findByEmail($email);
        });
    }
}
```

#### Cacheable Trait

[](#cacheable-trait)

```
use App\Modules\Core\Infrastructure\Cache\Cacheable;

class ProductService
{
    use Cacheable;

    protected string $cacheTag = 'products';
    protected int $cacheTtl = 3600;

    public function getFeaturedProducts()
    {
        return $this->remember('featured', function () {
            // Expensive query
            return Product::featured()->with('category')->get();
        });
    }

    public function clearProductCache()
    {
        $this->cacheFlush();
    }
}
```

### Cache Drivers

[](#cache-drivers)

#### File Driver

[](#file-driver)

Stores cache in filesystem. Good for single-server setups.

```
CACHE_DRIVER=file
CACHE_PATH=/var/www/html/storage/cache/data
```

#### Redis Driver

[](#redis-driver)

Recommended for production and multi-server setups.

```
CACHE_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_CACHE_DATABASE=1
```

#### Null Driver

[](#null-driver)

Disables caching. Useful for testing.

```
CACHE_DRIVER=null
```

### CLI Commands

[](#cli-commands)

```
# Clear application cache
php slim cache:clear

# Clear cache by tag
php slim cache:clear --tag=users
```

🍪 Cookies
---------

[](#-cookies)

The application includes a powerful Cookie Helper with encryption support:

### Features

[](#features-1)

- **Easy API**: Simple get/set methods with helper functions
- **Encryption**: AES-256-CBC encryption for sensitive data
- **Flexible**: Support for arrays, objects, and primitives
- **Secure**: Configurable secure, httpOnly, and SameSite options
- **Framework Agnostic**: Works with any PHP application

### Configuration

[](#configuration-1)

Configure cookies in your `.env` file:

```
# Cookie Settings
COOKIE_TTL=3600
COOKIE_PATH=/
COOKIE_DOMAIN=
COOKIE_SECURE=true
COOKIE_HTTP_ONLY=true
COOKIE_SAME_SITE=Lax
COOKIE_ENCRYPT=true
```

### Usage

[](#usage-1)

#### Helper Functions

[](#helper-functions-1)

```
// Set a cookie
cookie_set('user_id', 123, 3600);
cookie_set('preferences', ['theme' => 'dark'], 86400);

// Get a cookie
$userId = cookie_get('user_id');
$userId = cookie_get('user_id', 0); // With default

// Check if exists
if (cookie_has('user_id')) {
    // ...
}

// Delete a cookie
cookie_delete('user_id');

// Delete all cookies
cookie_flush();

// Forever cookie (10 years)
cookie_forever('remember_me', 'yes');

// Remember pattern (get or set)
$settings = cookie_remember('app_settings', 3600, function () {
    return Settings::getDefaults();
});
```

#### Using the Class Directly

[](#using-the-class-directly)

```
use App\Modules\Core\Infrastructure\Support\CookieHelper;

$cookie = CookieHelper::getInstance();

// Set with custom options
$cookie->set('session', $data, 3600, [
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Strict'
]);

// Get value
$value = $cookie->get('session');

// Make cookie for Slim Response
$cookieData = $cookie->make('name', 'value', 3600);
$response = $response->withHeader('Set-Cookie',
    'name=' . $cookieData['value'] . '; Path=' . $cookieData['path']
);
```

#### In Controllers

[](#in-controllers)

```
class UserController extends Controller
{
    public function login(Request $request, Response $response): Response
    {
        // Set user preference cookie
        cookie_set('last_login', date('Y-m-d H:i:s'), 86400 * 30);

        // Set encrypted session data
        cookie_set('user_prefs', [
            'theme' => 'dark',
            'lang' => 'en'
        ], 3600);

        return $response;
    }

    public function logout(Request $request, Response $response): Response
    {
        // Clear user cookies
        cookie_delete('user_prefs');
        cookie_delete('last_login');

        return $response;
    }
}
```

### Cookie Encryption

[](#cookie-encryption)

Cookies are automatically encrypted using AES-256-CBC when `COOKIE_ENCRYPT=true`:

```
// Encryption is transparent - works the same way
$helper = new CookieHelper(encryptionEnabled: true);
$helper->set('secret', 'sensitive data');

// Automatically decrypted on get
$data = $helper->get('secret'); // 'sensitive data'
```

### Security Best Practices

[](#security-best-practices)

1. **Always use encryption** for sensitive data
2. **Set httpOnly** to prevent XSS attacks
3. **Use secure flag** in production (HTTPS only)
4. **SameSite=Lax** or **Strict** for CSRF protection
5. **Reasonable TTL** - don't make cookies live forever

🔍 API Query Builder
-------------------

[](#-api-query-builder)

Powerful query parameter parsing for REST API filtering, sorting, and searching.

### Features

[](#features-2)

- **Filtering** - Filter by any field with operators (`eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `like`, `in`, etc.)
- **Sorting** - Multi-column sort with direction (`asc`/`desc`)
- **Searching** - Full-text search across multiple fields
- **Field Selection** - Select only needed fields (sparse fieldsets)
- **Relationships** - Eager load related data (`include`)
- **Ranges** - Filter by numeric ranges (price, dates, etc.)
- **Pagination** - Automatic pagination with configurable limits

### Usage

[](#usage-2)

#### Basic Filtering

[](#basic-filtering)

```
// URL: GET /api/users?filter[role]=admin&filter[active]=true
$users = User::filter($request)->paginate();
```

#### Sorting

[](#sorting)

```
// URL: GET /api/users?sort=-created_at,name
// Sort by created_at DESC, then name ASC
$users = User::filter($request)->paginate();
```

#### Searching

[](#searching)

```
// In User model
protected array $searchable = ['name', 'email'];

// URL: GET /api/users?search=john
// Searches in name and email fields
$users = User::filter($request)->paginate();
```

#### Field Selection

[](#field-selection)

```
// URL: GET /api/users?fields=id,name,email
// Returns only id, name, and email
$users = User::filter($request)->paginate();
```

#### Eager Loading

[](#eager-loading)

```
// URL: GET /api/users?include=posts,comments
$users = User::filter($request)->paginate();
```

#### Ranges

[](#ranges)

```
// URL: GET /api/products?range[price]=10,100
$products = Product::filter($request)->paginate();
```

#### Advanced Filters with Operators

[](#advanced-filters-with-operators)

```
// URL: GET /api/users?filter[age]=gt:18&filter[name]=like:john
// Operators: eq, ne, gt, gte, lt, lte, like, starts, ends, in, nin, null
```

### Using in Controllers

[](#using-in-controllers)

```
use App\Modules\Core\Infrastructure\Query\Filterable;

class UserController extends Controller
{
    public function index(Request $request): Response
    {
        // Using the Filterable trait
        $result = User::filterPaginate($request);

        return ApiResponse::success($result['items'], HttpStatusCode::OK, null, $result['pagination']);
    }
}
```

### Model Configuration

[](#model-configuration)

```
use App\Modules\Core\Infrastructure\Query\Filterable;

class User extends Model
{
    use Filterable;

    // Fields allowed for filtering
    protected array $filterable = ['name', 'email', 'role', 'active'];

    // Fields allowed for sorting
    protected array $sortable = ['id', 'name', 'created_at', 'updated_at'];

    // Fields allowed for searching
    protected array $searchable = ['name', 'email'];

    // Default sort order
    protected array $defaultSort = ['created_at' => 'desc'];
}
```

### Using QueryBuilder Directly

[](#using-querybuilder-directly)

```
use App\Modules\Core\Infrastructure\Query\QueryBuilder;

// Simple usage
$users = (new QueryBuilder($request))->paginate(User::class);

// With configuration
$builder = new QueryBuilder($request, [
    'filterable' => ['name', 'email'],
    'sortable' => ['id', 'name'],
    'searchable' => ['name', 'email'],
]);

$users = $builder->paginate(User::class);
```

### Helper Functions

[](#helper-functions-2)

```
// Parse query parameters
$parser = query_parser($request);
$filters = $parser->filters();
$sorts = $parser->sorts();
$search = $parser->search();

// Apply filters to query
$query = query_filter(User::class, $request);
$users = $query->paginate();

// Get paginated results directly
$result = query_paginate(User::class, $request);
// Returns: ['items' => [...], 'pagination' => [...]]
```

### URL Parameter Reference

[](#url-parameter-reference)

ParameterExampleDescription`filter[field]``filter[status]=active`Filter by field value`filter[field]=op:value``filter[age]=gt:18`Filter with operator`sort``sort=-created_at,name`Sort by fields`search``search=john`Full-text search`fields``fields=id,name,email`Select specific fields`include``include=posts,comments`Eager load relations`range[field]``range[price]=10,100`Filter by range`page``page=2`Page number`per_page``per_page=25`Items per page (max 100)### Filter Operators

[](#filter-operators)

OperatorExampleDescription`eq``filter[id]=eq:1`Equal (default)`ne``filter[status]=ne:draft`Not equal`gt``filter[age]=gt:18`Greater than`gte``filter[price]=gte:10`Greater than or equal`lt``filter[age]=lt:65`Less than`lte``filter[price]=lte:100`Less than or equal`like``filter[name]=like:john`Contains substring`starts``filter[name]=starts:John`Starts with`ends``filter[name]=ends:Doe`Ends with`in``filter[id]=in:1,2,3`In array`nin``filter[status]=nin:deleted`Not in array`null``filter[deleted_at]=null:true`Is null / not null📦 Dependencies
--------------

[](#-dependencies)

### Core

[](#core)

- `slim/slim` - Slim Framework 4
- `illuminate/database` - Eloquent ORM
- `illuminate/validation` - Validation
- `eftec/bladeone` - Lightweight Blade templating engine
- `php-di/slim-bridge` - Dependency injection

### Authentication &amp; Security

[](#authentication--security)

- `firebase/php-jwt` - JWT tokens
- `slim/csrf` - CSRF protection
- `tuupola/cors-middleware` - CORS support

### Utilities

[](#utilities)

- `monolog/monolog` - Logging
- `phpmailer/phpmailer` - Email sending
- `vlucas/phpdotenv` - Environment variables
- `illuminate/pagination` - Pagination support
- `illuminate/support` - Laravel support package
- `predis/predis` - Redis client (cache, queue, sessions)

### Development

[](#development)

- `phpunit/phpunit` - Testing
- `laravel/pint` - Code formatting
- `rector/rector` - Code refactoring

🚀 Deployment
------------

[](#-deployment)

### Storage Directory Setup

[](#storage-directory-setup)

The application requires write access to the `storage/` directory for logs, cache, and queue files.

#### Setup

[](#setup)

**For Nginx:**

```
# Set ownership
sudo chown -R www-data:www-data storage

# Set permissions
sudo chmod -R 775 storage
```

**For Apache:**

```
# Set ownership
sudo chown -R www-data:www-data storage

# Set permissions
sudo chmod -R 775 storage
```

**For Docker:**The storage directory is automatically mounted and permissions are handled by the container.

### Web Server Configuration

[](#web-server-configuration)

#### Nginx Configuration

[](#nginx-configuration)

The nginx configuration is located in `docker/nginx/app.conf`. For production, ensure:

1. **Document root** points to `/var/www/html/public`
2. **PHP-FPM** is configured correctly
3. **Storage directory** is protected (denied access in nginx config)
4. **Security headers** are set

Example production nginx configuration:

```
server {
    listen 80;
    server_name your-domain.com;
    root /var/www/html/public;

    # Deny access to storage and cache
    location ~ ^/(storage|cache)/ {
        deny all;
    }

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
```

#### Apache Configuration

[](#apache-configuration)

The `.htaccess` file in `public/` directory handles URL rewriting. Ensure:

1. **mod\_rewrite** is enabled:

    ```
    sudo a2enmod rewrite
    sudo systemctl restart apache2
    ```
2. **AllowOverride** is set to All in Apache config:

    ```

        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted

    ```
3. **Storage directory** is protected (already configured in `.htaccess`)

### Permissions Reference

[](#permissions-reference)

DirectoryPermissionsOwnerPurpose`storage/`775www-dataRoot storage directory`storage/logs/`775www-dataApplication logs`storage/cache/`775www-dataBlade view cache`storage/queue/`775www-dataQueue job files**Note:** Adjust user/group (`www-data`, `nginx`, `apache`) based on your server configuration.

### Security Considerations

[](#security-considerations)

1. **Storage directory** should never be accessible via web browser
2. **Environment files** (`.env`) should be protected
3. **Composer files** should not be accessible
4. **Git files** should not be accessible
5. **File uploads** (if implemented) should be stored outside `public/` directory

🤝 Contributing
--------------

[](#-contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License
---------

[](#-license)

This project is licensed under the MIT License.

🙏 Acknowledgments
-----------------

[](#-acknowledgments)

- [Slim Framework](https://www.slimframework.com/)
- [Laravel](https://laravel.com/) for Eloquent, Blade, and Validation
- All the amazing open-source contributors

---

**Made with ❤️ for the PHP community**

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance91

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 61% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~12 days

Recently: every ~1 days

Total

12

Last Release

46d ago

Major Versions

v1.0.10 → v2.0.02026-03-23

### Community

Maintainers

![](https://www.gravatar.com/avatar/472c4da0220f15747dd81d3a27ffbba022a06ab20f64a367ddcaacd790d812d7?d=identicon)[KalimeroMK](/maintainers/KalimeroMK)

---

Top Contributors

[![KalimeroMK](https://avatars.githubusercontent.com/u/24772657?v=4)](https://github.com/KalimeroMK "KalimeroMK (75 commits)")[![zbogoevski](https://avatars.githubusercontent.com/u/220718845?v=4)](https://github.com/zbogoevski "zbogoevski (48 commits)")

---

Tags

csrfdockereloquent-ormphp8sessionslim-frameworkslim4phpframeworkslimeloquentmigrationsmvcstarterviewskitslim4

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/kalimeromk-slim-mvc-starter/health.svg)

```
[![Health](https://phpackages.com/badges/kalimeromk-slim-mvc-starter/health.svg)](https://phpackages.com/packages/kalimeromk-slim-mvc-starter)
```

###  Alternatives

[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
