939 lines
23 KiB
Markdown
939 lines
23 KiB
Markdown
# Руководство по установке и настройке Laravel Sanctum с API авторизацией
|
||
|
||
## Описание
|
||
|
||
Данное руководство описывает процесс установки и настройки **Laravel Sanctum** для API аутентификации с использованием **wadakatu/laravel-spectrum** для генерации Swagger документации.
|
||
|
||
---
|
||
|
||
## Содержание
|
||
|
||
1. [Установка пакетов](#1-установка-пакетов)
|
||
2. [Настройка Sanctum](#2-настройка-sanctum)
|
||
3. [Структура API](#3-структура-api)
|
||
4. [API Endpoints](#4-api-endpoints)
|
||
5. [Использование API](#5-использование-api)
|
||
6. [Swagger документация](#6-swagger-документация)
|
||
7. [Команды Artisan](#7-команды-artisan)
|
||
|
||
---
|
||
|
||
## 1. Установка пакетов
|
||
|
||
### 1.1 Установка Laravel Sanctum
|
||
|
||
```bash
|
||
composer require laravel/sanctum
|
||
```
|
||
|
||
### 1.2 Установка wadakatu/laravel-spectrum
|
||
|
||
```bash
|
||
composer require wadakatu/laravel-spectrum
|
||
```
|
||
|
||
### 1.3 Публикация конфигураций
|
||
|
||
```bash
|
||
# Публикация Sanctum
|
||
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
|
||
|
||
# Публикация Spectrum
|
||
php artisan vendor:publish --provider="Wadakatu\LaravelSpectrum\LaravelSpectrumServiceProvider"
|
||
```
|
||
|
||
### 1.4 Запуск миграций
|
||
|
||
```bash
|
||
php artisan migrate
|
||
```
|
||
|
||
> **Примечание:** Если таблица `personal_access_tokens` уже существует, пропустите этот шаг.
|
||
|
||
---
|
||
|
||
## 2. Настройка Sanctum
|
||
|
||
### 2.1 Обновление модели User
|
||
|
||
Добавьте трейт `HasApiTokens` в модель `User`:
|
||
|
||
```php
|
||
// app/Models/User.php
|
||
|
||
namespace App\Models;
|
||
|
||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||
use Illuminate\Notifications\Notifiable;
|
||
use Laravel\Sanctum\HasApiTokens;
|
||
|
||
class User extends Authenticatable
|
||
{
|
||
use HasApiTokens, HasFactory, Notifiable;
|
||
|
||
// ...
|
||
}
|
||
```
|
||
|
||
### 2.2 Настройка middleware
|
||
|
||
Обновите файл `bootstrap/app.php`:
|
||
|
||
```php
|
||
// 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',
|
||
)
|
||
->withMiddleware(function (Middleware $middleware): void {
|
||
$middleware->statefulApi();
|
||
})
|
||
->withExceptions(function (Exceptions $exceptions): void {
|
||
//
|
||
})->create();
|
||
```
|
||
|
||
### 2.3 Конфигурация Sanctum
|
||
|
||
Конфигурация находится в файле `config/sanctum.php`. Основные настройки:
|
||
|
||
```php
|
||
// config/sanctum.php
|
||
|
||
return [
|
||
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
|
||
'%s%s',
|
||
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
|
||
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
|
||
))),
|
||
|
||
'guard' => ['web'],
|
||
|
||
'expiration' => null,
|
||
|
||
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
|
||
|
||
'middleware' => [
|
||
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
|
||
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
|
||
],
|
||
];
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Структура API
|
||
|
||
### 3.1 Директории
|
||
|
||
```
|
||
app/
|
||
├── Http/
|
||
│ ├── Controllers/
|
||
│ │ └── Api/
|
||
│ │ ├── AuthController.php
|
||
│ │ └── PostController.php
|
||
│ ├── Requests/
|
||
│ │ ├── LoginRequest.php
|
||
│ │ ├── RegisterRequest.php
|
||
│ │ ├── StorePostRequest.php
|
||
│ │ └── UpdatePostRequest.php
|
||
│ └── Resources/
|
||
│ ├── PostCollection.php
|
||
│ ├── PostResource.php
|
||
│ └── UserResource.php
|
||
└── Policies/
|
||
└── PostPolicy.php
|
||
```
|
||
|
||
### 3.2 API Resources
|
||
|
||
**UserResource** - форматирование данных пользователя:
|
||
|
||
```php
|
||
// app/Http/Resources/UserResource.php
|
||
|
||
namespace App\Http\Resources;
|
||
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Http\Resources\Json\JsonResource;
|
||
|
||
class UserResource extends JsonResource
|
||
{
|
||
public function toArray(Request $request): array
|
||
{
|
||
return [
|
||
'id' => $this->id,
|
||
'name' => $this->name,
|
||
'email' => $this->email,
|
||
'role' => $this->role,
|
||
'created_at' => $this->created_at,
|
||
];
|
||
}
|
||
}
|
||
```
|
||
|
||
**PostResource** - форматирование данных поста:
|
||
|
||
```php
|
||
// app/Http/Resources/PostResource.php
|
||
|
||
namespace App\Http\Resources;
|
||
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Http\Resources\Json\JsonResource;
|
||
|
||
class PostResource extends JsonResource
|
||
{
|
||
public function toArray(Request $request): array
|
||
{
|
||
return [
|
||
'id' => $this->id,
|
||
'title' => $this->title,
|
||
'content' => $this->content,
|
||
'user_id' => $this->user_id,
|
||
'user' => new UserResource($this->whenLoaded('user')),
|
||
'created_at' => $this->created_at,
|
||
'updated_at' => $this->updated_at,
|
||
];
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.3 Form Requests
|
||
|
||
**RegisterRequest** - валидация регистрации:
|
||
|
||
```php
|
||
// app/Http/Requests/RegisterRequest.php
|
||
|
||
namespace App\Http\Requests;
|
||
|
||
use Illuminate\Foundation\Http\FormRequest;
|
||
|
||
class RegisterRequest extends FormRequest
|
||
{
|
||
public function authorize(): bool
|
||
{
|
||
return true;
|
||
}
|
||
|
||
public function rules(): array
|
||
{
|
||
return [
|
||
'name' => ['required', 'string', 'max:255'],
|
||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||
'password' => ['required', 'string', 'min:8', 'confirmed'],
|
||
];
|
||
}
|
||
}
|
||
```
|
||
|
||
**LoginRequest** - валидация входа:
|
||
|
||
```php
|
||
// app/Http/Requests/LoginRequest.php
|
||
|
||
namespace App\Http\Requests;
|
||
|
||
use Illuminate\Foundation\Http\FormRequest;
|
||
|
||
class LoginRequest extends FormRequest
|
||
{
|
||
public function authorize(): bool
|
||
{
|
||
return true;
|
||
}
|
||
|
||
public function rules(): array
|
||
{
|
||
return [
|
||
'email' => ['required', 'string', 'email'],
|
||
'password' => ['required', 'string'],
|
||
];
|
||
}
|
||
}
|
||
```
|
||
|
||
**StorePostRequest** - валидация создания поста:
|
||
|
||
```php
|
||
// app/Http/Requests/StorePostRequest.php
|
||
|
||
namespace App\Http\Requests;
|
||
|
||
use Illuminate\Foundation\Http\FormRequest;
|
||
|
||
class StorePostRequest extends FormRequest
|
||
{
|
||
public function authorize(): bool
|
||
{
|
||
return true;
|
||
}
|
||
|
||
public function rules(): array
|
||
{
|
||
return [
|
||
'title' => ['required', 'string', 'max:255'],
|
||
'content' => ['required', 'string'],
|
||
];
|
||
}
|
||
}
|
||
```
|
||
|
||
**UpdatePostRequest** - валидация обновления поста:
|
||
|
||
```php
|
||
// app/Http/Requests/UpdatePostRequest.php
|
||
|
||
namespace App\Http\Requests;
|
||
|
||
use Illuminate\Foundation\Http\FormRequest;
|
||
|
||
class UpdatePostRequest extends FormRequest
|
||
{
|
||
public function authorize(): bool
|
||
{
|
||
return true;
|
||
}
|
||
|
||
public function rules(): array
|
||
{
|
||
return [
|
||
'title' => ['sometimes', 'string', 'max:255'],
|
||
'content' => ['sometimes', 'string'],
|
||
];
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. API Endpoints
|
||
|
||
### 4.1 Маршруты
|
||
|
||
```php
|
||
// routes/api.php
|
||
|
||
use App\Http\Controllers\Api\AuthController;
|
||
use App\Http\Controllers\Api\PostController;
|
||
use Illuminate\Support\Facades\Route;
|
||
|
||
// Swagger Documentation
|
||
Route::get('/docs', function () {
|
||
return redirect()->to('/docs/index.html');
|
||
});
|
||
|
||
// Public routes
|
||
Route::post('/register', [AuthController::class, 'register'])->name('api.register');
|
||
Route::post('/login', [AuthController::class, 'login'])->name('api.login');
|
||
|
||
// Protected routes
|
||
Route::middleware('auth:sanctum')->group(function () {
|
||
// Auth
|
||
Route::post('/logout', [AuthController::class, 'logout'])->name('api.logout');
|
||
Route::get('/user', [AuthController::class, 'user'])->name('api.user');
|
||
|
||
// Posts
|
||
Route::get('/posts', [PostController::class, 'index'])->name('api.posts.index');
|
||
Route::post('/posts', [PostController::class, 'store'])->name('api.posts.store');
|
||
Route::get('/posts/{post}', [PostController::class, 'show'])->name('api.posts.show');
|
||
Route::put('/posts/{post}', [PostController::class, 'update'])->name('api.posts.update');
|
||
Route::delete('/posts/{post}', [PostController::class, 'destroy'])->name('api.posts.destroy');
|
||
});
|
||
```
|
||
|
||
### 4.2 Список Endpoints
|
||
|
||
| Метод | Endpoint | Описание | Авторизация |
|
||
|-------|----------|----------|-------------|
|
||
| POST | `/api/register` | Регистрация | Нет |
|
||
| POST | `/api/login` | Вход | Нет |
|
||
| POST | `/api/logout` | Выход | Да |
|
||
| GET | `/api/user` | Текущий пользователь | Да |
|
||
| GET | `/api/posts` | Список постов | Да |
|
||
| POST | `/api/posts` | Создание поста | Да |
|
||
| GET | `/api/posts/{id}` | Просмотр поста | Да |
|
||
| PUT | `/api/posts/{id}` | Обновление поста | Да |
|
||
| DELETE | `/api/posts/{id}` | Удаление поста | Да |
|
||
| GET | `/api/docs` | Swagger UI | Нет |
|
||
|
||
---
|
||
|
||
## 5. Использование API
|
||
|
||
### 5.1 Регистрация
|
||
|
||
**Запрос:**
|
||
|
||
```bash
|
||
curl -X POST http://la.test/api/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"name": "John Doe",
|
||
"email": "john@example.com",
|
||
"password": "password123",
|
||
"password_confirmation": "password123"
|
||
}'
|
||
```
|
||
|
||
**Ответ:**
|
||
|
||
```json
|
||
{
|
||
"message": "User registered successfully",
|
||
"user": {
|
||
"id": 1,
|
||
"name": "John Doe",
|
||
"email": "john@example.com",
|
||
"role": null,
|
||
"created_at": "2026-03-20T03:45:00.000000Z"
|
||
},
|
||
"token": "1|abc123..."
|
||
}
|
||
```
|
||
|
||
### 5.2 Вход
|
||
|
||
**Запрос:**
|
||
|
||
```bash
|
||
curl -X POST http://la.test/api/login \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"email": "john@example.com",
|
||
"password": "password123"
|
||
}'
|
||
```
|
||
|
||
**Ответ:**
|
||
|
||
```json
|
||
{
|
||
"message": "Login successful",
|
||
"user": {
|
||
"id": 1,
|
||
"name": "John Doe",
|
||
"email": "john@example.com",
|
||
"role": null,
|
||
"created_at": "2026-03-20T03:45:00.000000Z"
|
||
},
|
||
"token": "2|def456..."
|
||
}
|
||
```
|
||
|
||
### 5.3 Создание поста
|
||
|
||
**Запрос:**
|
||
|
||
```bash
|
||
curl -X POST http://la.test/api/posts \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer {token}" \
|
||
-d '{
|
||
"title": "My First Post",
|
||
"content": "This is the content of my post."
|
||
}'
|
||
```
|
||
|
||
**Ответ:**
|
||
|
||
```json
|
||
{
|
||
"message": "Post created successfully",
|
||
"post": {
|
||
"id": 1,
|
||
"title": "My First Post",
|
||
"content": "This is the content of my post.",
|
||
"user_id": 1,
|
||
"user": {
|
||
"id": 1,
|
||
"name": "John Doe",
|
||
"email": "john@example.com"
|
||
},
|
||
"created_at": "2026-03-20T03:50:00.000000Z",
|
||
"updated_at": "2026-03-20T03:50:00.000000Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 5.4 Обновление поста
|
||
|
||
**Запрос:**
|
||
|
||
```bash
|
||
curl -X PUT http://la.test/api/posts/1 \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer {token}" \
|
||
-d '{
|
||
"title": "Updated Title"
|
||
}'
|
||
```
|
||
|
||
### 5.5 Удаление поста
|
||
|
||
**Запрос:**
|
||
|
||
```bash
|
||
curl -X DELETE http://la.test/api/posts/1 \
|
||
-H "Authorization: Bearer {token}"
|
||
```
|
||
|
||
### 5.6 Выход
|
||
|
||
**Запрос:**
|
||
|
||
```bash
|
||
curl -X POST http://la.test/api/logout \
|
||
-H "Authorization: Bearer {token}"
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Swagger документация
|
||
|
||
### 6.1 Доступ к документации
|
||
|
||
Swagger UI доступен по адресу: `{APP_URL}/api/docs`
|
||
|
||
Например: `http://la.test/api/docs`
|
||
|
||
### 6.2 Структура файлов документации
|
||
|
||
```
|
||
public/
|
||
└── docs/
|
||
├── index.html # Swagger UI
|
||
└── openapi.yaml # OpenAPI спецификация
|
||
```
|
||
|
||
### 6.3 Обновление документации
|
||
|
||
После добавления новых endpointов перегенерируйте документацию:
|
||
|
||
```bash
|
||
php artisan swagger:generate
|
||
```
|
||
|
||
### 6.4 Конфигурация Spectrum
|
||
|
||
```php
|
||
// config/spectrum.php
|
||
|
||
return [
|
||
'output' => 'public/docs',
|
||
'title' => env('APP_NAME', 'Laravel API'),
|
||
'description' => 'API Documentation',
|
||
'version' => '1.0.0',
|
||
'server_url' => env('APP_URL'),
|
||
'servers' => [
|
||
['url' => env('APP_URL'), 'description' => 'Local server'],
|
||
],
|
||
'security_schemes' => [
|
||
'bearerAuth' => [
|
||
'type' => 'http',
|
||
'scheme' => 'bearer',
|
||
'bearerFormat' => 'JWT',
|
||
],
|
||
],
|
||
'default_security_scheme' => 'bearerAuth',
|
||
'paths' => [
|
||
'controllers' => ['App\\Http\\Controllers\\Api\\'],
|
||
],
|
||
];
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Команды Artisan
|
||
|
||
### 7.1 Создание пользовательской команды
|
||
|
||
#### Структура директорий
|
||
|
||
Команды Artisan располагаются в директории `app/Console/Commands/`:
|
||
|
||
```
|
||
app/
|
||
├── Console/
|
||
│ └── Commands/
|
||
│ └── GenerateSwagger.php # Наша команда
|
||
```
|
||
|
||
#### Создание команды
|
||
|
||
**1. Создайте директорию Commands:**
|
||
|
||
```bash
|
||
mkdir -p app/Console/Commands
|
||
```
|
||
|
||
**2. Создайте файл команды:**
|
||
|
||
```bash
|
||
# app/Console/Commands/GenerateSwagger.php
|
||
```
|
||
|
||
#### Пример кода команды
|
||
|
||
```php
|
||
<?php
|
||
|
||
namespace App\Console\Commands;
|
||
|
||
use Illuminate\Console\Command;
|
||
use Illuminate\Support\Facades\File;
|
||
use Symfony\Component\Yaml\Yaml;
|
||
|
||
class GenerateSwagger extends Command
|
||
{
|
||
/**
|
||
* Имя и сигнатура команды.
|
||
* Используется для вызова: php artisan swagger:generate
|
||
*/
|
||
protected $signature = 'swagger:generate';
|
||
|
||
/**
|
||
* Описание команды.
|
||
* Показывается в списке команд: php artisan list
|
||
*/
|
||
protected $description = 'Generate OpenAPI specification for the API';
|
||
|
||
/**
|
||
* Метод execute() - основная логика команды.
|
||
* Вызывается при выполнении команды.
|
||
*/
|
||
public function handle(): int
|
||
{
|
||
// Вывод информационного сообщения
|
||
$this->info('Generating OpenAPI specification...');
|
||
|
||
// Создание директории для документации
|
||
$outputDir = public_path('docs');
|
||
if (!File::exists($outputDir)) {
|
||
File::makeDirectory($outputDir, 0755, true);
|
||
}
|
||
|
||
// Генерация спецификации
|
||
$spec = $this->generateSpec();
|
||
|
||
// Конвертация в YAML формат
|
||
$yaml = Yaml::dump($spec, 4, 2);
|
||
|
||
// Сохранение файла
|
||
File::put($outputDir . '/openapi.yaml', $yaml);
|
||
$this->info('OpenAPI specification saved to public/docs/openapi.yaml');
|
||
|
||
// Возврат кода успеха
|
||
return Command::SUCCESS;
|
||
}
|
||
|
||
/**
|
||
* Метод для генерации структуры OpenAPI спецификации.
|
||
* Можно создавать YAML или JSON вручную.
|
||
*/
|
||
protected function generateSpec(): array
|
||
{
|
||
$appUrl = config('app.url', 'http://localhost');
|
||
|
||
return [
|
||
'openapi' => '3.0.0',
|
||
'info' => [
|
||
'title' => config('app.name', 'Laravel API'),
|
||
'description' => 'API Documentation',
|
||
'version' => '1.0.0',
|
||
],
|
||
'servers' => [
|
||
['url' => $appUrl, 'description' => 'Local server'],
|
||
],
|
||
'paths' => $this->generatePaths(),
|
||
'components' => [
|
||
'securitySchemes' => [
|
||
'bearerAuth' => [
|
||
'type' => 'http',
|
||
'scheme' => 'bearer',
|
||
'bearerFormat' => 'JWT',
|
||
],
|
||
],
|
||
],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* Генерация секции paths для OpenAPI.
|
||
*/
|
||
protected function generatePaths(): array
|
||
{
|
||
return [
|
||
'/api/register' => [
|
||
'post' => [
|
||
'tags' => ['Auth'],
|
||
'summary' => 'Register a new user',
|
||
// ... описание endpoint
|
||
],
|
||
],
|
||
// ... другие endpoints
|
||
];
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Основные компоненты команды
|
||
|
||
| Компонент | Описание |
|
||
|----------|----------|
|
||
| `$signature` | Имя команды (например, `swagger:generate`) |
|
||
| `$description` | Описание для списка команд |
|
||
| `handle()` | Основной метод выполнения команды |
|
||
| `$this->info()` | Вывод информационного сообщения |
|
||
| `$this->error()` | Вывод сообщения об ошибке |
|
||
| `$this->warn()` | Вывод предупреждения |
|
||
| `$this->question()` | Вывод вопроса |
|
||
| `Command::SUCCESS` | Код успешного завершения |
|
||
| `Command::FAILURE` | Код неудачного завершения |
|
||
|
||
#### Методы для взаимодействия с пользователем
|
||
|
||
```php
|
||
// Вывод текста
|
||
$this->info('Сообщение'); // Зеленый текст
|
||
$this->error('Ошибка'); // Красный текст
|
||
$this->warn('Внимание'); // Желтый текст
|
||
$this->line('Текст'); // Обычный текст
|
||
|
||
// Запрос подтверждения
|
||
if ($this->confirm('Продолжить?')) {
|
||
// пользователь ответил "да"
|
||
}
|
||
|
||
// Выбор из списка
|
||
$choice = $this->choice('Выберите:', ['opt1', 'opt2', 'opt3'], 0);
|
||
|
||
// Ввод текста
|
||
$name = $this->ask('Введите имя:');
|
||
$password = $this->secret('Введите пароль:'); // Скрытый ввод
|
||
|
||
// Прогресс-бар
|
||
$bar = $this->output->createProgressBar(100);
|
||
$bar->start();
|
||
foreach ($items as $item) {
|
||
// обработка
|
||
$bar->advance();
|
||
}
|
||
$bar->finish();
|
||
```
|
||
|
||
### 7.2 Список команд
|
||
|
||
| Команда | Описание |
|
||
|---------|----------|
|
||
| `php artisan swagger:generate` | Генерация OpenAPI спецификации |
|
||
| `php artisan list` | Список всех команд |
|
||
| `php artisan list api` | Список команд содержащих "api" |
|
||
|
||
### 7.3 Пример использования
|
||
|
||
```bash
|
||
# Генерация документации
|
||
php artisan swagger:generate
|
||
|
||
# Очистка кэша конфигурации
|
||
php artisan config:clear
|
||
|
||
# Очистка кэша маршрутов
|
||
php artisan route:clear
|
||
|
||
# Просмотр списка команд
|
||
php artisan list
|
||
|
||
# Справка по команде
|
||
php artisan swagger:generate --help
|
||
```
|
||
|
||
### 7.4 Автоматическая регистрация
|
||
|
||
Laravel автоматически обнаруживает команды в директории `app/Console/Commands`.
|
||
Для ручной регистрации добавьте в `app/Console/Kernel.php`:
|
||
|
||
```php
|
||
// app/Console/Kernel.php
|
||
|
||
namespace App\Console;
|
||
|
||
use Illuminate\Console\Scheduling\Schedule;
|
||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||
|
||
class Kernel extends ConsoleKernel
|
||
{
|
||
/**
|
||
* The Artisan commands provided by your application.
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $commands = [
|
||
Commands\GenerateSwagger::class,
|
||
];
|
||
|
||
/**
|
||
* Define the application's command schedule.
|
||
*/
|
||
protected function schedule(Schedule $schedule): void
|
||
{
|
||
// $schedule->command('swagger:generate')->daily();
|
||
}
|
||
|
||
/**
|
||
* Register the commands for the application.
|
||
*/
|
||
protected function commands(): void
|
||
{
|
||
$this->load(__DIR__.'/Commands');
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Политики доступа
|
||
|
||
### 8.1 PostPolicy
|
||
|
||
```php
|
||
// app/Policies/PostPolicy.php
|
||
|
||
namespace App\Policies;
|
||
|
||
use App\Models\Post;
|
||
use App\Models\User;
|
||
|
||
class PostPolicy
|
||
{
|
||
public function update(User $user, Post $post): bool
|
||
{
|
||
return $user->id === $post->user_id;
|
||
}
|
||
|
||
public function delete(User $user, Post $post): bool
|
||
{
|
||
return $user->id === $post->user_id;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 8.2 Регистрация политики
|
||
|
||
```php
|
||
// app/Providers/AuthServiceProvider.php
|
||
|
||
namespace App\Providers;
|
||
|
||
use App\Models\Post;
|
||
use App\Models\User;
|
||
use App\Policies\PostPolicy;
|
||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||
|
||
class AuthServiceProvider extends ServiceProvider
|
||
{
|
||
protected $policies = [
|
||
Post::class => PostPolicy::class,
|
||
];
|
||
|
||
public function boot(): void
|
||
{
|
||
$this->registerPolicies();
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 9. Конфигурация .env
|
||
|
||
Убедитесь, что в файле `.env` указаны правильные настройки:
|
||
|
||
```env
|
||
APP_NAME=Laravel
|
||
APP_ENV=local
|
||
APP_KEY=base64:...
|
||
APP_URL=http://la.test
|
||
|
||
DB_CONNECTION=sqlite
|
||
|
||
SESSION_DRIVER=database
|
||
SANCTUM_STATEFUL_DOMAINS=la.test,localhost,127.0.0.1
|
||
```
|
||
|
||
---
|
||
|
||
## 10. Тестирование API
|
||
|
||
### 10.1 Примеры запросов в Swagger UI
|
||
|
||
1. Откройте `http://la.test/api/docs`
|
||
2. Нажмите **Authorize** и введите ваш token
|
||
3. Тестируйте endpoints прямо в браузере
|
||
|
||
### 10.2 Ручное тестирование
|
||
|
||
```bash
|
||
# Проверка списка маршрутов
|
||
php artisan route:list
|
||
|
||
# Запуск сервера
|
||
php artisan serve --host=la.test
|
||
|
||
# Запуск тестов
|
||
php artisan test
|
||
```
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
### Проблема: 401 Unauthorized
|
||
|
||
**Решение:**
|
||
1. Убедитесь, что передаёте правильный токен в заголовке `Authorization`
|
||
2. Проверьте срок действия токена
|
||
3. Убедитесь, что используете префикс `Bearer`
|
||
|
||
### Проблема: CSRF token mismatch
|
||
|
||
**Решение:**
|
||
Для SPA приложений добавьте домен в `SANCTUM_STATEFUL_DOMAINS`:
|
||
|
||
```env
|
||
SANCTUM_STATEFUL_DOMAINS=la.test,localhost,127.0.0.1
|
||
```
|
||
|
||
### Проблема: Таблица уже существует
|
||
|
||
**Решение:**
|
||
Если миграция `personal_access_tokens` уже выполнена, пропустите её:
|
||
|
||
```bash
|
||
php artisan migrate --path=/database/migrations/2026_03_20_032532_create_personal_access_tokens_table.php --skip
|
||
```
|
||
|
||
---
|
||
|
||
## Заключение
|
||
|
||
Теперь у вас есть полностью настроенный API с:
|
||
- ✅ Laravel Sanctum для аутентификации
|
||
- ✅ Token-based авторизация
|
||
- ✅ API Resources для форматирования ответов
|
||
- ✅ Form Requests для валидации
|
||
- ✅ Swagger документация по адресу `/api/docs`
|
||
- ✅ Политики доступа для постов
|
||
|
||
Для получения дополнительной информации обратитесь к официальной документации:
|
||
- [Laravel Sanctum](https://laravel.com/docs/sanctum)
|
||
- [wadakatu/laravel-spectrum](https://github.com/wadakatu/laravel-spectrum)
|