I use ApiPlatform and want to change the delete request behavior for my entities. In every entity, I have a status property - when a delete request is called, it should set status to 0 instead of removing the record from the database.
I have a solution for this (a custom controller), but I have to create a new controller for each entity. Is it possible to create one controller and reuse it?
My plan was:
status
property is requiredinterface SoftDeletableInterface
{
public function setStatus(int $status): static;
}
#[ApiResource(
operations: [
new Delete(
controller: ChannelSoftDeleteController::class
),
]
)]
public function __invoke(string $entityClassName, $id): Response
{
$entityClass = 'App\\Entity\\' . ucfirst($entityClassName);
if (!class_exists($entityClass) || !is_subclass_of($entityClass, SoftDeletableInterface::class))
{
return new Response(null, Response::HTTP_METHOD_NOT_ALLOWED);
}
$repository = $this->entityManager->getRepository($entityClass);
$entity = $repository->find($id);
if (!$entity)
{
return new Response(null, Response::HTTP_NOT_FOUND);
}
$entity->setStatus(0);
$this->entityManager->persist($entity);
$this->entityManager->flush();
return new Response(null, Response::HTTP_NO_CONTENT);
}
But it generates error:
Could not resolve argument $entityClassName of "App\Controller\SoftDeleteController::__invoke()", maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?
When the __invoke
argument is specific class (Channel
in my case) everything works.
I also tried passing the argument without type declaration to __invoke
:
public function __invoke($entity)
but it's generate same error
At least in ApiPlatform v3.3, deleting the entity happens in a service named api_platform.doctrine.orm.state.remove_processor
, implemented in ApiPlatform\Doctrine\Common\State\RemoveProcessor
. You could try to override this service like this:
class SoftDeleteProcessor implements ProcessorInterface
{
use ClassInfoTrait;
public function __construct(private readonly ManagerRegistry $managerRegistry)
{
}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): void
{
if (!$manager = $this->getManager($data)) {
return;
}
$data->setStatus(0);
$manager->persist($data);
$manager->flush();
}
/**
* Gets the Doctrine object manager associated with given data.
*/
private function getManager($data): ?DoctrineObjectManager
{
return \is_object($data) ? $this->managerRegistry->getManagerForClass($this->getObjectClass($data)) : null;
}
}