← Назад к вопросам
REST API для сущности Item (Laravel)
2.0 Middle🔥 211 комментариев
#API и веб-протоколы#Тестирование#Фреймворки
Условие
Разработать REST API (CRUD) сервис на Laravel для управления сущностью Item.
Структура сущности Item
- id - целочисленный автоинкремент
- name - символьное поле (255 символов)
- key - символьное поле (25 символов, обязательное)
- created_at - дата создания
- updated_at - дата обновления
Требования
- Реализовать CRUD операции (Create, Read, Update, Delete)
- Валидация входных данных
- Использовать миграции для создания таблиц
- Использовать Eloquent-модели
- Написать автоматические тесты (покрытие 90%)
Технологии
PHP 8+, Laravel 10+, PHPUnit
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
1. Миграция базы данных
Создание таблицы items:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void {
Schema::create("items", function (Blueprint $table) {
$table->id();
$table->string("name", 255)->nullable();
$table->string("key", 25)->unique();
$table->timestamps();
});
}
public function down(): void {
Schema::dropIfExists("items");
}
};
2. Eloquent модель
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Item extends Model {
protected $fillable = ["name", "key"];
protected $casts = [
"created_at" => "datetime",
"updated_at" => "datetime",
];
}
3. Form Request для валидации
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreItemRequest extends FormRequest {
public function authorize(): bool {
return true;
}
public function rules(): array {
return [
"name" => "nullable|string|max:255",
"key" => "required|string|max:25|unique:items,key",
];
}
public function messages(): array {
return [
"key.required" => "Поле key обязательно",
"key.max" => "Key не может быть длинне 25 символов",
"key.unique" => "Key уже существует",
"name.max" => "Name не может быть длинне 255 символов",
];
}
}
class UpdateItemRequest extends FormRequest {
public function authorize(): bool {
return true;
}
public function rules(): array {
$itemId = $this->route("item")->id;
return [
"name" => "nullable|string|max:255",
"key" => "sometimes|required|string|max:25|unique:items,key,{$itemId}",
];
}
}
4. REST контроллер
<?php
namespace App\Http\Controllers\Api;
use App\Http\Requests\StoreItemRequest;
use App\Http\Requests\UpdateItemRequest;
use App\Models\Item;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
class ItemController extends Controller {
/**
* GET /api/items - Получить все items
*/
public function index(): JsonResponse {
$items = Item::paginate(15);
return response()->json($items);
}
/**
* POST /api/items - Создать новый item
*/
public function store(StoreItemRequest $request): JsonResponse {
$item = Item::create($request->validated());
return response()->json($item, 201);
}
/**
* GET /api/items/{id} - Получить item по id
*/
public function show(Item $item): JsonResponse {
return response()->json($item);
}
/**
* PUT /api/items/{id} - Обновить item
*/
public function update(UpdateItemRequest $request, Item $item): JsonResponse {
$item->update($request->validated());
return response()->json($item);
}
/**
* DELETE /api/items/{id} - Удалить item
*/
public function destroy(Item $item): JsonResponse {
$item->delete();
return response()->json(["message" => "Item deleted successfully"], 200);
}
}
5. Маршруты API
<?php
use App\Http\Controllers\Api\ItemController;
use Illuminate\Support\Facades\Route;
Route::apiResource("items", ItemController::class);
// Автоматически создаст маршруты для:
// GET /api/items
// POST /api/items
// GET /api/items/{item}
// PUT /api/items/{item}
// DELETE /api/items/{item}
6. Тесты (PHPUnit)
<?php
namespace Tests\Feature;
use App\Models\Item;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ItemControllerTest extends TestCase {
use RefreshDatabase;
public function test_get_all_items(): void {
Item::factory()->count(3)->create();
$response = $this->getJson("/api/items");
$response->assertStatus(200);
$response->assertJsonCount(3, "data");
}
public function test_create_item(): void {
$data = ["name" => "Test Item", "key" => "test-key"];
$response = $this->postJson("/api/items", $data);
$response->assertStatus(201);
$response->assertJsonPath("name", "Test Item");
$response->assertJsonPath("key", "test-key");
$this->assertDatabaseHas("items", $data);
}
public function test_create_item_validation_fails(): void {
$data = ["name" => "Test Item"];
$response = $this->postJson("/api/items", $data);
$response->assertStatus(422);
$response->assertJsonValidationErrors(["key"]);
}
public function test_get_item_by_id(): void {
$item = Item::factory()->create(["key" => "unique-key"]);
$response = $this->getJson("/api/items/{$item->id}");
$response->assertStatus(200);
$response->assertJsonPath("key", "unique-key");
}
public function test_update_item(): void {
$item = Item::factory()->create();
$newData = ["name" => "Updated", "key" => "updated-key"];
$response = $this->putJson("/api/items/{$item->id}", $newData);
$response->assertStatus(200);
$this->assertDatabaseHas("items", ["id" => $item->id, "name" => "Updated"]);
}
public function test_delete_item(): void {
$item = Item::factory()->create();
$response = $this->deleteJson("/api/items/{$item->id}");
$response->assertStatus(200);
$this->assertDatabaseMissing("items", ["id" => $item->id]);
}
public function test_unique_key_validation(): void {
Item::factory()->create(["key" => "same-key"]);
$data = ["name" => "Another", "key" => "same-key"];
$response = $this->postJson("/api/items", $data);
$response->assertStatus(422);
$response->assertJsonValidationErrors(["key"]);
}
public function test_key_max_length(): void {
$longKey = str_repeat("a", 26);
$data = ["key" => $longKey];
$response = $this->postJson("/api/items", $data);
$response->assertStatus(422);
}
}
7. Factory для тестов
<?php
namespace Database\Factories;
use App\Models\Item;
use Illuminate\Database\Eloquent\Factories\Factory;
class ItemFactory extends Factory {
protected $model = Item::class;
public function definition(): array {
return [
"name" => $this->faker->sentence(),
"key" => $this->faker->unique()->word(),
];
}
}
Запуск тестов
php artisan test --coverage
API примеры
GET /api/items - Получить все
POST /api/items - {"name": "Item", "key": "item-key"}
GET /api/items/1 - Получить по id
PUT /api/items/1 - Обновить
DELETE /api/items/1 - Удалить