core
core copied to clipboard
Service Injection in Processor Causes /api Route to Fail
API Platform version(s) affected: 4.1.8 on Laravel
Description
After creating a processor in Laravel, if you inject a service into the processor’s constructor, accessing the /api route results in a 500 error, as shown in the image.
How to reproduce
<?php
//app/State/UserProcessor.php
declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
final class UserProcessor implements ProcessorInterface
{
public function __construct(
private ProcessorInterface $persistProcessor,
private ProcessorInterface $removeProcessor,
)
{
}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): void
{
// Handle the state
}
}
<?php
//app/Models/User.php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use ApiPlatform\Metadata\ApiResource;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
#[ApiResource(processor: 'App\State\UserProcessor')]
class User extends Authenticatable
{
/** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var list<string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var list<string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
}
Create a service provider I'm not sure how we're supposed to know what services to inject in the UserProcessor.
@soyuka
I used the following command to create the processor:
php artisan make:state-processor
This added the following line to the AppServiceProvider:
$this->app->tag(UserProcessor::class, ProcessorInterface::class);
Here is the content of the provider
<?php
namespace App\Providers;
use App\State\UserProcessor;
use ApiPlatform\State\ProcessorInterface;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
$this->app->tag(UserProcessor::class, ProcessorInterface::class);
}
}
However, it seems that this part of the documentation isn't working as expected: https://api-platform.com/docs/core/state-processors/#laravel-state-processor-mechanism
If you want both arguments to be properly injected you're missing something like:
$this->app->singleton(UserProcessor::class, function (Application $app) {
return new UserProcessor(
$app->make(\ApiPlatform\Laravel\Eloquent\State\ItemProvider::class),
$app->make(\ApiPlatform\Laravel\Eloquent\State\RemoveProcessor::class),
);
});
Thank you. This code works:
$this->app->singleton(UserProcessor::class, function (Application $app) {
return new UserProcessor(
$app->make(\ApiPlatform\Laravel\Eloquent\State\PersistProcessor::class),
$app->make(\ApiPlatform\Laravel\Eloquent\State\RemoveProcessor::class),
);
});
So I believe the documentation should be updated for both the state provider and the state processor sections.
don't hesitate to update the documentation thanks!
Okay. I will
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.