EasyТеория9 min

Структура директорий

Архитектура приложения Laravel 11, ключевые директории app/, routes/, resources/, database/, config/

Структура директорий Laravel

Общий обзор

Laravel 11 представил «тонкий» скелет приложения (slim skeleton), существенно упростив начальную структуру проекта. Многие файлы и директории создаются только по необходимости.

Корневая структура проекта

my-app/
├── app/                    # Application code (Models, Controllers, etc.)
├── bootstrap/              # Framework bootstrap and cache files
│   ├── app.php             # Application instance creation
│   ├── cache/              # Cached config, routes, services
│   └── providers.php       # Service providers registration
├── config/                 # Configuration files
├── database/               # Migrations, factories, seeders
│   ├── factories/          # Model factories for testing
│   ├── migrations/         # Database migration files
│   └── seeders/            # Database seed classes
├── public/                 # Web server document root
│   ├── index.php           # Application entry point
│   ├── .htaccess           # Apache rewrite rules
│   └── favicon.ico
├── resources/              # Views, raw assets, language files
│   ├── css/                # CSS source files
│   ├── js/                 # JavaScript source files
│   └── views/              # Blade templates
├── routes/                 # Route definitions
│   ├── web.php             # Web routes (session, CSRF)
│   └── console.php         # Console commands (closures)
├── storage/                # Compiled views, logs, file uploads
│   ├── app/                # Application files
│   │   └── public/         # Public files (symlinked)
│   ├── framework/          # Framework-generated files
│   │   ├── cache/          # File-based cache
│   │   ├── sessions/       # File-based sessions
│   │   └── views/          # Compiled Blade views
│   └── logs/               # Application logs
├── tests/                  # Automated tests
│   ├── Feature/            # Feature (integration) tests
│   └── Unit/               # Unit tests
├── vendor/                 # Composer dependencies (not in Git)
├── .env                    # Environment variables (not in Git)
├── .env.example            # Environment template
├── artisan                 # CLI entry point
├── composer.json           # PHP dependencies
├── package.json            # Node.js dependencies
├── phpunit.xml             # PHPUnit configuration
└── vite.config.js          # Vite asset bundler config

Ключевое изменение Laravel 11: Из скелета удалены файлы app/Http/Kernel.php, app/Console/Kernel.php, app/Exceptions/Handler.php и большинство сервис-провайдеров. Их функциональность перенесена в bootstrap/app.php.

Директория app/

Директория app/ содержит основной код приложения. Использует пространство имён App\ с автозагрузкой PSR-4.

Структура app/ в Laravel 11

app/
├── Console/                # (Created on demand)
│   └── Commands/           # Custom Artisan commands
├── Exceptions/             # (Created on demand)
├── Http/
│   ├── Controllers/        # Request handlers
│   │   └── Controller.php  # Base controller (slim)
│   ├── Middleware/          # (Created on demand)
│   └── Requests/           # (Created on demand)
├── Models/                 # Eloquent models
│   └── User.php            # Default User model
└── Providers/
    └── AppServiceProvider.php  # Main service provider

Для экзамена: В Laravel 11 по умолчанию только ОДИН сервис-провайдер -- AppServiceProvider. Ранее было 5: AppServiceProvider, AuthServiceProvider, BroadcastServiceProvider, EventServiceProvider, RouteServiceProvider.

Дополнительные директории app/ (создаются по необходимости)

# Created automatically by artisan make: commands
app/
├── Casts/                  # php artisan make:cast
├── Console/Commands/       # php artisan make:command
├── Events/                 # php artisan make:event
├── Exceptions/             # php artisan make:exception
├── Http/Middleware/         # php artisan make:middleware
├── Http/Requests/          # php artisan make:request
├── Http/Resources/         # php artisan make:resource
├── Jobs/                   # php artisan make:job
├── Listeners/              # php artisan make:listener
├── Mail/                   # php artisan make:mail
├── Notifications/          # php artisan make:notification
├── Observers/              # php artisan make:observer
├── Policies/               # php artisan make:policy
├── Rules/                  # php artisan make:rule
├── Services/               # Created manually (no artisan command)
├── Actions/                # Created manually (single-action classes)
├── DTOs/                   # Created manually (Data Transfer Objects)
├── Enums/                  # Created manually (PHP 8.1+ enums)
└── ValueObjects/           # Created manually
<?php
declare(strict_types=1);

// Naming convention: singular for most directories
// app/Models/User.php → App\Models\User
// app/Http/Controllers/UserController.php → App\Http\Controllers\UserController
// app/Services/PaymentService.php → App\Services\PaymentService

// PSR-4 autoloading maps namespace to directory:
// "App\\" → "app/"
// App\Models\User → app/Models/User.php
// App\Http\Controllers\Api\V1\UserController → app/Http/Controllers/Api/V1/UserController.php

Директория bootstrap/

bootstrap/
├── app.php              # Application instance and configuration
├── cache/               # Framework cache files
│   ├── config.php       # Cached configuration (after config:cache)
│   ├── events.php       # Cached event-listener mapping
│   ├── packages.php     # Auto-discovered package service providers
│   ├── routes-v7.php    # Cached routes (after route:cache)
│   └── services.php     # Compiled service container
└── providers.php        # Service providers list

bootstrap/app.php в Laravel 11

<?php
declare(strict_types=1);

// bootstrap/app.php — the new central configuration point
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__ . '/../routes/web.php',
        api: __DIR__ . '/../routes/api.php',
        commands: __DIR__ . '/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        // Configure global middleware
        $middleware->web(append: [
            \App\Http\Middleware\HandleInertiaRequests::class,
        ]);

        // API middleware
        $middleware->api(prepend: [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        ]);

        // Middleware aliases
        $middleware->alias([
            'role' => \App\Http\Middleware\CheckRole::class,
            'admin' => \App\Http\Middleware\EnsureIsAdmin::class,
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        // Configure exception handling
        $exceptions->renderable(function (\Throwable $e) {
            // Custom exception rendering
        });
    })
    ->create();

Важно для Senior: В Laravel 11 файл bootstrap/app.php заменяет Http/Kernel.php, Console/Kernel.php и Exceptions/Handler.php. Это единая точка конфигурации маршрутов, middleware и обработки исключений.

bootstrap/providers.php

<?php
declare(strict_types=1);

// bootstrap/providers.php — list of service providers
return [
    App\Providers\AppServiceProvider::class,
    // Add custom providers here
    // App\Providers\EventServiceProvider::class,
    // App\Providers\AuthServiceProvider::class,
];

Директория config/

<?php
declare(strict_types=1);

// config/app.php — main application config
// config/auth.php — authentication guards and providers
// config/cache.php — cache store drivers
// config/database.php — database connections
// config/filesystems.php — filesystem disks
// config/logging.php — log channels
// config/mail.php — mail drivers
// config/queue.php — queue connections
// config/services.php — third-party services
// config/session.php — session configuration

// Custom config files are automatically loaded
// config/payment.php → config('payment.key')
// config/social.php → config('social.facebook.app_id')

// Laravel 11: Many config files removed from skeleton
// Publish with: php artisan config:publish <name>

Директория database/

database/
├── factories/
│   └── UserFactory.php      # Model factory for User
├── migrations/
│   ├── 0001_01_01_000000_create_users_table.php
│   ├── 0001_01_01_000001_create_cache_table.php
│   └── 0001_01_01_000002_create_jobs_table.php
└── seeders/
    └── DatabaseSeeder.php   # Main seeder
<?php
declare(strict_types=1);

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

/**
 * @extends Factory<User>
 */
final class UserFactory extends Factory
{
    // Factory automatically maps to model by convention:
    // UserFactory → App\Models\User
    // OrderFactory → App\Models\Order

    public function definition(): array
    {
        return [
            'name' => fake()->name(),
            'email' => fake()->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => Hash::make('password'),
            'remember_token' => Str::random(10),
        ];
    }

    public function unverified(): static
    {
        return $this->state(fn (array $attributes) => [
            'email_verified_at' => null,
        ]);
    }
}
<?php
declare(strict_types=1);

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;

final class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        // Create a test user
        User::factory()->create([
            'name' => 'Test User',
            'email' => '[email protected]',
        ]);

        // Create multiple users
        User::factory(50)->create();

        // Call other seeders
        $this->call([
            // CategorySeeder::class,
            // ProductSeeder::class,
        ]);
    }
}

Директория public/

public/
├── index.php           # Application entry point
├── .htaccess           # Apache URL rewriting
├── favicon.ico
├── robots.txt
└── build/              # Compiled assets (Vite output, gitignored)
<?php
declare(strict_types=1);

// public/index.php — the entry point for ALL HTTP requests
// This is a simplified view of what happens:

// 1. Define start time for performance measurement
define('LARAVEL_START', microtime(true));

// 2. Maintenance mode check
if (file_exists($maintenance = __DIR__ . '/../storage/framework/maintenance.php')) {
    require $maintenance;
}

// 3. Register Composer autoloader
require __DIR__ . '/../vendor/autoload.php';

// 4. Bootstrap the application and handle the request
/** @var \Illuminate\Foundation\Application $app */
$app = require_once __DIR__ . '/../bootstrap/app.php';

// 5. Handle incoming request and send response
$app->handleRequest(
    \Illuminate\Http\Request::capture()
);

Для экзамена: Файл public/index.php -- это единственная точка входа для всех HTTP-запросов (front controller pattern). Веб-сервер (Nginx/Apache) должен указывать document root на директорию public/, а не на корень проекта. Это защищает конфигурационные файлы и исходный код от прямого доступа.

Директория resources/

resources/
├── css/
│   └── app.css          # Main CSS file (Tailwind, etc.)
├── js/
│   ├── app.js           # Main JavaScript entry
│   └── bootstrap.js     # Axios, Echo setup
└── views/
    ├── welcome.blade.php   # Default welcome page
    └── layouts/            # Layout templates (created manually)
<?php
declare(strict_types=1);

// Views are organized by convention:
// resources/views/users/index.blade.php → view('users.index')
// resources/views/admin/users/edit.blade.php → view('admin.users.edit')
// resources/views/components/alert.blade.php → <x-alert />

// Language files (if using JSON translation)
// resources/lang/en.json
// resources/lang/ru.json

// Language files (if using PHP translation)
// resources/lang/en/messages.php
// resources/lang/ru/messages.php

// In Laravel 11, lang directory is NOT created by default
// Publish with: php artisan lang:publish

Директория routes/

Laravel 11: Упрощённая маршрутизация

routes/
├── web.php             # Web routes (session, CSRF, cookies)
├── console.php         # Artisan command definitions
└── api.php             # API routes (created on demand)

Важно: В Laravel 11 файл routes/api.php НЕ создаётся по умолчанию. Для его создания выполните php artisan install:api, что также установит Laravel Sanctum.

<?php
declare(strict_types=1);

// routes/web.php — routes with web middleware group
// Includes: session, CSRF protection, cookie encryption
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

// routes/console.php — closure-based artisan commands
use Illuminate\Support\Facades\Schedule;

Schedule::command('inspire')->hourly();

// routes/api.php — routes with api middleware group
// Created after: php artisan install:api
// Includes: Sanctum, rate limiting, stateless

// routes/channels.php — broadcast channel authorization
// Created after: php artisan install:broadcasting
<?php
declare(strict_types=1);

// Laravel 11: Route files are loaded in bootstrap/app.php
// No more RouteServiceProvider

// bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__ . '/../routes/web.php',
        api: __DIR__ . '/../routes/api.php',
        commands: __DIR__ . '/../routes/console.php',
        health: '/up', // Health check endpoint
        // Custom route loading
        then: function () {
            Route::middleware('web')
                ->prefix('admin')
                ->group(base_path('routes/admin.php'));
        },
    )
    ->create();

Директория storage/

storage/
├── app/                    # Application files
│   ├── public/             # Publicly accessible files (symlinked)
│   └── private/            # Private files
├── framework/              # Framework-generated files
│   ├── cache/              # File cache (if file driver)
│   │   └── data/
│   ├── sessions/           # File sessions (if file driver)
│   ├── testing/            # Test files
│   └── views/              # Compiled Blade templates
└── logs/                   # Application log files
    └── laravel.log         # Default log file
# Create symbolic link: public/storage → storage/app/public
php artisan storage:link

# This allows public access to files in storage/app/public
# URL: /storage/filename.jpg → storage/app/public/filename.jpg
<?php
declare(strict_types=1);

use Illuminate\Support\Facades\Storage;

// Using Storage facade
Storage::disk('local')->put('file.txt', 'Content');     // storage/app/file.txt
Storage::disk('public')->put('photo.jpg', $imageData);  // storage/app/public/photo.jpg
Storage::disk('s3')->put('backup.zip', $data);           // AWS S3

// Path helpers
$path = storage_path();                    // /path/to/storage
$path = storage_path('app/file.txt');      // /path/to/storage/app/file.txt
$path = storage_path('logs/laravel.log');  // /path/to/storage/logs/laravel.log

Для Senior: Директория storage/ должна быть записываемой веб-сервером. Права доступа: chmod -R 775 storage. В Docker-контейнерах убедитесь, что пользователь контейнера имеет права на запись. Логи ротации настраиваются в config/logging.php.

Директория tests/

tests/
├── Feature/                # Integration/Feature tests
│   └── ExampleTest.php
├── Unit/                   # Unit tests
│   └── ExampleTest.php
├── Pest.php                # Pest configuration (if using Pest)
└── TestCase.php            # Base test case
<?php
declare(strict_types=1);

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    // Base test case — all tests extend this
    // Provides: RefreshDatabase, WithFaker, etc.
}

Вспомогательные функции путей

<?php
declare(strict_types=1);

// Path helper functions
$path = app_path();                      // /project/app
$path = app_path('Models/User.php');     // /project/app/Models/User.php

$path = base_path();                     // /project
$path = base_path('vendor/autoload.php');// /project/vendor/autoload.php

$path = config_path();                   // /project/config
$path = config_path('app.php');          // /project/config/app.php

$path = database_path();                 // /project/database
$path = database_path('migrations');     // /project/database/migrations

$path = public_path();                   // /project/public
$path = public_path('css/app.css');      // /project/public/css/app.css

$path = resource_path();                 // /project/resources
$path = resource_path('views');          // /project/resources/views

$path = storage_path();                  // /project/storage
$path = storage_path('logs');            // /project/storage/logs

$path = lang_path();                     // /project/lang
$path = lang_path('en/messages.php');    // /project/lang/en/messages.php

Различия Laravel 10 vs Laravel 11

Аспект Laravel 10 Laravel 11
Http Kernel app/Http/Kernel.php bootstrap/app.php
Console Kernel app/Console/Kernel.php bootstrap/app.php
Exception Handler app/Exceptions/Handler.php bootstrap/app.php
Service Providers 5 по умолчанию 1 (AppServiceProvider)
Middleware 9 файлов в app/Http/Middleware/ 0 файлов (по требованию)
routes/api.php Существует по умолчанию php artisan install:api
routes/channels.php Существует по умолчанию php artisan install:broadcasting
Config файлы ~15 файлов ~10 файлов
Минимум PHP 8.1 8.2

Проверь себя

Сколько сервис-провайдеров создаётся по умолчанию в новом проекте Laravel 11?

Какая команда создаёт файл `routes/api.php` и устанавливает Laravel Sanctum в Laravel 11?

Какой хелпер возвращает путь к директории `storage/`?

Куда должен указывать document root веб-сервера (Nginx/Apache) для Laravel-проекта?

В Laravel 11, где настраиваются глобальные middleware, обработка исключений и маршрутизация?