Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Confirm Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and register the bundle

    composer require symfonycontrib/confirm-bundle
    

    Then register it according to your Symfony version:

    • Symfony 2/3: add it to app/AppKernel.php in registerBundles().
    • Symfony 4/5: add it to config/bundles.php.
    • Symfony 5.3+/6: the bundle may need a Flex recipe or manual registration; check the repo's composer.json for supported Symfony constraints before assuming compatibility.
  2. 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.
  3. First use case: destructive-action confirmation The typical day-one integration is a "delete/confirm" page:

    • A GET request renders a form with a confirmation message and Confirm/Cancel buttons.
    • A POST request with a valid CSRF token performs the destructive action.
    • Cancel redirects back without mutating state.

    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,
        ]);
    }
    

Implementation Patterns

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.
  • Never mutate state on GET. This makes the flow safe against link prefetching, crawlers, and accidental refreshes.

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

  • Functional test: GET the confirmation route, assert the message is present; POST without the token and assert 403/validation failure; POST with a valid token and assert the entity is removed and a redirect is returned.
  • Unit test any confirmation handler/service in isolation by mocking the request and form factory.
  • Add a test that a GET request does not delete anything, since this is the most common regression in confirmation flows.

Gotchas and Tips

  • Maintenance risk is the headline. With no stars and no dependents, assume the package may be abandoned. Check the last commit date and 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.
  • Bundle registration differs by Symfony version. Symfony 4+ uses config/bundles.php; older projects use AppKernel. A bundle built for Symfony 2 will not auto-register under Flex.
  • Service IDs may be private. In modern Symfony, bundle services are private by default. Do not rely on $container->get('confirm...') in controllers; inject the service or the form type instead.
  • CSRF is the point — do not disable it. Confirmation forms exist to prevent CSRF and accidental actions. If the bundle's form does not include a CSRF field by default, add one via form options or a form extension. Verify the token is validated on POST.
  • Method spoofing. If the confirmation form posts to a route restricted to DELETE, ensure _method is set and the route allows POST with method override. Otherwise you will get 405 errors that look like routing bugs.
  • Double submission and idempotency. A user double-clicking Confirm can trigger two POSTs. Use a redirect-after-POST and, for critical actions, consider a one-time token or a uniqueness constraint on the operation. The confirmation form itself does not make the action idempotent.
  • Open redirects via cancel/return URLs. If the bundle accepts a "cancel" or "return" URL option, validate it against an allowlist of routes or paths. Do not pass $request->query->get('return') straight through.
  • Debugging: use 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.
  • Extension points: the safest customization points are (1) form type options, (2) template block overrides, (3) a form type extension (FormTypeExtensionInterface) to add fields, and (4) decorating the bundle's service in services.yaml. Avoid editing files in vendor/.
  • Consider whether you need the bundle at all. A confirmation page is roughly a Symfony form with a submit button, a CSRF token, and a redirect. If the bundle is unmaintained or its API does not fit, a ~30-line local form type is often lower risk than adopting a 0-dependency package. Use the bundle only if it provides meaningful behavior you would otherwise reimplement (e.g., standardized templates, translations, or a controller flow).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core