I don’t understand how add_action and do_action work in tandem. The former executes the code already…what is do_action for?

The do_action() function executes any code that’s been hooked with add_action(). The only reason your function_save_custom_form_data() function runs is because the WP Forms plugin has added a call to do_action() inside its code.

So what using do_action() in a theme or plugin does is allow other plugins or themes to run code during its processes. In your example, whenever the form processing is completed, the WP Forms plugin runs do_action( 'wpforms_process_complete' ). This doesn’t do anything on its own, but it allows you to use add_action() to run code at that point by using add_action().

Also in the example, the do_action has more params passed. The add_action function has only one, yet i’m able to access it like an array with ease?

In your callback function you’re accessing $this->fields as $params (so it’s not an appropriate name), which happens to be an array. You don’t have any access to $entry, $form_data or $entry_id. To get access to these you need to pass the number of arguments you accept to add_action. For example, this allows you to access all 4 arguments:

add_action( 'wpforms_process_complete', 'function_save_custom_form_data', 10, 4 );

The last argument is the “accepted args” value. By setting it to 4 you’re letting WordPress know that your function_save_custom_form_data() function accepts 4 arguments, which you can now use like this:

function function_save_custom_form_data( $fields, $entry, $form_data, $entry_id ) {

Under the hood the 2nd arugment you’re passing to add_action() is a callback, and do_action() just executes that callback.