Custom Form Handler in Statamic

This past week I've been working on some pretty heavy forms in Statamic that led me down the path to some custom Statamic addon development.

Originally posted on https://zaengle.com/blog/custom-form-handler-in-statamic

This past week I've been working on some pretty heavy forms in Statamic that led me down the path to some custom Statamic addon development.

The Statamic docs are generally excellent 99% of the time, but there's nothing in the API docs around form handling. So for that kind of work, you're needing to grok core.

Here was my MO with form submissions:

We know that Statamic creates files from form submissions natively - if you've enabled that in the form settings but how do we pass the submission to the CRM?

My initial thought and process was to create a form listener. On terminal, you'd do:

This scaffolds the listener for me. 

The docs provide a good list of Statamic events but the one I was going to need specifically was Form.submission.creating.

So changing MyFormsListener.php to this

This got me 90% of the way. The CRM was happy, it got the food it needed, it sent the response but nothing happened on the Statamic side 🤔.

Of course, the listener was doing just that, listening for a submission event, Statamic core was handling the rest of the submission process, creating the file, saving to the file system etc.

So, back to the drawing board.

After a post on the forum and a helpful nudge in the right direction from @erin - such a great guy btw - I opted for a custom controller.

The Statamic docs on controllers are great.

I moved my logic from MyFormsListener.php method into a new postSubmission() method inside MyFormsController.php but that doesn't handle creating the form submission.

As I mentioned earlier, you need to grok the core to see how the Statamic Gents handle form submissions. You'll find that in FormListener.php and specifically the create() method.

Taking what's in that method and adding it to my postSubmission() method, specifically lines 29-40 and then 49-64

I should probably mention at this point, my forms are submitted via Vue methods and that's why I'm returning a String value.

If you were handling things server side then you'd do this on line 84.

So there you have it. A custom form handler that takes the submission, saves the data as a flat file on the file system, tries to pass it to a CRM. If successful, we get a redirect URL in response that we can use to redirect the user. If it fails, we log a critical error to notify the client that something went wrong, we still have the form data saved so that we can manually update the CRM and we redirect the user to a fallback URL.

Job done 👍🏼

Thanks for reading.