UUID primary keys cause IRI generation failure in Laravel
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 35/100
Hướng nghiên cứu
Bắt đầu trong vendor/api-platform/laravel/Routing/IriConverter.php, đặc biệt là getIriFromResource() quanh các dòng 119-125 và generateRoute() quanh dòng 182, sau đó so sánh siêu dữ liệu thao tác và tên route được báo cáo với các thao tác ApiResource được định nghĩa rõ ràng. Tái hiện request collection từ issue và xác minh rằng việc tuần tự hóa thành công với các IRI dựa trên UUID cho từng tòa nhà.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
API Platform version(s) affected: 4.1.20
Description
When using UUID as the primary key for Eloquent models with API Platform Laravel, the IriConverter fails to generate proper IRIs for individual items in collections. This results in a InvalidArgumentException: Unable to generate an IRI for the item of type 'App\Models\Building' error when trying to serialize collections in JSON:API format.
The issue occurs because API Platform generates malformed route names (_api_/api/buildings{._format}_get) that don't match the actual Laravel routes and don't include the UUID parameter.
How to reproduce
- Create a Laravel model with UUID as primary key:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use ApiPlatform\Metadata\Delete;
#[ApiResource(
operations: [
new GetCollection(
uriTemplate: '/buildings',
name: 'api_buildings_get_collection'
),
new Get(
uriTemplate: '/buildings/{uuid}',
name: 'api_buildings_get_item'
),
new Post(
uriTemplate: '/buildings',
name: 'api_buildings_post'
),
new Put(
uriTemplate: '/buildings/{uuid}',
name: 'api_buildings_put'
),
new Delete(
uriTemplate: '/buildings/{uuid}',
name: 'api_buildings_delete'
)
],
normalizationContext: ['groups' => ['building:read']],
denormalizationContext: ['groups' => ['building:write']],
paginationEnabled: true
)]
class Building extends Model
{
protected $primaryKey = 'uuid';
protected $keyType = 'string';
public $incrementing = false;
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if (!$model->uuid) {
$model->uuid = (string) Str::uuid();
}
});
}
}
- Create a migration with UUID primary key:
Schema::create('buildings', function (Blueprint $table) {
$table->uuid('uuid')->primary();
$table->string('name');
$table->uuid('user_uuid');
$table->timestamps();
});
- Configure API Platform (
config/api-platform.php):
return [
'formats' => [
'jsonapi' => ['application/vnd.api+json'],
],
'defaults' => [
'route_prefix' => '/api',
],
];
- Make a request to the collection endpoint:
// Test case
public function test_it_lists_buildings(): void
{
Building::factory()->count(3)->create();
$response = $this->get('/api/buildings', [
'Accept' => 'application/vnd.api+json',
]);
$response->assertOk(); // Fails with IRI generation error
}
Error Output:
InvalidArgumentException: Unable to generate an IRI for the item of type "App\Models\Building"
Stack trace:
#0 vendor/api-platform/laravel/Routing/IriConverter.php(182): Unable to generate an IRI for the item of type "App\Models\Building"
api-platform/api-platform#1 vendor/api-platform/laravel/Routing/IriConverter.php(149): ApiPlatform\Laravel\Routing\IriConverter->generateRoute()
api-platform/api-platform#2 vendor/api-platform/jsonapi/Serializer/ItemNormalizer.php(100): ApiPlatform\Laravel\Routing\IriConverter->getIriFromResource()
Debug logs from IriConverter:
[IriConverter] Generating route:
- routeName: "_api_/api/buildings{._format}_get"
- identifiers: ["uuid" => "550e8400-e29b-41d4-a716-446655440000"]
- operation_class: "ApiPlatform\Metadata\Get"
- operation_name: "_api_/api/buildings{._format}_get"
Possible Solution
The issue appears to be in IriConverter::getIriFromResource() where it creates a new Get operation without proper configuration:
// Line 119-125 in IriConverter.php
if (!$operation) {
$operation = (new Get())->withClass($resourceClass);
}
This new operation doesn't have the correct route name or URI template. The IriConverter should:
- Use the explicitly defined operation names from the ApiResource attribute
- Properly detect and handle UUID identifiers
- Generate route names that match Laravel's routing conventions
A potential fix would be to ensure the operation metadata is properly loaded from the resource metadata factory before attempting to generate IRIs.
Additional Context
- Laravel version: 12.x
- PHP version: 8.4+
- Database: MariaDB with UUID columns
- Authentication: Laravel Sanctum
The error occurs specifically when the JSON:API serializer tries to generate the @id field for each item in a collection. Individual item fetches may work if accessed directly, but collections fail during serialization.
This bug prevents any Laravel application using UUIDs as primary keys from working properly with API Platform, which is a significant limitation since UUIDs are commonly used in modern applications for distributed systems and better security.
Workarounds attempted (all failed):
- Defining explicit operations with names and uriTemplates
- Using custom State Providers
- Changing route prefix configurations
- Testing with different output formats (JSON:API, HAL+JSON)
- Ngôn ngữ chính
- PHP
- Star
- 2.6k
- Fork
- 989
- Merge trung bình
- 1 ngày 17 giờ
- Pull request đã merge (30 ngày)
- 81
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của api-platform/core
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
api-platform/core#8665 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
api-platform/core#8660 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
DeserializeProvider calls PartialDenormalizationException::getErrors(), deprecated in Symfony 8.1Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
api-platform/core#8650 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
`OrderExtension` and `OrderFilter` pass string sort directions, deprecated since `doctrine/orm` 3.7Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
api-platform/core#8648 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Laravel] Optional BelongsTo relation cannot be set to null (500 on POST/PATCH)Có thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 54/100
api-platform/core#8664 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của api-platform/core
Issue tương tự
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
Maintainer thường phản hồi trong vòng 1 ngày
-
sync-en
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
Maintainer thường phản hồi trong vòng 1 ngày
-
sync-en
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
Maintainer thường phản hồi trong vòng 4 ngày
-
Перевод устарел
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
-
Adapter: Algolia Performance
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100