Tag: PHP

This is not very elegant and could easily be expanded, but while it was fresh in my head, I thought I would share it in case it helps anyone.

The shortcode asks for two attributes: name and values

If the param value is contained in the list, it will hide any content you've put in between the opening and closing shortcodes.


Your View: [check_param_list name="project" values="Project A, Project B, Project C"] Here's the content I want to show if the project is NOT listed[/check_param_list]

Scenario 1 - Your project param = Project A: Nothing will show

Scenario 2 - Your project param = Project D: "Here's the content I want to show if the project is NOT listed" will be displayed

This was my quick and dirty way of handling a situation where I have a standard view for most projects using a central form, but there are a handful of projects that have custom views. In this situation, I don't want to have lots of separate pages for each one. By using this approach, I can have a single page with this shortcode (which has the standard view as its content), followed by two (for now) frm-condition shortcodes, one for each of the projects that have custom views. If I need to add an additional custom view I can add the new project to the list of values and include an additional frm-condition shortcode to display the custom view.*

While being a bit clunky, it has the advantage of being able to be edited/added to by colleagues who are unable to edit shortcodes directly.

Here's the PHP for the shortcode, which can be added to theme functions or via the code snippets plugin.

add_shortcode('check_param_list', 'check_param_value_against_multiple_values');
function check_param_value_against_multiple_values( $atts, $content="" ) {
if ( ! isset( $atts['name'] ) || ! isset( $atts['values'] ) ) {
return $content;
$get_param_name = isset( $_GET[ $atts['name'] ] ) ? $_GET[ $atts['name'] ] : '';
$get_param_name = utf8_decode( urldecode( $get_param_name ) );
$values_array = explode(",",$atts['values']);
if (in_array($get_param_name, $values_array)) {
$content = "";
return do_shortcode( $content );


NOTE: The following is really not specific to Formidable, rather it's specific to WordPress, however, there are so many opportunities to use this in Formidable that I've written it as if it were a "Formidable thing".  Amusingly enough, when I got done with this, I discovered this entry in the Formidable Knowledgebase.

/* add_shortcode is a WordPress function and its first and second parameters can be anything you want, though you should make sure both are as unique as possible to avoid conflicts.  In the below example, I added 'ff_custom_' to minimize the chances of a conflict.  The second parameter must match exactly with the name of the function attached to the shortcode  */

add_shortcode('myCustomShortcode', 'ff_custom_doSomething');

/* In your PHP function, you'll do all the calculations, database searching or whatever and then use RETURN to send the information back to Formidable (or WordPress or whatever).  The data you return can be as simple as true/false or as "complex" as an entire stream of HTML.  Actually, you don't have to pass back any information (so just use return;) if you want the shortcode to do something rather than return something.

The parameter $atts is an array of attributes (parameters) you can pass to the function when calling it from a Formidable page or view, e.g., [myCustomShortcode entry=[id]].  In that example, there's a parameter named "entry" and its value is the value Formidable assigns to [id].

In this function, you can do whatever you can accomplish in PHP.  Frequently you pass in a Formidable entry id or key and then use the Formidable functions to get the information from that entry and do something with it.  That's what I'll do for the example below in which we return the square root of a number since we can't easily do square root using Formidable's math functions.  See this Formidable example.


function ff_custom_doSomething($atts) {

  $entry_id = $atts["entry"];

  $number_field_id = 101; // example field id

  $val = FrmEntryMeta::get_entry_meta_by_field( $entry_id, $number_field_id, true );

  $myVal = sqrt($val );

  return $myVal;


In summary, you can have a shortcode almost anywhere you want, certainly without a page or view and the shortcode can do an infinite amount of things.

Recently a client of ours asked if we could implement a solution to allow a Formidable Forms submission to send data as a CSV file to an external server when a user submits the form. The client wanted the form submissions to be imported into a 3rd party software that could only accept CSV files from a folder on an external server so we looked at building a solution.

This functionality can have several use cases and be used as our client required to export a unique CSV file per form entry or you could amend it to allow a single CSV file to be updated with a new row each time a form is submitted.

You can view the full tutorial, along with a little extra information on connecting to a remote FTP server, HERE.

Part 1: Create the CSV

Firstly, we created a form for users to fill out which will capture essential data we would need to store on the CSV. Our code below assumes the form has the following fields (but you can change these to meet your requirements):

  1. First name
  2. Last name
  3. Email address
  4. Organisation ID
  5. Organisation Name

In our snippet below, we use the frm_after_create_entry hook which runs after the entry has been created in the database. This allows us to use the data once the form has been submitted.

add_action('frm_after_create_entry', 'create_csv', 30, 2);
function create_csv($entry_id, $form_id) {
	if ($form_id == 1234) { //replace 1234 with the id of the form

		// Collect the form data - Add a new row for each field you want to export and give it a unique name
		$firstName = isset($_POST['item_meta'][1537]) ? $_POST['item_meta'][1537] : '';
		$lastName = isset($_POST['item_meta'][1538]) ? $_POST['item_meta'][1538] : '';
		$email = isset($_POST['item_meta'][1540]) ? $_POST['item_meta'][1540] : '';
		$organizationId = isset($_POST['item_meta'][1547]) ? $_POST['item_meta'][1547] : '';
		$organizationName = isset($_POST['item_meta'][1548]) ? $_POST['item_meta'][1548] : '';
		$createdAt = isset($_POST['item_meta'][1555]) ? $_POST['item_meta'][1555] : '';

		// The header row of the CSV - Add a name for each field in the form
		$header = "firstName,lastName,email,organizationId,organizationName,createdAtn";

		// The data of the CSV - Add each of the form fields listed above
		$data = "$firstName,$lastName,$email,$organizationId,$organizationName,$createdAtn";

		 * The file name of the CSV.
		 * NB: To save a single file per entry you will need to make the file name unique 
		 * This can be done using the entry ID or the date & time stamp by including the hour, minutes & seconds. 
		 * E.g at 12:38:43 the file will be named "TestUser-21-02-05-12-38-43-request.csv".
		 * One second later the time (and file name) will be "12:38:44".
		 * Then a new file "TestUser-21-02-05-12-38-44-request.csv" will be created.
		 * How you name the file will determine if you have a new file for each entry, a new file per user or a single file with all entry data.

		$fileName = dirname(__DIR__, 3) . "/your-project-folder/" . $refUserId . "-" .$createdAt . "-request" . ".csv";

		 * Create the CSV file.
		 * If file exists, append the data to it. Otherwise create a new file.
		if (file_exists($fileName)) {
			// Add only data. The header is already added in the existing file.
			file_put_contents($fileName, $data, FILE_APPEND);
		} else {
			// Add CSV header and data.
			file_put_contents($fileName, $header.$data);

What the code does

The function, create_csv, will first check to see which form has been submitted. In our case, if the form with an ID of 1234 has a new entry then the rest of our code will trigger.

We’re storing all the data we need to export onto the CSV into PHP variables. This will make it much easier to pass our $data. You’ll need to add rows for each field you want to export giving it a unique variable name. We’re also using the PHP isset function which will handle the scenario of any of the fields being left blank and not containing a value.

$firstName = isset($_POST['item_meta'][202]) ? $_POST['item_meta'][202] : '';
$lastName = isset($_POST['item_meta'][203]) ? $_POST['item_meta'][203] : '';
$email = isset($_POST['item_meta'][204]) ? $_POST['item_meta'][204] : '';
$organizationId = isset($_POST['item_meta'][193]) ? $_POST['item_meta'][193] : '';
$organisationName = isset($_POST['item_meta'][194]) ? $_POST['item_meta'][194] : '';
$refUserId = isset($_POST['item_meta'][197]) ? $_POST['item_meta'][197] : '';
$createdAt = isset($_POST['item_meta'][199]) ? $_POST['item_meta'][199] : '';

If you’re reading this article then you’re most likely familiar with what components make up a valid CSV document. For those of you who aren’t so familiar, CSVs are made up of two main parts: Headers; and Data – separated by commas (or any other valid delimiter).

Simply put, headers are the name of the column whereas the data is the value you’d like to store in that column.

For our function, we need to come up with suitable headers (column names) for our CSV document and store our data in CSV format.

$header = "firstName,lastName,email,organizationId,organisationName,refUserId,createdAtn";

$data = "$firstName,$lastName,$email,$organizationId,$organisationName,$refUserId,$createdAtn";

The next stage is to save the file to our web-server and to do that we need to decide on what we want the file to contain. If we want to create a new file for each form entry (as our client did) then we’ll need to create a unique filename for each file. We do this in our code by adding the date & time stamp to each file name however if you want to have just 1 CSV file add a new row to it for each new form entry you can set the filename as something static.

We also need to set a location to save the file on our local server.

In our clients case we set this fucntion up using the Code Snippets plugin and as the code will be executed from the plugin folder we had to add in (__DIR__, 3) in the file path to look 3 directories above where the code runs to then get the correct to the folder they wanted to store the files locally.

The file path and name are then all set on the same line of code using variable set as seen below.

$fileName = dirname(__DIR__, 3) . "/your-project-folder/" . $refUserId . "-" . $createdAt . "-request" . ".csv";

If you only want to save the CSV file(s) on your own web-server then thats all you need to do. However if you then want to move the files once they have been created to an external server via FTP, you can view the full tutorial HERE which covers stage 2 ina bit more detail.

And thats it. We’ve tried to add as much markup as possible to the code itself to help explain further what each part does so amending this to your own needs should be quite straight forward.

There are examples on the Formidable site for sending data from repeaters in one form to repeaters in another, but nothing that matched this scenario so I hope this tutorial is of use. It can be adapted for a situation where from A has any number of repeaters as long as Form B has none.

You will need the API add on and an active licence for this to work.

Example scenario:

On submission of Form A a new entry is created in Form B for every row in the relevant Form A repeater(s):

Form A
Form B

Solving the problem using the API add on

The first thing to note is that you can only include fields inside the repeater using this approach so if you need data from elsewhere in the form you will either need to use javascript to copy it into hidden fields in the repeater on the fly or use the frm_validate_field_entry hook to copy on submission - I did the latter.

Unfortunately, you cannot set up a ‘foreach’ argument in the ‘out of the box’ API json builder to handle the repeaters.

What you can do is create an action using the API add on in the settings of each of the child forms that were generated when you created your repeaters and then add a code snippet to trigger them.

To do this follow the steps below:

  1. Go to the settings page of Form A and in the URL bar of your web browser replace the form ID with that of the first repeater (you can find this by going to the Formidable Import/Export screen and searching for the relevant child form – the form ID will be alongside it) and hit enter - you are now in the child form settings
  2. Go to the Actions & Notifications section of the Settings tab
  3. Click the icon to add a 'Send API Data' action
  4. Follow the instructions on the Formidable site to create an entry in another form (https://formidableforms.com/knowledgebase/formidable-api/#kb-create-an-entry-in-another-form )
  5. Update the settings to save your API call
  6. Repeat steps 1-5 for your second repeater (if you have one)

If you tested at this point your API actions would not run because form actions are not triggered by default when either child or embedded forms are submitted. To fix this you need to use a form action hook* to force this to happen. This is the one you need to use: https://formidableforms.com/knowledgebase/frm_use_embedded_form_actions/#kb-examples

I only wanted the triggers to fire on these two child forms so I used the second example, but I changed line 3 from:

if ( $args['form']->id == 123) {


if ( $args['form']->id == 421 || $args['form']->id == 422 ) {

Change 421 to the id of your first child form and 422 to the id of the second child form so that the snippet will run if the form has either of those ids.

If you have found a better approach please do share 😊

*you can find more information on using Formidable Hooks here: https://formidableforms.com/knowledgebase/formidable-hooks/

×Warning: This tutorial was created 1947 days ago. Some of the information may be out of date with more recent versions of Formidable. Please proceed with caution and always perform a backup before adding custom code.

This is the solution provided by authors: https://Formidableforms.com/knowledgebase/javascript-examples/javascript-after-form-submit/

However, it didn't work for me in Chrome (pop-up window blocked).

I found that adding the attribute target="_blank" to the form, opens a new tab on submit.


add_filter( 'frm_form_attributes', 'add_custom_form_attributes', 10, 2 );
function add_custom_form_attributes( $attributes, $form ){
if ( $form->id == 123 ) {
$attributes .= 'target="_blank"';

return $attributes;
×Warning: This tutorial was created 2102 days ago. Some of the information may be out of date with more recent versions of Formidable. Please proceed with caution and always perform a backup before adding custom code.

Create A Staff Timesheet Using Formidable Forms

This article details how to create a basic staff timesheet using Formidable Forms, ideal for home or remote workers or anyone needing to record dates and times in an online form. This article assumes that you are using the latest version of Formidable Pro and know how to add PHP snippets to your site. Along with a basic understanding of HTML and CSS.

This timesheet application consists of three key parts:

  1. A form for entering the dates and times worked
  2. A filter form for filtering the dates viewable (optional)
  3. A view for displaying the information

We built this application using the following steps:

Step 1: Build the initial form

Create your form for users to log their times and dates worked. Include a hidden / admin only field for the time calculation to be inserted. Then add the following PHP snippet to your functions.php file, a custom plugin or the code snippets plugin:

/* Calculate Time Worked */
add_filter('frm_validate_field_entry', 'calculate_time', 11, 3);
function calculate_time($errors, $field, $value){
  if($field->id == 25){ //change 25 to the ID of the hidden or admin only field which will hold the calculation
    	$start = (strtotime($_POST['item_meta'][23])); //change 23 to the ID of the first field
    	$end = (strtotime($_POST['item_meta'][24])); //change 24 to the ID of the second field
$lunch = (strtotime($_POST['item_meta'][25])); //change 25 to the ID of the lunch hour field
    $totaltime = ($end – ($start + $lunch));
    $hours = intval($totaltime / 3600);   
    $seconds_remain = ($totaltime - ($hours * 3600)); 
    $minutes = intval($seconds_remain / 60);
    //$seconds = ($seconds_remain - ($minutes * 60)); Uncomment this line if you want seconds calculated.
    $leading_zero_for_minutes = $minutes < 10 ? '0' : '';
    //$leading_zero_for_seconds = $seconds < 10 ? '0' : '';//Uncomment this line if you're including seconds.
    $totaltime = $hours . ':' . $leading_zero_for_minutes . $minutes;	
    //$totaltime = $hours . ':' . $leading_zero_for_minutes . $minutes . ':' . $leading_zero_for_seconds . $seconds;//uncomment this line if you're including seconds
    $value = $_POST['item_meta'][26] = $totaltime; //change 26 to the ID of the hidden or admin only field which will hold the calculation
  return $errors;

This code will calculate the number of hours worked for each period and insert the value into a hidden or admin only field within your form. This is a slightly edited version of the original snippet which can be found on the Formidable KB HERE.

Step 2: Build a Search form

This stage is optional if you want to be able to search and filter your results in your view (which we did).Create a new search form with any fields you wish to search on. Our search form is very basic and consists of 2 date fields (start_date and end_date). In the form settings we set the following options:

  1. Select “Do not store entries submitted from this form”
  2. Change the ‘On Submit’ option to ‘Redirect to URL’
  3. In the URL enter www.YourSite.com/YourView/?start_date=[551]&end_date=[552] and change 552 and 553 to the ID’s of your 2 date fields.
Step 3: Building Your View

Now you can create your view which will display the hours worked. You may wish to create 2 Views depending on your requirements as it may be useful to have 1 view for the employee to view their own hours and a 2nd view for Administrators to view everyone’s working hours.

In our view, under basic settings, we have selected Form 1 (our time sheet form) and ‘All Entries’ as the view type. Our view has been set up as a html table, but you may wish to build yours differently.

In order to calculate the total time worked for the numbers of rows on display in the table, we have created a new code snippet that will create a total of the hidden fields from Form 1 and add display them in a shortcode – [sum_544] – in the ‘After Content’ section of the view.


Change 7808 to the ID of your view and 544 to the ID of your hidden field in 2 places. This snippet will allow you to only total what is being displayed in the view and therefore will always display the correct total based on the filters being used.

That's pretty much it for the basics. For a more in-depth look at how this was achieved you can view the full article on our website HERE.



Making the Best WordPress Plugin even better - Together

Take on bigger projects with confidence knowing you have access to an entire community of Formidable Experts and Professionals who have your back when the going gets tough. You got this!
Join the community