ApnaPHP

Documentation

Project Structure

Understanding the ApnaPHP project structure will help you organize your application effectively. The boilerplate comes with everything pre-configured!

Directory Structure

my-app/
├── app/                          # Application files (Next.js App Router style)
│   └── page.apna.php            # Your main page (like Next.js pages)
├── config/                       # Configuration files (pre-configured)
│   ├── app.php                  # App configuration
│   └── database.php             # Multi-database configuration
├── models/                       # Your models directory
│   └── User.php                 # Sample User model with auto-migration
├── public/                       # Public assets and entry point
│   ├── index.php                # Main entry point (handles all requests)
│   ├── apnaphp.png              # Framework logo
│   ├── file.svg                 # Sample icons
│   ├── globe.svg
│   └── window.svg
├── storage/                      # Application storage (organized)
│   ├── cache/                   # Cache files
│   │   └── views/
│   ├── database/                # SQLite database files
│   ├── logs/                    # Log files
│   │   └── console.log
│   └── uploads/                 # User uploaded files
├── vendor/                       # Composer dependencies (framework auto-installed)
├── .env.example                 # Environment variables template
├── apna                         # CLI executable
├── composer.json                # Dependencies (everything included)
├── LICENSE                      # MIT License
└── README.md                    # Project documentation

File Types

Pages (page.apna.php)

Regular pages that render HTML content:

<?php
// app/page.apna.php
metadata([
    'title' => 'Welcome to ApnaPHP',
    'description' => 'Your first ApnaPHP page'
]);
?>

<h1>Hello, ApnaPHP!</h1>
<p>Welcome to your first ApnaPHP application.</p>

API Routes (route.apna.php)

API endpoints that return JSON responses:

<?php
// app/api/users/route.apna.php

use ApnaPHP\Routing\Request;
use ApnaPHP\Routing\Response;

class UsersHandler
{
    public function GET(Request $request)
    {
        $users = User::all();
        return Response::json(['users' => $users]);
    }
    
    public function POST(Request $request)
    {
        $user = User::create($request->all());
        return Response::json($user, 201);
    }
}

Models (models/User.php)

Eloquent-inspired models with auto-migration:

<?php

namespace App\Models;

use ApnaPHP\Database\Model;

class User extends Model
{
    protected string $table = 'users';
    protected bool $autoMigrate = true; // ✅ Auto-creates table on first use

    protected array $schema = [
        'name' => 'required|type:string|length:255',
        'email' => 'required|unique|type:string|length:255',
        'phone' => 'required|unique|type:string|length:20',
        'password' => 'required|type:string',
        'role' => 'type:string|default:user|length:50',
        'status' => 'type:string|default:active|length:50',
    ];

    protected array $fillable = [
        'name', 'email', 'password', 'phone', 'role', 'status'
    ];

    protected array $hidden = ['password'];
}

File Types

Pages (page.apna.php)

Regular pages that render HTML content:

<?php
// app/page.apna.php - Home page (/)
metadata([
    'title' => 'Welcome',
    'description' => 'Welcome to our site'
]);
?>

<h1>Welcome to ApnaPHP</h1>
<p>This is the home page.</p>

API Routes (route.apna.php)

API endpoints that return JSON or other data:

<?php
// app/api/users/route.apna.php - /api/users endpoint

class UsersAPI {
    public function GET() {
        return json([
            'users' => [
                ['id' => 1, 'name' => 'John Doe'],
                ['id' => 2, 'name' => 'Jane Smith']
            ]
        ]);
    }
    
    public function POST() {
        $data = request()->json();
        
        // Create user logic here
        
        return json(['message' => 'User created successfully'], 201);
    }
}

Layouts (layout.apna.php)

Layout files that wrap pages:

<?php
// app/layout.apna.php - Root layout
metadata([
    'title' => 'My App',
    'description' => 'My ApnaPHP Application'
]);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= metadata('title') ?></title>
    <meta name="description" content="<?= metadata('description') ?>">
</head>
<body>
    <header>
        <nav>
            <a href="/">Home</a>
            <a href="/about">About</a>
        </nav>
    </header>
    
    <main>
        <?= $content ?? '' ?>
    </main>
    
    <footer>
        <p>&copy; 2024 My App</p>
    </footer>
</body>
</html>

Middleware (middleware.apna.php)

Middleware files that run before page rendering:

<?php
// app/middleware.apna.php - Global middleware

// Check authentication
if (!auth()->check() && request()->path() !== '/login') {
    return redirect('/login');
}

// Add security headers
response()->headers([
    'X-Frame-Options' => 'DENY',
    'X-XSS-Protection' => '1; mode=block'
]);

Error Pages

404 Page (not-found.apna.php)

<?php
// app/not-found.apna.php
metadata([
    'title' => 'Page Not Found'
]);
?>
<h1>404 - Page Not Found</h1>
<p>The page you're looking for doesn't exist.</p>
<a href="/">Go Home</a>

500 Page (500.apna.php)

<?php
// app/500.apna.php
metadata([
    'title' => 'Server Error'
]);
?>
<h1>500 - Server Error</h1>
<p>Something went wrong on our end.</p>

Dynamic Routes

Single Parameter

<?php
// app/blog/[slug]/page.apna.php
$slug = request()->param('slug');
$post = Post::where('slug', $slug)->first();

if (!$post) {
    return notFound();
}

metadata([
    'title' => $post->title,
    'description' => $post->excerpt
]);
?>

<h1><?= htmlspecialchars($post->title) ?></h1>
<div><?= $post->content ?></div>

Multiple Parameters

<?php
// app/blog/[year]/[month]/[slug]/page.apna.php
$year = request()->param('year');
$month = request()->param('month');
$slug = request()->param('slug');

$post = Post::where('year', $year)
    ->where('month', $month)
    ->where('slug', $slug)
    ->first();
?>

Catch-All Routes

<?php
// app/docs/[...slug]/page.apna.php
$segments = request()->params();
$docPath = implode('/', $segments);

// Load documentation page
$content = loadDocContent($docPath);
?>

Route Groups

Route groups allow you to organize related routes without affecting the URL:

app/
├── (admin)/
│   ├── dashboard/
│   │   └── page.apna.php        # /dashboard (not /admin/dashboard)
│   └── users/
│       └── page.apna.php        # /users (not /admin/users)
└── (public)/
    ├── about/
    │   └── page.apna.php        # /about
    └── contact/
        └── page.apna.php        # /contact

Configuration Files

Application Config (config/app.php)

<?php
return [
    'name' => env('APP_NAME', 'ApnaPHP Application'),
    'url' => env('APP_URL', 'http://localhost:3000'),
    'env' => env('APP_ENV', 'production'),
    'debug' => env('APP_DEBUG', false),
    'timezone' => 'UTC',
];

Database Config (config/database.php)

<?php
return [
    'default' => env('DB_DRIVER', 'mysql'),
    'connections' => [
        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', 'localhost'),
            // ... other database settings
        ],
    ],
];

Storage Directories

Logs (storage/logs/)

Application logs are stored here:

storage/logs/
├── apnaphp.log                  # Main application log
├── error.log                    # Error log
└── access.log                   # Access log

Cache (storage/cache/)

Temporary cache files:

storage/cache/
├── views/                       # Compiled views
├── routes/                      # Route cache
└── config/                      # Config cache

Uploads (storage/uploads/)

User uploaded files:

storage/uploads/
├── images/                      # Image uploads
├── documents/                   # Document uploads
└── avatars/                     # User avatars

Best Practices

File Organization

  1. Keep related files together - Group pages, layouts, and middleware by feature
  2. Use descriptive names - Make file names clear and meaningful
  3. Follow conventions - Use the .apna.php extension consistently
  4. Separate concerns - Keep business logic in separate classes when possible

Directory Structure Tips

  1. Flat structure for simple apps - Don't over-nest directories
  2. Group by feature - Organize by business logic, not technical concerns
  3. Consistent naming - Use kebab-case for directories, camelCase for files
  4. Public assets - Keep static files in the public/ directory

Environment Management

  1. Use .env files - Store environment-specific configuration
  2. Never commit secrets - Add .env to .gitignore
  3. Provide examples - Include .env.example for other developers
  4. Validate configuration - Check required environment variables on startup