FileMaker Server

An Approach to FileMaker Server-Side Script Debugging

The ability to schedule the execution of FileMaker Scripts – that is scripts created in ScriptMaker/Manage Scripts using FileMaker Pro/FileMaker Pro Advanced client application – under FileMaker Server was one of the sleeper features when it was first introduced in FileMaker Server v9 in July, 2007. It didn’t even rate a mention in the original press release but it’s become a very important tool in my developer bag ever since. Some examples of how I’m using FileMaker Server Side scripts include:

- one client requires a .xml file to be downloaded each day from a URL and imported into a file that then conditionally updates and creates new records in related tables and logs the execution

- we use server side scripts with our fmSMS solution to enable our clients to have the sending of the SMS messages performed by FileMaker Server instead of the client application. For bulk operations (e.g. sending several hundred or more messages at the one time) or for scheduling messages to be sent in the future this enables a user to offload the heavy lifting to the server which can typically perform the scripts faster and without tying up the user’s computer waiting for the script to run

- another client send and receives emails from a FileMaker database. Sending bulk emails previously would take almost 8 hours for their mailing list and require a dedicated computer to handle this that couldn’t be used for the duration of the script.

- we update account balances overnight for another client so that all searches can be performed on stored – and therefore indexed – number fields instead of unstored calculation fields, which can result in a find operation taking seconds vs minutes for large data sets.

FileMaker Server Side Scripts – Before You Begin

There are several important caveats that you need to know before you dive head first into setting up your FileMaker Server Side scripts:

- not all Script steps are supported. Only “Server” compatible script steps are supported. You can view the list of server compatible script steps by changing the Show Comptability popup menu in the bottom left hand corner the script window when editing a script:

All script steps that are NOT server compatible will then be greyed out, leaving you with the list of compatible script steps:

If you’re hoping to offload the generation of PDF invoices which are then emailed to a contact then you’re out of luck as far as native FileMaker script steps are concerned. You can use the Send Email via STMP Server step but the Save Records As PDF step is not available – hopefully this will be supported in a future version of FileMaker Server.

- some Script steps are only compatible when certain options are selected. For  example the Send Mail step is only compatible when used with the send via Server option (not client):

Any supported script step that has the option of presenting a dialog box to the user is only compatible when the dialog is not displayed – you’ll need to select the “Perform without dialog” option in this case. Examples of this include Sort Records, Commit Records and Delete Record.

- the Allow User Abort script step determines what happens when a server side script encounters an unsupported script step. From the FileMaker Server v11 Help:

  • If the Allow User Abort script step option is enabled (On), unsupported script steps will stop the script from continuing.
  • If the Allow User Abort script step option is disabled (Off), unsupported script steps are skipped over and the script continues to execute.
  • If this script step is not included, scripts are executed as if the feature is enabled, so unsupported script steps will stop scripts.

- A server-side FileMaker script that is running on one FileMaker server cannot open a database that is hosted on a different FileMaker server.

- Server-side FileMaker scripts run in separate sessions on the Database Server. Each session has its own copy of global fields and variables.

- FileMaker Server can also reference FileMaker plug-ins (see the FileMaker Server v11 Help for details on how to install and enable plug-ins under FileMaker Server)

- there is no script debugger!

Server Side Script Logging

The lack of a script debugger is the focus of the rest of this post. FileMaker Pro Advanced provides a number of tools to assist developers in debugging scripts, including the Script Debugger and the Data Viewer. Both of these tools make life easy for the FileMaker developer to see what is happening at each step of the script and the current values in fields and variables that the script is referencing. However when it comes to debugging scripts under FileMaker Server you’re essentially on your own and need to roll your own solution – remember that there is no interface on FileMaker Server to show you the progress of each script and set breakpoints or access the Data Viewer. The FileMaker Server Log Viewer shows some information AFTER the script has executed which can help but it is very limited. The list of Schedules in the Admin Console also shows when the schedule was last completed and when it’s due to run next.

Some of my server-side scripts have hundreds of steps – when things go wrong or you don’t get the result you expected (or nothing appears to happen) you’re not sure where to start. I needed a solution that was as dynamic as possible and would involve the minimal amount of additional schema changes and let me insert the equivalent of breakpoints at any point in the script to capture information about the current state. My solution to this was to create a built-in log table that I can populate as I go without having to change contexts (i.e. no switching to a new layout based on the log table occurrence to create records). This can be done quite easily using the Magic Key/Pivot technique but I wanted a solution that didn’t require any new relationships and required the least amount of additional script steps so I turned to FileMaker’s internal SQL feature that is currently only exposed through the use of an external plug-in.

This approach does require a plug-in – there are several free and paid ones to choose from – but for me it’s the neatest way to adding logging features to a server side script. Once you’ve installed and enabled the plug-in under FileMaker Server you can easily add some logging features to your database to help you debug a server-side script process. Here’s my approach to server-side script debugging/logging:

- in the database that contains the script I copy/paste in a new table: ServerLog. This table has a handful of fields and FileMaker Pro will then create a single table occurrence and layout for you automatically (you can make the layout visible only in Layout mode). Do NOT rename or delete the table occurrence!

- install and enable the plug-in that can perform the internal SQL operations for you: see the list of plug-ins at the end of this article that I’ve used recently. I currently use the free BaseElements Plugin(thanks Goya!) and my example file uses the BaseElements plug-in to demonstrate my approach. Instructions for installing and enabling plug-ins under FileMaker Server can be found in the FileMaker Server v11 Help under “Managing plug-ins”.

- if your database has an OnFirstWindowOpen/startup script or a OnLastWindowClose/close script (as set under the File Options for the file) you might need to modify these depending on your requirements. These scripts will be performed by the server-side script and depending on their compatibility with server side steps and the use of the Allow User Abort script step that may create unexpected results. I typically bypass the startup and close scripts when performed under FileMaker Server by adding the following steps to the top of the script:

If [ PatternCount ( Get (ApplicationVersion); "server") ]
    Exit Script [  ]
Else
... continue with script as normal

- I set a local variable at the top of the actual server-side script that I wish to debug to allow me to enable or disable the logging on the fly:

Set Variable [ $EnableLoggingSQL; Value:1 ]

- as I’m using a plug-in I need to test that the plug-in is installed (and possibly registered and also the correct minimum version if required)

- I first delete all previous entries in my ServerLog table as I’m only interested in the log files for the current script execution (you can bypass this if you wish to keep a history). Here’s where the power of FileMaker’s internal SQL engine kicks in – I don’t need to change layouts, show all records, then delete them and return to the orignal layout. I can simply make one function call as the calculation value for a Set Variable script step (N.B. all examples in this post are using the BaseElements plug-in):

Set Variable [ $serverLogSQL; Case ( $EnableLoggingSQL ; BE_FileMakerSQL ("DELETE FROM ServerLog") ) ]

The function call and syntax will depend on the plug-in you use but the SQL statement will generally be similar. Here the use of  ”DELETE FROM ServerLog” deletes all records in the ServerLog table. Note that I’m wrapping the plug-in call within the Case function which checks whether logging has been enabled (the $serverLogSQL variable is set to either 1 or 0 at the top of the script) – if logging is enabled the plug-in function will be evaluated, otherwise it will be ignored. Be careful when using the SQL Delete command as, unlike FileMaker Pro, you WON’T get a dialog box confirming that you wish to delete the records.

- Adding a single Set Variable script step is usually the maximum that you need to add if you wish to capture and log information about the current state (e.g. by calling one of FileMaker’s functions) or by checking the result of the last script step or retrieving the current value of a variable or field. For example the following Set Variable steps will return information using FileMaker Get Functions:

Set Variable [ $serverLogSQL; Case ( $EnableLoggingSQL ; BE_FileMakerSQL ("INSERT INTO ServerLog(Description) VALUES('Logging Commenced at " &  Get ( CurrentTimeStamp ) & "'" & ")"))]
Set Variable [ $serverLogSQL; Case ( $EnableLoggingSQL ; BE_FileMakerSQL ("INSERT INTO ServerLog(Description) VALUES('Get (AccountName) result " &  Get ( AccountName ) & "'" & ")") )]

- you don’t always necessarily need to add a Set Variable step to create a log entry: anywhere you can access FileMaker’s calculation dialog you can create a log entry. For example you can add a log entry when the Exit Script step is performed as long as you specify a calculation result. I usually decide where in my script I’m going to start debugging and add one or more Set Variable steps at the appropriate places then perform the script manually using the FileMaker Server Admin Console:

 

- when setting up the new Schedule for the server side script in the FileMaker Sever Admin Console you’ll need to specify the Account Name and Password to use when performing the script. Make sure the Account Name and Password has sufficient privileges to perform the required steps. I generally create a new Account for server side scripts with the appropriate privileges. It’s also worth nothing that Get(AccountName) returns the account name that the script was run under and Get(UserName) returns the schedule name.

When it comes to setting up the frequency for the Schedule that you create in the FileMaker Server Admin Console you might be surprised that there’s no option that lets you create a script that runs every x minutes all the time. The limitation is that the start time and end time of a schedule must fall within the same day – there’s no option to tell it to run every day every 5 minutes for example. You can work around this by creating a schedule that starts say at 12:01AM and finishes at 11:59pm if you require a script that runs constantly every 5 minutes.

Whilst debugging I strongly recommend enabling the email notification to get as much information as possible about the execution of the server side script. You can also use the Log Viewer in the FileMaker Server Admin Console to view relevant log entries – these are often helpful as they pinpoint the script step that caused an error. It’s also worth noting that not all errors are actual errors. For example if you’re script involves a Find operation that results in no records found (error #401) this will be captured but might be completely expected. Also if your FileMaker script involves a Loop that uses the  Go to Record/Request/Page [ Next ] step you’ll get an error when it gets to the last record (error #101 – once again this would be expected). You can use the following step immediately above the Go to Record/Request/Page [ Next ] step to bypass this:

Exit Loop If [ Get (FoundCount ) = Get (RecordNumber ) ]

The FileMaker Server Admin Console also allows you to specify some Script Options. You can select Abort schedule if time limit reached or server stopped in the Schedule assistant to abort the FileMaker script schedule if the script takes longer to run than the specified Time limit, or if the Database Server stops:

I’ve created an example file that you can download and pull apart (you’ll need to also download the BaseElements plugin (link below) and install and enable this on FileMaker Server):  ServerLogging.fp7

Here’s a list of the plug-ins I’ve used with my server-side debugging approach:

BaseElements Plugin

SQL Runner

MMQuery

 

Additional Resources:

FileMaker’s Internal SQL Engine, part 1 

Server Side Imports and Exports

FileMaker Server 11 Help

FileMaker Server Event Log Messages

Troubleshooting Errors with FileMaker Server Auto Update plug-ins feature

I’ve been spending a lot of time recently deploying solutions that require plug-ins and having FileMaker Server distribute them automatically to clients via it’s nifty Auto Update feature. Inevitably you will encounter issues for some clients when attempting to download the plug-in: permissions issues with the plug-ins on the server, not having the plug-in in the correct location etc. They are usually easy to resolve once you know what the error is.

When you write a script to download a plug-in you end up calling the FMSAUC_UpdatePlugIn function. This is a function of the AutoUpdate plugin (yes you need to use an existing FileMaker plug-in to download a plug-in), which thankfully by default is always installed by FileMaker Pro/Pro Advanced (there are only 3 functions for this plug-in: one checks the version (used to see if the plug-in is installed), another to find the plug-in you’re after on the FileMaker Server computer, and the third to download the plug-in). Assuming you have the plug-in installed in the correct location on your FileMaker Server with the appropriate permissions set (see the FileMaker Server 11 Guide to Updating Plug-ins for the full details) you’ll end up calling the FMSAUC_UpdatePlugIn function to initiate the download of the plug-in. If successful this function will return 0 like a normal successful script step, and if unsuccessful it will return an error number in the range of -6 to 101.

I like to capture the error number and if necessary display that to the user along with a more human readable error description. There are some custom functions that you can use to return the description for the error code. For example you capture the error code into a variable using the Get (LastError) function and then pass that to the custom function which will return the error description. For example using the custom function linked above ErrorToEnglish ( 101 ) returns “Record is missing” and saves you the trouble of looking up the error code in FileMaker’s help. However when using the FMSAUC_UpdatePlugIn function you won’t able to use this as it has it’s own list of error codes which overlap with existing list of FileMaker error codes. For example error 101 means “The function call from the client computer to the computer running FileMaker Server failed. The server computer might be running a previous version of FileMaker Server.” when returned by the FMSAUC_UpdatePlugIn function but could return ”Record is missing” from the Go to Record/Request/Page script step.

I ended up creating another custom function that you can call when performing the FMSAUC_UpdatePlugIn function that will return the appropriate description for any errors encountered when attempting to download a FileMaker plug-in from FileMaker Server. Note you could also extend the existing ErrorToEnglish custom function to include a 2nd parameter to indicate whether it is a script step or the FMSAUC_UpdatePlugIn you are capturing the error code for, rather than have separate custom functions.

Simple Pagination with the FileMaker PHP API

During one of my sessions at the recent 2010 FileMaker Developer Conference in San Diego I was asked about the pagination/navigation on a search results page that is generated by the FileMaker PHP API. They were referring to the links you might see at the top/bottom of the search results page like this:

First | Previous | Record 21 – 40 of 52 Next | Last

which are generated dynamically and use the equivalent of conditional formatting in FileMaker to display only the necessary elements. For example on the first page of the search results there is no Previous page nor can you go to the First page as you are already on it; likewise with the last page there is no Next page and no Last page, so these should not appear depending on the context of the current page.

I finally found some time to put together a simple example of how you can generate these using the FileMaker PHP API.

As with FileMaker when you perform a search via PHP/Custom Web Publishing you will generate a found set of records (or no matching records). With a large found set of records you might want to present these to the user in chunks, for example you could present 5/10/20 records per page and allow the user to navigate to the next page. This is similar to how most search engines on the web work these days. Google for example defaults to showing 10 results per page. With the FileMaker PHP API you use the setRange() method to request only part of the found set of records by passing in 2 paremeters: the first parameter is the number of records to skip past and the second parameter is the maximum number of records to return.

Say you do a search and you find 52 matching records. Using a $max value of 20 you will get records 1-20 on the first page, records 21 to 40 on the second page, and records 41 to 52 on the third (and last) page. On the first page we are skipping 0 records, on the second page we are skipping 20 records and on the third (and last) page we are skipping 40 records.

Here’s an example of how to use the setRange method:


// Set a Max value. Paging 20 records at a time
$max = 20;
$skip = $_GET['skip'];
if(!isset($skip)) { $skip = 0; }
$request->setRange($skip, $max);

Here I’ve hardcoded the $max value to 20 which means I’ll only ever get back 20 records at the most per page. For the skip value I’m using the $skip variable and if this hasn’t already been set I’m setting it to 0, which is typically done on the first page of search results. Otherwise this will be passed as a parameter in the URL and the php script will check to see if this GET variable exists. Now we need to perform the find and check for a found set of records:

// Perform the Find
$result = $request->execute();
if (FileMaker::isError($result)) {
if ($result->code = 401) {
$errorMessage = "There are no Contacts that match that request: " . ' (' . $result->code . ')';
} else {
$errorMessage = "Contacts Find Error: " . $result->getMessage() . ' (' . $result->code . ')';
}
} else {

If there are matching records we then generate some variables that will be used in the First, Previous, Next and Last links, as well as calculating the number of records found and how many were “fetched” on the current page:

If you use the previous example of 52 matching records here are the values of these variables for each of the 3 pages of search results:

  • Page 1 (records 1-20): $skip = 0, $max = 20, $found = 52, $ fetchcount = 20, $prev = -20, $next = 20, $lastskip =42, $firstrecord = 1
  • Page 2 (records 1-20): $skip = 20, $max = 20, $found = 52, $ fetchcount = 20, $prev = 0, $next = 40, $lastskip =42, $firstrecord = 21
  • Page 3 (records 1-20): $skip = 40, $max = 20, $found = 52, $ fetchcount = 12, $prev = 20, $next = 60, $lastskip =42, $firstrecord = 41

I’m also using a pipe character as a separator between the links as well which is stored in the $sepbar variable. Now we’re ready to generate the links within the HTML part of the php page: Here’s the code for the “First” link:


<?php
if ($skip != 0) {echo '<a href="?skip=0">First</a>'.$sepbar;
}
?>

As we only want to show the First link on every page except for the first page of search results we are checking the value of the $skip variable. If $skip is not equal to 0 then we are not on the first page of search results so we can show this link, along with the pipe character to give it some space between the links.

For the “Previous” link we use:

<?php
if ($prev >= 0) {
echo '<a href="?skip='.$prev.'">Previous</a>'.$sepbar;
}
?>

Here we only want to show the Previous link if there is a previous page of search results, so we can check the contents of the $prev variable which will only equal 0 on the first page of the search results.

For the “Next” link we use:


<?php
if (($skip + $max) < $found) {
echo '<a href="?skip='.$next.'">Next</a>'.$sepbar;
}
?>

Here we need to check that there actually are subsequent pages of search results, which we do by checking that the total of the $skip and $max variables is less than the total found set of records.

Finally for the “Last” link we use:


<?php
if (($skip + $fetchcount) < $found) {
echo '<a href="?skip='.$lastskip.'">Last</a>';
}
?>

Here we need to test that we are not on the last page of the search results which we do by checking that the total of the $skip and $fetchcount variables is less than the total found set of records.

If you want to display the total number of found records along with the records that you are currently viewing (e.g. “Record 21 – 40 of 52″) you can use:


Record <?php echo $firstrecord; ?> - <?php echo $lastrecord; ?> of <?php echo $found; ?>

I’d like to credit Sonja Froyen’s article Custom Web Publishing: Paginate Your Results which I used as a starting point for some of these links (no need to reinvent the wheel here). If you Google “PHP Pagination” there are thousands of other articles on different ways to generate the pagination links, including variations which show how to include the search results page numbers like Google (e.g. “Previous 1 2 3 4 5 6 7 8 9 10 11 Next”. Most of these reference MySQL as the data source but it’s relatively easy to swap the references to the FileMaker PHP API.

As some of this code won’t make sense on it’s own here’s the full php page with the HTML (remember this is a simple page that finds all of the Contacts in the DevCon sample file):

<?php
require_once 'FileMaker.php';
require_once 'connections/INT002.php';

}
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>
FileMaker DevCon INT002 Contacts
</title>
<link rel="stylesheet" type="text/css" media="screen" href="css/glass_grey.css">
<style type="text/css">
form#auth label.error { display: none;
margin-top: 5px;
color: red;}
.appropriateError{
color: red;
}
.emphasise{
color: red;
}
</style>
</head>
<body>
<div id="container">
<!-- HEADER -->
<div id="header">
<h1>
FileMaker DevCon INT002 Contacts
</h1>
</div>
</div>
<table>
<thead>
<tr>
<th>
Customer ID                          </th>
<th>
First Name                            </th>
<th>
Last Name                            </th>
<th>
Country                            </th>
<th>
Phone Mobile                          </th>
</tr>
</thead>
<tbody>
<?php
$recnum = 1;
foreach($result->getRecords() as $contacts_search_row){
$rowclass = ($recnum % 2 == 0) ? "table_row" : "alt_row";
$recid = $contacts_search_row->getRecordId();
$pos = strpos($recid, "RID_!");
if ($pos !== false) {
$recid = substr($recid,0,5) . urlencode(substr($recid,strlen("RID_!")));
}
?>
<tr>
<td><a href='<?php echo "contactdetails.php?recid=$recid";?>'><?php echo nl2br( $contacts_search_row->getField('_kp_ContactID'))?></a></td>
<td>
<?php echo nl2br( $contacts_search_row->getField('NameFirst'))?>                            </td>
<td>
<?php echo nl2br( $contacts_search_row->getField('NameLast'))?>                            </td>
<td>
<?php echo nl2br( $contacts_search_row->getField('Country'))?>                            </td>
<td>
<?php echo nl2br( $contacts_search_row->getField('PhoneMobile'))?>                            </td>
</tr>
<?php $recnum++; } /* foreach record */?>
</tbody>
</table>
</div>
</div>
</body>
</html>

<!– Navigation Menu –>
<?php include_once ‘navigation.php’ ?><!– PAGE BODY –>
<div>
<?php
if ($errorMessage != ”) {
echo $errorMessage;
die;
}
?>
</div>
<div id=”content”>
<h1>
Contacts List                </h1>

Click on the Customer ID to view the full Contact details
<!–  Display record list page navigation controls –>
<div>

<?php
if ($skip != 0) {
echo ‘<a href=”?skip=0″>First</a>’.$sepbar;
}
?>

<?php
if ($prev >= 0) {
echo ‘<a href=”?skip=’.$prev.’”>Previous</a>’.$sepbar;
}
?>

Record <?php echo $firstrecord; ?> – <?php echo $lastrecord; ?> of <?php echo $found; ?>

<?php
if (($skip + $max) < $found) {
echo ‘<a href=”?skip=’.$next.’”>Next</a>’.$sepbar;
}
?>

<?php
if (($skip + $fetchcount) < $found) {
echo ‘<a href=”?skip=’.$lastskip.’”>Last</a>’;
}
?>

$layouts = $fm->listLayouts();
if(FileMaker::isError($layouts)) {
// FileMaker PHP API Error — Alert User.
$errorMessage = “FileMaker PHP Error: ” . $layouts->getMessage();
} else {

// Find all Contact records
$request = $fm->newFindAllCommand(‘WebContacts’);

// Set a Max value. Paging 20 records at a time
$max = 20;

$skip = $_GET['skip'];
if(!isset($skip)) { $skip = 0; }
$request->setRange($skip, $max);

// Perform the Find
$result = $request->execute();

if (FileMaker::isError($result)) {
if ($result->code = 401) {
$errorMessage = “There are no Contacts that match that request: “  . ‘ (‘ . $result->code . ‘)’;
} else {
$errorMessage = “Contacts Find Error: ” . $result->getMessage() . ‘ (‘ . $result->code . ‘)’;
}

} else {

// Get the found records and setup page navigation links
$records = $result->getRecords();
$found = $result->getFoundSetCount();
$fetchcount = $result->getFetchCount();

// $totalpages = ceil($found / $max);

$prev = $skip – $max;
$next = $skip + $max;
if(($skip + $max) > $found) {$next = $skip; }

$lastskip = $found – $max;

$firstrecord = $skip + 1;

if ($fetchcount == $max) {
$lastrecord = (($firstrecord + $fetchcount) – 1);
} else {
$lastrecord = ($skip + $fetchcount);
}

$sepbar = ” | “;

// Get the found records and setup page navigation links
$records = $result->getRecords();
$found = $result->getFoundSetCount();
$fetchcount = $result->getFetchCount();
 
$totalpagesceil = ceil($found / $max);
$totalpagesfloor = floor($found / $max);
 
$prev = $skip – $max;
$next = $skip + $max;
if(($skip + $max) > $found) {$next = $skip; }
  
if($totalpagesceil == $totalpagesfloor) {
$lastskip = ($totalpagesceil – 1) * $max;
} else {
$lastskip = $totalpagesfloor * $max;
}
 
$firstrecord = $skip + 1;
 
if ($fetchcount == $max) {
$lastrecord = (($firstrecord + $fetchcount) – 1);
} else {
$lastrecord = ($skip + $fetchcount);
}
 
$sepbar = ” | “;

}
}

FileMaker Server v11 – What’s New with the FileMaker API for PHP?

Since FileMaker Server v11 was released I’ve been wondering what new features there was as far as the API for PHP was concerned. There hasn’t been any mention of any new features for the API for PHP or the PHP Site Assistant. I did a quick comparison of the API for PHP files between FileMaker Server v10 and FileMaker Server v11:

FileMaker Server v10:

API Version Number 1.1
Minimum FM Server Version Number 10.0.0.0

FileMaker Server v11:

API Version Number 1.1
Minimum FM Server Version Number 10.0.0.0

So it looks like there’s no changes to the PHP API with FileMaker Server v11. I’ll run a diff on them just to be sure and report back if there are any changes.

FYI you can use the following PHP Code to get these details from the API:

php echo $fm->getAPIVersion(); ?>
php echo $fm->getMinServerVersion(); ?>

Databuzz eNews – December 2008 Released

We’ve just released our eNews newsletter for December 2008. You can view it online at:

http://www.databuzz.com.au/enews/enews_122008_generic.html

If you want to be added to the newsletter mailing list just leave a comment below and we’ll add you to the list until our new automated subscription service is operational.

Unable to see hosted files on FileMaker Server

An issue has arisen with installations of FileMaker Pro and FileMaker Server on or after Sept. 22, 2008 using SSL that causes hosted database files to be invisible to workstation computers. If you have installed FileMaker Pro on or after Sept. 22, 2008 and have FileMaker Server set to use SSL you will experience this. FileMaker now have an article in their KnowledgeBase about this with a suggested workaround. There’s also been some discussion about this on fmforums with some other suggestions that you might find more practical, including simply replacing the server.pem file with a known good copy from another workstation in your office that was installed prior to Sept. 22, 2008 or turning off SSL.

Update (October 19, 2003): FileMaker have released a number of “SSL Updaters” that will install a valid SSL certificate file (server.pem). Updaters are available at the FileMaker downloads site. At the time of writing there are the following updates:

 

Not sure if a FileMaker Server 9 update for Windows is necessary at this stage.

FileMaker API for PHP

It’s been over 2 years now since the FileMaker API for PHP public beta was first released, followed by it’s inclusion in FileMaker Server 9 (not Advanced which was a great decision to really get the technology widely adopted). I’ve done a lot of projects this year involving the FileMaker API for PHP to create web interfaces to backend FileMaker 9 databases, as well as upgrading some old .fp5/CDML sites to PHP API. Upgrading an old CDML site is great as you can accomplish so much more with PHP compared to the old proprietary CDML, and more often than not there is a great code snippet that you can reuse on the php.net site or other third party sites. I’ve been able to convert a 20+ page CDML site down to less than 10 pages with PHP, mainly through the use of include pages and variables.

FileMaker Server 9 ships with the PHP Site Assistant, which for anyone who worked with CDML and used the FileMaker Connection Assistant that was part of Claris Home Page, will see as it’s logical successor for the PHP API. It does a good job in creating a site in a matter of minutes (you can choose what type of site you require) and creates the necessary php pages and uses some nice looking CSS. However the more you use php pages generated by the Site Assistant the more problems you are likely to encounter in my experience. The php pages created by the Site Assistant are multi-purposed and have code for a number of requirements that you might not require (e.g. a record details page can be used to view, edit, delete or find). It also makes use of an include file – fmview.php – which is where things get really confusing. This php page has lots of php code to handle lots of different tasks and as you start to extend and customise the pages generated by the Site Assistant you are likely to butt heads with the fmview.php page as you try to understand what it’s trying to do.

Like me you’ll probably find extending pages generated by the Site Assistant problematic if you don’t want to rely on the fmview.php file, which is required for other functions. You quickly get to the point where you need to rewrite the pages from scratch so they don’t rely on the fmview.php page and you can have total control over each page and how it interacts with your FileMaker database. There’s also a few bugs with the php generated by the Site Assistant that you’ll have to deal with (e.g. in the recordlist.php page it creates navigation links for moving from one page to another in your found set of records, but the links overlap. For example it will have Record 1-20 on page 1, then Record 20-40 on page 2, and so on but it should be Record 1-20, Record 21-40 etc.)

Another alternative to generating PHP API pages quickly is FM Studio from fmwebschool. Like the Site Assistant it will generate the necessary PHP code for the PHP API and create your browse, find, edit, delete etc code for you. Like the Site Assistant you will also probably spend some time understanding how and why FM Studio does certain things and getting your head around the include files that are required.

Once your become familiar with the PHP code required you can hopefully get to the point where you can simply write the code yourself into your php editor (I use Dreamweaver). You’ll generally end up with cleaner and more concise code that you understand and can make sense of (don’t forget those comments!) without wondering why someone else did it that way.

Getting started with PHP does takes some time, like learning anything new. Here’s a list of some of the resources that I found useful in getting started with PHP in general and the new PHP API:

six.fried.rice blog article “Up to Speed with the FileMaker PHP API”

FileMaker Inc PHP Web Publishing Overview

Article in PHP Architect Magazine by Jonathan Stark – Part 1

Article in PHP Architect Magazine by Jonathan Stark – Part 2

FileMaker Custom Web Publishing with PHP PDF

VTC Training CD – FileMaker 9 PHP Foundations

jonathanstark.com - Jonathan Stark is the author of the Web Publishing with PHP and FileMaker 9 book

As well as Jonathan Stark’s book there is also another book I found useful that extends the content of Jonathan’s book – FileMaker Web Publishing: A Complete Guide to Using the API for PHP
By Allyson Olm, Stephen Knight, Michael Petrov. Both books come with sample code that you can open in your editor of choice and get hands on as you work your way through the chapters.

Note: as well as FileMaker’s official API for PHP there are some other alternative PHP API’s. Firstly there is FX.PHP which was around for many years before FileMaker’s PHP API was released. There’s also FM and PHP which I haven’t looked at yet.

FileMaker DevCon 2008 Post Mortem

It’s been a few weeks now since I returned from the FileMaker 2008 Developer Conference in Phoenix, Arizona. It was a whirlwind trip this time – there and back in 6 days with lots of jetlag and not much sleep, no thanks to Qantas for cancelling my return flight and delaying my departure. I’ve finally settled back in and can report on some of the highlights from the conference and the product showcase. I spent most of my time attending any PHP related sessions and learnt a lot about the power of PHP in conjunction with the FileMaker PHP API. I’m currently working on a project that is an upgrade from a CDML/FileMaker Unlimited 5 database driven site to a FileMaker Server 9/PHP driven site. There’s lots of new stuff to learn and I’m impressed with the capabilities of PHP compared to CDML. I particularly enjoyed Lance Hallberg’s sessions on the PHP API fundamentals and the advanced features.

The two sessions on using the Web Viewer to interact with your FileMaker tables and as a dynamic interface were both well attended. Both highlighted the power of the MBS plugin and the Fusion Reactor plugin – the amazing Fusion Reactor also won the FileMaker Excellence award for Solution of the Year. Congratulations to Craig and the gang at Digital Fusion for their amazing plugin which is one of the most truly innovative plugins to be released in the last few years.

In the product showcase I ended up buying some new tools and upgrades:

BaseElements 2 – Goya have released their update to v2 of their DDR Analysis tool BaseElements. This is almost a must have for the professional FileMaker Developer. I’m still using both Inspector and BaseElements as each have their strengths but spend most of my time with BaseElements. SixFriedRice were demoing an early released of a web hosted service – FM Lumen - which they promise will provide deeper and faster analysis of the FileMaker DDR. I can’t wait to give that one a try.

ClipManager – My FM Butler have released a beta of v3.0 of their handy tool Clip Manager which allows you to store and manipulate the contents of the FileMaker clipboard. It’s also at present one of the only ways to copy custom functions and you can use it to build up a library of fields, scripts, layouts and other elements that you can quickly add to your solutions. v3.0 is also the first release that runs on Windows as well as the Macintosh.

Web Services Plugin – I already have a developer licence for the amazing Web Services plugin from FM Nexus. This was featured in the opening keynote and FM Nexus released a beta of v2 which makes it easier to load functions on the fly by storing the WSDL file inside a field in your database.

I also bought the VTC PHP Training CD so I can totally immerse myself in the FileMaker API for PHP. I look forward to attending the next DevCon in 2009 in San Francisco – finally a new city and new new hotel!

Plugins, AutoUpate and FileMaker Pro Runtimes

I’ve written previously about the changes to where plugins are downloaded to with FileMaker Pro 9, which now has 2 possible locations for storing plugins:

1 - the FileMaker Pro Extensions folder and;

2 – the user’s Application Data folder

Having the same plugins (but different versions) in both locations can create some plugin management problems for you as the plugins in the user’s Application Data folder take precedence over plugins with the same name in the FileMaker Pro Extensions folder. Today I encounterd a new scenario where this creates problems for the user – a runtime application that also uses plugins created with FileMaker Pro Advanced v9.

I created a runtime using FMPA 9.0v3 (Windows XP) and installed it on a client’s computer, which also had some of the same plugins in the /Application Support/FileMaker/Extensions folder but several of them were older versions used for other FileMaker Pro databases.

This led to several errors with my runtime as it couldn’t register the older versions of the plugin and my runtime was checking for specific versions of the plugin as it uses functions not available in the older versions. Whilst I am a fan of the AutoUpdate feature and the new download location in the user’s Application Data folder it certainly does create problems with interference with runtime applications on the same computer that use the same but different versions of a plugin, which is something we haven’t had to worry about with previous versions of FMP. I’ve reported this to FileMaker Inc as both a product problem and a feature request for this to be addressed in future releases.

If you’re a heavy user of plugins like myself with FileMaker Pro 9 you will be spending more time on plugin management issues and locating the user’s Application Data folder unfortunately. Runtime applications should only be able to reference plugins installed in the runtime application’s Extensions folder like runtime’s created with previous versions of FileMaker Pro.

FileMaker Server and Auto Updating Plugins

As a long time user of as many plugins as I can get my hands on one of my favourite features of FileMaker Server (starting with v5.5 if my memory serves me correctly) is the ability to push plugins to FileMaker Pro and FileMaker Pro Advanced clients automatically from the server using some simple FileMaker Pro scripts. Plugin maintenance was a painful process before this, having to manually install and update new plugin versions on each client workstation.The Auto Update feature is great for:

  1. ensuring all users of your database solution have the plugin installed
  2. distributing plugin updates by making some small changes to the server and having these downloaded automatically
  3. updating plugins without having to restart FileMaker Pro/Advanced!

The documentation for setting up the Auto Update feature is covered in depth in the FileMaker Server 9 Guide to Updating Plug-ins available from the FileMaker website and the FileMaker Server CD. Essentially you need to setup some scripts that you call (typically as part of the on open or startup script) which will download the plugin if it is not installed or update the plugin if an older version of the plugin is installed (if you were to manually update an older version of the plugin you would have to quit FileMaker Pro/Advanced and re-open it if it was already open).

The Auto Update feature has worked in much the same way from Server 5.5 through Server 7, 8 and 9. However there is one small change in FileMaker Pro 9 that has caused some extra plugin maintenance work. FileMaker Pro 9 now has the ability to store plugins in 2 locations. In addition to storing plugins in the Extensions directory within the FileMaker Pro folder, for example on Windows for FileMaker Pro Advanced v9 this would be:

C:\Program Files\FileMaker\FileMaker Pro 9 Advanced\Extensions

 it can also store plugins in the user’s application data directory, which is typically a hidden folder that is not subject to the same access privileges issues as the application directory might be which can cause plugins not be downloaded (the user might not have read/write access to the application directory, for example). The application data directory has different locations for all supported operating systems for FileMaker Pro 9:

  • Windows XP: C:\Document Settings\User Name\Local Settings\ApplicationData\FileMaker\Extensions
  • Windows Vista: C:\Users\User Name\AppData\Local\FileMaker\Extensions
  • Mac OS X: Macintosh HD/Users/User Name/Library/Application Support

Now that you can install plugins in more than one location you will need to learn the new rules about managing plugins in these different locations. For example what happens if you have the same plugin installed in both locations? Which one do you update?

As I encountered these problems within days of FileMaker Pro 9 being released I’ve developed a good understanding of how to manage plugins in both locations and have developed these rules:

  • Any plugin distributed by FileMaker Server (not just Server 9) to a FileMaker Pro 9 client will be downloaded to the user’s application folder. I regularly use FileMaker Pro 9 with FileMaker Server 8 and it is a function of FileMaker Pro 9 not Server 9 that causes the plugins to be downloaded to the user’s application data folder. 
  • If you have the same plugin installed in both locations the one installed in the user’s application data folder takes precedence, even if it is an older version. This can be hard to troubleshoot as the user’s application data folder is typically hidden in my experience so you need to know the location and how to turn on hidden folders so you can find it in the first place.
  • If you are attempting to update a plugin that is installed in both locations it will be downloaded to the user’s application data folder and any older versions will be moved to the Saved folder like normal. However if an older version of the plugin is currently installed in the FileMaker extensions folder you will have to quit/relaunch FileMaker Pro for the newer downloaded version of the plugin to be loaded by FileMaker Pro 9. This is one of the downsides to this new feature, mostly for developers that work with plugins and are used to manually putting them into the FileMaker Pro extensions folder. For most workstations all plugins will be downloaded and updated without incident in the user’s application data folder.

The information about the change to downloading to the user’s application data folder is tucked away in the FileMaker Server 9 readme – in my opinion it would be more appropriate to include it in the FileMaker Pro 9 readme. There’s some useful information about Auto Update and FileMaker Server on the Troi website and the 24u website as well. 

P.S: I needed to locate the user’s application data folder quickly on different workstations so I wrote this script (which uses the Troi File plugin naturally!) to get the location to the user’s application data folder (currently only for Windows XP and Vista, haven’t done a Mac version yet sorry). Haven’t worked out the best way to format scripts in a WordPress blog post so sorry for the formatting – if you know how to do this please let me know!

#This script gets the path to the local application data extensions folder that FileMaker Pro 9 and FileMaker Server 9 use for downloading

plugins automatically

Enter Browse Mode

#First check to see if single user or multi user as paths will be different

If [ Get( MultiUserState) <> 2 ]

#They are single user so just open the local application Extensions folder for the currently running version of FileMaker Pro

Set Variable [ $VarTroiPath; Value:TrFile_Launch( "" ; TrFile_GetPathTo( "-CurrentAppFolder" ) & "Extensions\\" ; ) ]

If [ $VarTroiPath 0 ]

Show Custom Dialog [ Title: "Error - Opening Folder"; Message: "There was an error opening the plugins folder!"; Buttons: OK ]

Exit Script [ ]

End If

Exit Script [ ]

End If

#First need to determine if current user is on Windows XP or Vista as the paths are different

If [ Abs ( GetAsNumber ( Get ( SystemVersion ) = 5.1) ) ]

#It's Windows XP SP 2

Set Variable [ $VarPath1; Value:Right ( ( Get(DesktopPath) ) ; (Length ( Get(DesktopPath) ) - 27)) ]

Set Variable [ $VarPath2; Value:Left ($VarPath1 ; (Length ($VarPath1 ) -9 )) ]

#First check to see if the folder actually exists as it might not yet exist if no plugins have been downloaded to this location yet

Set Variable [ $VarFolderExists; Value:TrFile_Exists( "-Unused" ; "C:\Documents and Settings\\" & $VarPath2 & "\Local

Settings\Application Data\FileMaker\Extensions\\" ) ]

#Will return 0 if it doesn't exist otherwise will return 1

If [ $VarFolderExists = 0 ]

#Doesn't exist so just open local FileMaker Pro extensions folder instead

Set Variable [ $VarTroiPath; Value:TrFile_Launch( "" ; TrFile_GetPathTo( "-CurrentAppFolder" ) & "Extensions\\" ; ) ]

Else

#Does exist so open that one

Set Variable [ $VarTroiPath; Value:TrFile_Launch( "" ; "C:\Documents and Settings\\" & $VarPath2 & "\Local Settings\Application

Data\FileMaker\Extensions\\" ; ) ]

End If

If [ $VarTroiPath 0 ]

Show Custom Dialog [ Title: "Error - Opening Folder"; Message: "There was an error opening the plugins folder!"; Buttons: OK ]

Exit Script [ ]

End If

Else If [ Abs ( GetAsNumber ( Get ( SystemVersion ) = 6) ) ]

#It's Windows Vista

Set Variable [ $VarPath1; Value:Right ( ( Get(DesktopPath) ) ; (Length ( Get(DesktopPath) ) - 10)) ]

Set Variable [ $VarPath2; Value:Left ($VarPath1 ; (Length ($VarPath1 ) -9 )) ]

#First check to see if the folder actually exists as it might not yet exist if no plugins have been downloaded to this location yet

Set Variable [ $VarFolderExists; Value:TrFile_Exists( "-Unused" ; "C:\Users\\" & $VarPath2 &

"\AppData\Local\FileMaker\Extensions\\" ) ]

#Will return 0 if it doesn't exist otherwise will return 1

If [ $VarFolderExists = 0 ]

#Doesn't exist so just open local FileMaker Pro extensions folder instead

Set Variable [ $VarTroiPath; Value:TrFile_Launch( "" ; TrFile_GetPathTo( "-CurrentAppFolder" ) & "Extensions\\" ; ) ]

Else

#Does exist so open that one

Set Variable [ $VarTroiPath; Value:TrFile_Launch( "" ; "C:\Users\\" & $VarPath2 & "\AppData\Local\FileMaker\Extensions\\" ; ) ]

End If

If [ $VarTroiPath 0 ]

Show Custom Dialog [ Title: "Error - Opening Folder"; Message: "There was an error opening the plugins folder!"; Buttons: OK ]

Exit Script [ ]

End If

End If

Commit Records/Requests

© 2011 Databuzz