symfonycontrib/confirm-bundle
Symfony bundle that adds a confirmation step to sensitive actions, letting you guard routes, controllers, and forms with a simple confirm dialog before changes are applied.
Install and register the bundle
composer require symfonycontrib/confirm-bundle
Then register it according to your Symfony version:
app/AppKernel.php in registerBundles().config/bundles.php.composer.json for supported Symfony constraints before assuming compatibility.Read the bundle source first, not just the README This is a low-traffic package (0 dependents, no stars), so the source is the most reliable documentation. Start with:
Form/Type/ — the confirmation form type and its options.Controller/ — any provided confirmation controller/action.Resources/config/ — service definitions and service IDs.Resources/views/ — the confirmation template and its blocks.DependencyInjection/ — configuration tree and default parameters.First use case: destructive-action confirmation The typical day-one integration is a "delete/confirm" page:
Sketch (adapt class/option names to what the bundle actually exposes):
public function delete(Request $request, int $id): Response
{
$entity = $this->repository->find($id);
if (!$entity) {
throw $this->createNotFoundException();
}
$form = $this->createForm(ConfirmType::class, null, [
'action' => $this->generateUrl('item_delete', ['id' => $id]),
'method' => 'POST',
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->repository->remove($entity);
$this->em->flush();
return $this->redirectToRoute('item_index');
}
return $this->render('item/confirm_delete.html.twig', [
'form' => $form->createView(),
'entity' => $entity,
]);
}
Two-step confirmation flow (recommended) Keep the confirmation step separate from the mutation:
GET /item/{id}/delete → render the confirmation form.POST /item/{id}/delete → validate the form (including CSRF), perform the action, redirect.Reuse the bundle's form type
If the bundle provides a ConfirmType, instantiate it in controllers rather than hand-rolling a form. Benefits: consistent button labels, translation domain, template block names, and any CSRF/validation defaults the bundle ships. If the bundle expects options such as a message, action URL, or cancel URL, pass them from the controller so the form remains presentation-agnostic.
Wrap it in a service or controller trait For applications with many destructive actions, wrap the flow:
final class ConfirmationHandler
{
public function confirm(Request $request, callable $onConfirm): Response
{
// build form, handle request, invoke callback on valid POST
}
}
This keeps controllers from repeating form-building logic and gives you one place to change behavior if the bundle is later replaced.
Template overrides
If the bundle's default markup does not match your design system, override its templates in templates/bundles/ConfirmBundle/ (Symfony 4+) or app/Resources/ConfirmBundle/views/ (Symfony 2/3). Prefer overriding a single block (buttons, message) rather than copying the whole template, so upstream fixes remain visible.
Translations
Check whether the bundle ships translation files under Resources/translations/. If so, configure the translation domain used by the form and add your locale. If not, pass explicit labels through form options rather than hard-coding strings in templates.
Integration with existing forms
If your application already uses Symfony Forms, the confirmation type can be embedded as a nested form or used as the sole field of a small form. Keep the confirmation form's action pointing to the same route that renders it, which simplifies routing and avoids open-redirect issues from user-supplied return URLs.
Testing
composer.json constraints before adopting it. If it targets Symfony 2/3 only, budget time to fork it or replace it with a small custom form type.config/bundles.php; older projects use AppKernel. A bundle built for Symfony 2 will not auto-register under Flex.$container->get('confirm...') in controllers; inject the service or the form type instead.DELETE, ensure _method is set and the route allows POST with method override. Otherwise you will get 405 errors that look like routing bugs.$request->query->get('return') straight through.bin/console debug:container --tag=form.type to find the registered type, debug:router to confirm the route/method, and the profiler's Forms panel to inspect submitted data and errors. If the form always appears invalid, check the CSRF token and the form's action/method against the route.FormTypeExtensionInterface) to add fields, and (4) decorating the bundle's service in services.yaml. Avoid editing files in vendor/.How can I help you explore Laravel packages today?