fmAccounting Link (Xero Edition) Customers Map

Every now and then I like to generate a map and see where in the world our customers are located. We’ve shared some maps of where our fmSMS Customers are located and I’ve just generated a map for our fmAccounting Link (Xero Edition) customers. Xero currently reports that it has over 600,000 subscribers in more than 180 countries, however these 4 countries/regions represent their largest customer base:

  • Australia
  • New Zealand
  • UK
  • North America

Xero will be announcing their annual results next month, but we know that as of 30 September, 2015 these countries/regions had the following subscribers:

  • Australia: 262,000
  • New Zealand: 163,000
  • UK: 102,000
  • North America: 47,000

Xero UK total subscribers recently overtook Sage 50, the UK’s #1 desktop accounting software product for the past 30 years. Australia and New Zealand is seeing subscriber growth of over 50% and North America is their fastest growing region.

It came as no surprise to see that our fmAccounting Link (Xero Edition) customers reflect these Xero numbers – as you can see in the following map all fmAccounting Link (Xero Edition) users are based in the four main Xero target markets:

fmXERO Customers April 2016

It will be interesting to see what happens over the next 12 months – based on Xero’s growth we’ll see more Australia, New Zealand, UK and North American customers, but we’re also expecting to see some interest from other countries that Xero is actively targeting such as Asia where Xero did it’s first ever Roadshow in February.

Databuzz releases fmAccounting Link (MYOB AccountRight Edition) – Integrate FileMaker Pro and MYOB AccountRight Accounting Software

Sydney, Australia – April 12, 2016 – Databuzz today announced fmAccounting Link (MYOB AccountRight Edition), a FileMaker solution that integrates with the MYOB AccountRight Accounting Software.

fmAccounting Link (MYOB AccountRight Edition) allows you to upload and download data between your FileMaker solution and MYOB AccountRight, the powerful accounting software with business management capabilities that allows you to work off or online. fmAccounting Link (MYOB AccountRight Edition) removes double data entry and human errors saving your company significant time, money and hassle by automating the exchange of data between FileMaker and MYOB AccountRight.

fmAccounting Link (MYOB AccountRight Edition) is completely unlocked allowing you to integrate it into your FileMaker solution. You can copy and paste examples showing you how to authenticate with the MYOB AccountRight API and upload Contacts, Invoices, Payments and more at the click of a button.

fmAccounting Link (MYOB AccountRight Edition) features include:

  • works with FileMaker Pro v12, v13 and v14
  • completely unlocked
  • can be hosted by FileMaker Pro or FileMaker Server
  • works with Macintosh and Windows
  • works with MYOB AccountRight running in the Cloud or on the Desktop (online and offline)
  • works with MYOB AccountRight Live 2013, 2014, 2015 and 2016

“Previous integrations between FileMaker and MYOB AccountRight have involved manual exports and imports of multiple text files or a Windows only ODBC connection,” said Andrew Duncan, Director of Databuzz. “These are now a thing of the past – with fmAccounting Link (MYOB AccountRight Edition) you can push and pull data between FileMaker and MYOB AccountRight at the click of a button.”

fmAccounting Link (MYOB AccountRight Edition) includes examples for the following MYOB AccountRight API endpoints:

  • Company Files: select from all available MYOB AccountRight Company Files that you have access to
  • Contacts: download and upload Contacts (Customers and Suppliers)
  • Invoices: download and upload Invoices (including Invoice line items)
  • Items (Products): download and upload Items (Products price list)
  • Payments: download and upload Payments against an Invoice
  • Employees: download and upload Employees
  • Account Codes: download Account Codes from MYOB AccountRight
  • Tax Codes: download Tax Codes from MYOB AccountRight
  • Categories: download Categories from MYOB AccountRight

Availability, Pricing, and Compatibility

fmAccounting Link is available in a number of licenses: Company, Vertical Solution and Developer. It is available now from the Databuzz website at http://www.databuzz.com.au/fmaccounting-link-myob-accountright-edition/. Company Licenses start at AUD $495.00. fmAccounting Link (MYOB AccountRight Edition) requires FileMaker Pro v12, v13 or v14 and MYOB AccountRight Live 2013, 2014, 2015 or 2016.

Media/Customer Contact:

Andrew Duncan

Phone: +61 418 468 103

sales@databuzz.com.au

http://www.databuzz.com.au

About Databuzz: Databuzz is a long standing member of the FileMaker Business Alliance. We have been developing and deploying FileMaker solutions for clients in Australia and internationally since 1999. Our clients are individuals, small-medium businesses, government agencies and multi-national corporations. Databuzz was founded by Andrew Duncan, a Certified FileMaker 14 Developer. For more information please visit our website at http://www.databuzz.com.au.

###

FileMaker is a trademark of FileMaker, Inc., registered in the U.S. and other countries. All other trademarks are the property of their respective owners.

fmAccounting Link (MYOB AccountRight Edition) Preview Video

We’ve just uploaded our first preview video for fmAccounting Link (MYOB AccountRight Edition). This video demonstrates the following:

  • authenticating against the MYOB AccountRight API
  • downloading a list of available AccountRight Company Files
  • selecting the AccountRight Company File and entering the credentials for the selected Company File
  • uploading a Contact from FileMaker Pro to AccountRight
  • uploading an Invoice from FileMaker Pro to AccountRight
  • uploading a Payment from FileMaker Pro to AccountRight
  • downloading Chart of Accounts, Tax Codes, Categories and Inventory Items from AccountRight to FileMaker

The video also demonstrates how you can integrate with MYOB AccountRight (a Windows only application) from a Mac OS X computer.

You can watch the video below or directly on YouTube via this link.

We should be releasing fmAccounting Link (MYOB AccountRight Edition) in the next couple of weeks – please Contact Us if you have any questions in the meantime.

North West Sydney FileMaker Developer Meetup Dates for 2016

The dates for the North West Sydney FileMaker Developer Meetups for the rest of 2016 have been locked in:

June 17

September 16

December 9

Venue: Pennant Hills Bowling Club (short walk from Pennant Hills train station)
Time: 12.30pm

If you would like to join the mailing list just visit the signup page at:

http://databuzz.us12.list-manage.com/subscribe?u=366d1a87399a120a9d438cb56&id=8bb1fea366

We’ll send our reminders before each meeting – anyone is welcome to attend and no RSVP is required.

FileMaker PHP API Layout Tips

Over the past few months we’ve been working on a large FileMaker PHP Project for a client that required a web based interface to their FileMaker solution that worked on smartphones and tablets (both iOS and Android),  as well as the traditional desktops (Mac and Windows). The web interface was for users who were out of the office for large amounts of the week but needed to access the office solution from their car, client meetings or at home.

We’ve done many FileMaker PHP projects since the PHP API was first released in 2007 but this was by far our largest. Having worked closely with the PHP API for many months we’ve picked up a few tips and tricks along the way that we wanted to share, starting with Layouts.

If you’re not familiar with FileMaker’s PHP API the way the API interacts with your database is via FileMaker layouts – if you wish to find, edit, create or delete a record you need to specify the layout to use. Specifying the layout establishes the context for the query. It’s also important to note that everything on the layout is returned when performing a API command such as finding a record – this is why best practise has always been to only included the fields required by the PHP pages. The XML data that is returned by the API is quite verbose so you want to keep this to an absolute minimum as it can have significant performance implications if you don’t optimise your layouts for the API.

The following are some tips that you should be aware of when working with FileMaker Layouts and the PHP API:

Watch out for hidden fields not visible on the layout

In the screenshot below you can see there are only 5 fields on the ‘ContactsDetailsWeb’ layout: Title, First, Last, Initial and Name:

ContactsDetailsWeb

If we use the PHP API to request all the fields on that layout and echo this back to the browser:

$layout = $fm->getLayout('ContactsDetailsWeb');
// Get an associative array with the names of all fields as keys and FileMaker_Field objects as the array values
$layoutFields = $layout->getFields();
echo '<p><pre>'.print_r ($layoutFields).'</pre></p>';

we get the following:

Array(
 [Title] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => Title[_autoEntered] => [_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => normal[_valueList] => [_styleType] => [_maxCharacters] => 0)) [First] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => First[_autoEntered] => 1[_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => normal[_valueList] => [_styleType] => [_maxCharacters] => 0)) [Last] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => Last[_autoEntered] => [_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => normal[_valueList] => [_styleType] => [_maxCharacters] => 0)) [Initial] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => Initial[_autoEntered] => 1[_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => calculation[_valueList] => [_styleType] => [_maxCharacters] => 0)) [Name] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => Name[_autoEntered] => [_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => calculation[_valueList] => [_styleType] => [_maxCharacters] => 0)) [Mobile] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => Mobile[_autoEntered] => [_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => normal[_valueList] => [_styleType] => [_maxCharacters] => 0)) [OfficeEmail] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => OfficeEmail[_autoEntered] => [_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => normal[_valueList] => [_styleType] => [_maxCharacters] => 0)) [OfficePhone] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => OfficePhone[_autoEntered] => [_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => normal[_valueList] => [_styleType] => [_maxCharacters] => 0)) [Fax] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => Fax[_autoEntered] => [_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => normal[_valueList] => [_styleType] => [_maxCharacters] => 0)) [PersonalEmail] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => PersonalEmail[_autoEntered] => [_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => normal[_valueList] => [_styleType] => [_maxCharacters] => 0)) [PersonalPhone] => FileMaker_FieldObject([_impl] => FileMaker_Field_ImplementationObject([_layout] => FileMaker_LayoutObject([_impl] => FileMaker_Layout_ImplementationObject([_fm] => FileMaker_ImplementationObject([V73ee434e] => Array(
 [charset] => UTF - 8[locale] => en[logLevel] => 3[hostspec] => 127.0.0.1[recordClass] => FileMaker_Record[prevalidate] => [database] => ContactsStarterSolution[username] => Admin[password] =>
 ) [Vea4b3413] => [V9a3dcbce] =>) [_name] => ContactsDetailsWeb[_fields] => Array * RECURSION * [_relatedSets] => Array() [_valueLists] => Array() [Vab234ad8] => Array() [_database] => ContactsStarterSolution[_extended] =>)) [_name] => PersonalPhone[_autoEntered] => [_global] => [_maxRepeat] => 1[_validationMask] => 0[_validationRules] => Array() [_result] => text[_type] => normal[_valueList] => [_styleType] => [_maxCharacters] => 0))
 )

As you can see the result is quite verbose and includes some additional fields that you can’t see on the layout: Mobile, OfficeEmail, OfficePhone, Fax, PersonalEmail and PersonalPhone. So how does the PHP API see these fields? Let’s have a look at the same layout in Layout mode:

ContactsDetailsWeb Layout Mode

You can see these fields are hidden off to the right of the layout’s visible boundary and don’t appear in Browse mode using the FileMaker Pro client, but the PHP API sees all fields on the layout including the hidden fields. It’s advisable to not only have PHP specific layouts that contain just the fields you need for the PHP pages but don’t park/hide other fields off the edge of the layout. The PHP API will retrieve them as well and add additional overhead to your queries causing pages to take longer to load.

This only applies to those using FileMaker Pro/Server v12 or above – the ability to set a layout width was introduced in FileMaker Pro v12.

Beware of Layout Folder Names

We encountered an issue that caused quite a few hours of troubleshooting to resolve but seems obvious in hindsight. Here’s a screenshot showing a list of layouts in a FileMaker database:

List of Layouts

We had a PHP page that interacted with the ‘ContactsPHP’ layout – it would find records, edit records, create records etc and had been working fine for weeks without any issues when all of a sudden it stopped working one day. We ran multiple tests, double checked the spelling of the layout names, checked privileges etc but couldn’t understand what had happened.

We used the API to list out all the layouts in the database and echo this back to the browser:

$layout = $fm->getLayout('ContactsDetailsWeb');
$layouts = $fm->listLayouts();
echo '<p><pre>'.print_r ($layouts).'</pre></p>';

This returned the following array showing the ‘ContactsPHP’ layout:

Array(
 [0] => StartupScreen[1] => - [2] => Contacts[3] => ContactDetails[4] => Contacts | iPad[5] => ContactDetails | iPad[6] => Contacts | iPhone[7] => ContactDetails | iPhone[8] => Contacts | Web[9] => ContactDetails | Web[10] => ContactsDetailsWeb[11] => - [12] => Labels[13] => ContactList[14] => - [15] => ContactsPHP[16] => [17] => [18] => [19] => [20] => [21] => [22] => [23] => [24] => [25] =>
 )

Once again we couldn’t spot any issues with the layouts – the ‘ContactsPHP’ layout was amongst the list of layouts returned.

We then decided to rename the layout, update the PHP page and run some tests and it started working again. We renamed it back to ‘ContactsPHP’ and it failed immediately. Finally the penny dropped – we had a layout folder with exactly the same name that appear above the layout in the list of layouts. We tried renaming the layout folder and voila it started working again. It seems that for certain commands having a layout folder with the same name as the layout works fine, but there are times when it will cause the API to fail. We haven’t been able to isolate the specific circumstances yet but the safest approach is to simply avoid having layout folders with the same names as actual layouts entirely – remember that layout folders are special layout types and it appears that the PHP API can still interact with them when they share the same name as actual layouts.

We’ve run a number of tests and have been able to reproduce this many times on a sample file. We’ve found that if you’re checking for a 401 ‘no records found’ error with a find command like this:

if (FileMaker::isError($result)) {
    if ($result->code = 401) {
    $findError = $result->getMessage(). ' (' . $result->code . ')</p>';
    } else {
    $findError = $result->getMessage(). ' (' . $result->code . ')</p>';
    }
}

you will be mislead into thinking there was a real 401 ‘no records found’. If you examine the FileMaker_Error Object you should see it’s returning a 102 error:

[code] => 102

which is “Field is missing” and makes more sense if it’s using the Layout Folder instead of the actual Layout with the same name (we’ve also seen other instances where the API returns a misleading 401 error, such as when the XML returned is too large for the PHP XML  parser to handle – another reason to carefully optimise your PHP layouts). We first noticed this when we had a Layout Folder named ‘Websites’ and another layout used for a PHP find command called ‘WebSites’, but we have been able to reproduce this with other names as well.

Find Commands and the setResultLayout method

As we’ve discussed it’s ideal to optimise your FileMaker layouts used for the PHP API to only have the required fields on the layout necessary for the particular command, such as creating a new record or performing a find. It’s also possible to further optimise your queries to use separate layouts for the find command and the find results. For example you might have a form on your website that allows users to search for contact records by first name and last name only, however the PHP page is using a layout that has 25 fields from the Contacts table as you using the one Contacts layout for all PHP requests. For smaller record sets you can probably get away with this, but if you would like to optimise this further you can create a layout just for the find command with the 2 fields that you can search on and then have a separate layout that is used to display the find results, which might only require 6 fields for first name, last name, company, email, phone and mobile.

A typical PHP API find command that uses the one layout for both the find request and the find results looks like this:

$request = $fm->newFindCommand('ContactsDetailsWeb');
$request->addFindCriterion('FirstName', 'John');
$result = $request->execute();
if (FileMaker::isError($result)) {
    if ($result->code = 401) {
    $findError = 'There are no Records that match that request: '. ' (' . $result->code . ')';
    } else {
    $findError = 'Find Error: '. $result->getMessage(). ' (' . $result->code . ')';
    }
} else {
$records = $result->getRecords();
}

Here we are performing a find command on the ContactsDetailsWeb layout for any records that have a FirstName that equals ‘John’. We are then checking for any errors with the find command – if there are no matching records it will return a 401 error code, otherwise it will return another find error. If there is no error we are then retrieving all the found records.

To modify the find request to also use a different layout for the find results (to reduce the amount of XML data returned by the API by specifying a layout with just the fields required to show the search results) would look like this:

$request = $fm->newFindCommand('ContactsDetailsWeb');
$request->addFindCriterion('FirstName', 'John');
$request->setResultLayout( 'ContactsSearchResults' );
$result = $request->execute();
if (FileMaker::isError($result)) {
    if ($result->code = 401) {
    $findError = 'There are no Records that match that request: '. ' (' . $result->code . ')';
    } else {
    $findError = 'Find Error: '. $result->getMessage(). ' (' . $result->code . ')';
    }
} else {
$records = $result->getRecords();
}

The only difference between the 2 examples is the addition of this line that uses the setResultLayout method :

$request->setResultLayout( 'ContactsSearchResults' );

The setResultLayout method requests that the command’s result be returned in a layout different from the current layout. This certainly helps speed up the display of search results, however it does have one side effect. When you use the setResultLayout method as part of your find command and there are find errors (such as no records found) the API no longer returns a FileMaker_Error Object but instead returns a FileMaker_Result Object. This is a subtle but important difference – it means you can no longer simply trap for any find errors by calling:

if (FileMaker::isError($result)) {

as you will not get a FileMaker_Error Object. You can check for the number of matching records found, e.g.:

$found = $result->getFoundSetCount();

but it is certainly not as neat as simply checking for a FileMaker_Error Object.

I had trouble finding out more information about the setResultLayout method and ended up submitting a bug report with FileMaker Inc. The response they came back with suggests this is a known limitation when using the setResultLayout method. It would be great if this could be addressed in a future release of the PHP API.

(N.B. all references are to FileMaker Pro/FileMaker Server v14 which was the current shipping version at the time this article was written)

A Beginner’s Guide to Working with Lists in FileMaker Pro

As you become more familiar with FileMaker Pro and make the leap from beginner to intermediate developer you will inevitably become accustomed to working with lists. By list I’m referring to a series of values separated by carriage returns such as

apple
banana
pear
mango

The list might be referencing a series of repeating fields, some related fields from another table, or it might be a series of values that you concatenate manually to achieve the desired result. You might use your list in a script as part of a loop that iterates through the list and performs actions for each value in the list, such as creating a new record or sending an email. You might be creating a list of delimited data to use in a chart or you might be generating a list to use as a match field in a relationship (see below for more details).

List Related Functions

FileMaker Pro has a number of native calculation functions to help you generate lists and extract values from a list:

List ( field { ; field…} ) – the list function was originally introduced with FileMaker Pro 8.5 (there hasn’t been a .5 release since) and as it’s name suggests its sole purpose is to generate a list of values.

The field reference can be any related field, repeating field, or set of non-repeating fields; an expression that returns a field, repeating field, or a set of non-repeating fields, or a variable. For example you might wish to generate a list of all the Invoice Numbers for a particular Contact record. Assuming you have a table occurrence named Invoices that is related to Contacts by a Contact ID match field the following calculation:

List ( Invoices::InvoiceNumber )

would return the list of Invoice Numbers for the current customer record. You can mix and match field references, variables and literal strings – for example:

List ( "INV1056" ; Invoices::InvoiceNumber ; $invoiceID )

It’s important to note that the List function ignores blank values – List ( “apple” ; “” ; “banana” )  would return:

apple
banana

ValueCount – this returns a count of the total number of values in specified list. For example ValueCount ( List ( “apple” ; “banana” ; “orange” ) ) returns 3.

LeftValues ( text; numberOfValues)  – this returns the first numberOfValues from the specified list. N.B. the resulting list of values returned always ends with a carriage return. For example LeftValues ( List ( “apple” ; “banana” ; “orange” ) ; 1 ) returns:

apple¶

RightValues ( text; numberOfValues ) – this returns the last numberOfValues from the specified list. N.B. the resulting list of values returned always ends with a carriage return. For example RightValues ( List ( “apple” ; “banana” ; “orange” ) ; 1 ) returns:

orange¶

MiddleValues( text ; startingValue ; numberOfValues)  – this returns the middle numberOfValues from the specified list, starting at startingValue. N.B. the resulting list of values returned always ends with a carriage return. For example MiddleValues ( List ( “apple” ; “banana” ; “orange” ) ; 2 ; 2 ) returns:

banana
orange¶

FilterValues ( textToFilter ; filterValues ) – this returns all the items in textToFilter that are also in filterValues, in the order they were originally entered in textToFilter. This allows you to compare two lists to find the values they both have in common. N.B. the resulting list of values returned always ends with a carriage return. For example FilterValues ( List ( “apple” ; “banana” ; “orange” ) ; “banana¶orange” ) returns:

banana
orange¶

GetValue ( listOfValues ; valueNumber )  – this allows you to retrieve a specified value from a list of values, typically used when you are looping through a list and performing some actions for each value in the list. N.B. the value returned does NOT end with a carriage return. For example GetValue ( List ( “apple” ; “banana” ; “orange” ) ; 2 )returns:

banana

Multi-Key fields

One of the more common uses for lists mentioned above was for use as a match field in a relationship. Most relationships typically use a single field/value on both sides of the relationship. For example the Company ID field in the Companies table (primary key) matches the Company ID field in the Users table (foreign key). FileMaker Pro also lets you enter mutliple values into the same field which has the effect of increasing the number of possible matching values on the other side of the relationship. You simply enter the values separated by carriage returns and FileMaker will look for matches for every line/value you have entered.

If you entered the following values into a text field (you would typically use a text field with global storage):

C1045
C2784
C3698
C1077

FileMaker Pro will then look for any matching records for each of these 4 values. Multi-key fields can be a very powerful feature of FileMaker Pro and are also often referred to as multi-line keys.

Generating a list of values from a field in a found set of records

One of my favourite new features of FileMaker Pro v13 was the new “List of” option when creating a Summary field. This option creates a return-delimited list of non-blank values in specified field for the current found set of records. One obvious purpose of this function is to create a list to use for a Multi-key field – you can’t use a Summary field itself as the match field in a relationship but you can use the result it generates in a global or calculation field.

I would also recommend reading the fileMakerhacks series on using Summary list fields in relationships.

Custom Functions and Plug-in Functions

There will be times where you need to manipulate lists and go beyond the native FileMaker functions – for example you might want to compare two lists and return all the values that are different in both lists, sort the list of values, or you might want to remove any duplicate values from a list. Here’s some of the custom functions and external plug-in functions that I use on a regular basis:

SortList ( ValueList ; Sort ; Type ) – this custom function allows you to sort a list with options for ascending or descending order

XORvalues ( ListA ; ListB ) – this custom function returns all lines that are different in two lists. If you only specify one list it will also eliminate duplicates from the list and return a single instance of each value

ZapValues ( ListA ; ListB ) – this custom function will compare two lists and remove the items in List B from List A (this is the inverse of the native FilterValues function)

Trim4 ( text ) – if you are using the native functions that also return a trailing carriage return you can use this custom function to remove this at the same time

AddRemoveListItem ( theList ; value ) – this custom function will add an item to a list if it does not already exist; otherwise the item is removed from the list

There will be times when you are not able to use a custom function due to the limitations of custom functions – recursive custom functions are limited to either 10,000 interactions or 50,000 iterations depending on the style of recursion they use (this article has more details on the limitations). When you hit these limitations you will need to use a plug-in function which are not bound by the same limitations as custom functions. Databuzz is a proud sponsor of the open source BaseElements plug-in which has a number of handy list related functions including:

BE_Values_Unique ( listOfValues {; caseSensitive } ) – this removes any duplicate values from the specified list

BE_Values_Sort  ( listOfValues ) – this sorts the list in alphanumeric order

BE_Values_FilterOut ( textToFilter ; filterValues {; caseSensitive } ) – similar to the ZapValues custom function, this will compare two lists and remove items from the textToFilter list that are found in the filterValues list
(N.B. all references are to FileMaker Pro v14 which was the current shipping version at the time this article was written)

Simple FileMaker Server Monitoring

If you’re deploying mission critical FileMaker solutions hosted by FileMaker Server then monitoring the state of your databases and servers is an important part of ensuring everything is running smoothly. Server monitoring is something that’s normally managed by the IT department using dedicated monitoring tools and services to keep an eye on everything, however if you don’t have a dedicated IT department but still need to monitor the uptime of your FileMaker Server databases you will need to implement your own custom monitoring solution.

FileMaker Server has the ability to send email notifications to a nominated email address when errors are logged or when either warnings or errors are logged. However if you’re using web publishing it’s important to note that FileMaker Server sends no email notifications for web publishing errors or warnings. If you need to monitor your web publishing service or would like to do some custom monitoring to check that a particular database is currently hosted then you will need to implement your own monitoring solution.

There’s a number of commercial monitoring services – I’ve used Pingdom and Monitis – which will check for a response from a particular URL and notify you via email/SMS when it encounters an error. You can also tell it what content to expect for a successful result, rather than just relying on a generic HTTP 200 server response. With a bit of PHP code and FileMaker’s PHP API you can quickly setup a custom PHP page to check that the web publishing service is running or that a particular database is currently being hosted, and output a success or error message. You will need to deploy and enable Custom Web Publishing with PHP on your FileMaker Server first, and know where to find the web server root folder on your FileMaker Server machine:

  • on Mac OS X you can find this at /Library/FileMaker Server/HTTPServer/htdocs (or /Library/FileMaker Server/HTTPServer/htdocs/httpsRoot  if you have enabled HTTPS/SSL)
  • on Windows you can find this at [drive]:\Program Files\FileMaker\FileMaker Server\HTTPServer\Conf where [drive] is the drive on which the Web Publishing Engine component of your FileMaker server deployment resides.

Creating the PHP Page:

Using your favourite text editor create a file with the .php extension as follows:

<?php

// Include FileMaker API
require_once ('FileMaker.php');

$fm = new FileMaker();

$fm->setProperty('hostspec', '127.0.0.1'); 

$listDatabases = $fm->listDatabases();

if(FileMaker::isError($listDatabases)) {
 $connectionError = 'Server Error: '. $listDatabases->getMessage(). ' (' . $listDatabases->code . ')';
 echo $connectionError;
} else {
 $connectionError = '';
 echo 'Server Connection Successful';
}

?>

This simply makes a connection to the FileMaker Server (you can change the 127.0.0.1 hostspec address if required) and calls the PHP API listDatabases method – this returns an array of databases that are available with the current server settings and the current user name and password credentials. You will notice that I have not included a FileMaker database Account Name and Password – this will only work when the setting in the FileMaker Server Admin Console List only the databases each user is authorized to access is NOT selected (found under Database Server > Security > File Display Filter).

File Display Filter

We would generally recommend that this is enabled – however this will break our PHP code which will now return an error (401 Unauthorized). We now need to include some account credentials for the database you wish to monitor – I would recommend creating a new Privilege Set/Account in your FileMaker Database just for this purpose with very limited privileges as we won’t be using it to view or create records, but simply to check that the file is being hosted (don’t forget to enable the PHP extended privileges for this Privilege Set).

The PHP code would then look like this (using an Account Name of PHPWeb and Password W3bOnly):

<?php

// Include FileMaker API
require_once ('FileMaker.php');

$fm = new FileMaker();

$fm->setProperty('hostspec', '127.0.0.1'); 
$fm->setProperty('username', 'PHPWeb'); 
$fm->setProperty('password', 'W3bOnly');

$listDatabases = $fm->listDatabases();

if(FileMaker::isError($listDatabases)) {
 $connectionError = 'Server Error: '. $listDatabases->getMessage(). ' (' . $listDatabases->code . ')';
 echo $connectionError;
} else {
 $connectionError = '';
 echo 'Server Connection Successful';
}

?>

If you would like to extend this to check whether a particular database is currently being hosted you can search the array of database names that is returned by the listDatabases method for the presence of a particular file. You can see what the listDatabases array looks like by adding the following line:

echo '<p><pre>'.print_r ($listDatabases).'</pre></p>';

We use the PHP in_array function which checks if a value exists in an array like this:

if (in_array('Contacts', $listDatabases)) {
 echo 'Contacts Database is Live';
} else {
 echo 'Contacts Database is NOT Live';
}

Here I am checking for a database named Contacts – if it is part of the array of databases it will return the string Contacts Database is Live, otherwise it will return Contacts Database is NOT Live.

Here’s the complete PHP code which checks for the individual database name:

<?php

// Include FileMaker API
require_once ('FileMaker.php');

$fm = new FileMaker();

$fm->setProperty('hostspec', '127.0.0.1'); 
$fm->setProperty('username', 'PHPWeb'); 
$fm->setProperty('password', 'W3bOnly');

$listDatabases = $fm->listDatabases();

if(FileMaker::isError($listDatabases)) {
 $connectionError = 'Server Error: '. $listDatabases->getMessage(). ' (' . $listDatabases->code . ')';
 echo $connectionError;
} else {
 $connectionError = '';
 //echo '<p><pre>'.print_r ($listDatabases).'</pre></p>';
 //echo 'Server Connection Successful';
 
 if (in_array('Contacts', $listDatabases)) {
 echo 'Contacts Database is Live';
 } else {
 echo 'Contacts Database is NOT Live';
 }
 
}

?>

N.F. If the Web Publishing Engine is not running on your FileMaker Server deployment you will get a 503 Service Unavailable error.

You can get more information about Custom Web Publishing with PHP from the FileMaker Server 14 Custom Web Publishing Guide.

FileMaker Commercial Hosting Changes

FileMaker Inc. have recently released an updated version of the FileMaker Commercial Hosting FAQ. FileMaker Commercial Hosting involves the provision of FileMaker Server from a data centre via the Internet, typically on a rental or subscription basis. There are many FileMaker Commercial Hosting providers around the world that provide an alternative to deploying FileMaker Server within your organisation. FileMaker Commercial Hosting is currently supported with the current version of FileMaker Server – v14 – on the Volume License Agreement (VLA) and Annual Volume License Agreement (AVLA) license programs (as well as the Solution Bundle Agreement (SBA) for vertical solutions).

FileMaker Inc. have announced that they will be changing the FileMaker Server End User License Agreement (EULA) to require commercial hosting providers to acquire a dedicated license for each customer. This means that commercial hosting providers will no longer be able to offer a “shared server” hosting option where multiple customers database files are stored on the same FileMaker Server for future versions of FileMaker Server.

The can read the full FileMaker Commercial Hosting FAQ here. For further details on performance management best practices on the FileMaker platform click here.

North West Sydney FileMaker Developer March Meetup

Databuzz has been organising an informal gathering of Sydney based FileMaker developers for the past few years – we  catch up over lunch at the Pennant Hills Bowling Club in north west Sydney 3-4 times per year. It started as an informal lunch between a number of developers who live within a few suburbs of each other (and the majority were named Andrew). We’ve since spread the word and called our gathering the the North West Sydney FileMaker Developer Meetup.

We don’t have a website and there’s no formal presentations – we sit around the table over a meal and a few drinks discussing all things FileMaker. We’ve recently setup a mailing list so you can be notified of upcoming meetings – we’re planning on setting the dates for the rest of 2016 in the next few weeks so everyone can put these into their diaries. If you would like to join the mailing list here’s the signup form.

The first meetup for 2016 will be happening in March where we will be discussing FileMaker’s new iOS App SDK.

Here’s the details:

Date: Friday, 18 March 2016
Venue: Pennant Hills Bowling Club (short walk from Pennant Hills train station)
Time: 12.30pm

Anyone is welcome to attend – no RSVP required.

FileMaker Inc. releases State of the Custom App Report

FileMaker Inc. today released their State of the Custom App Report –  a survey of custom app usage and results. After surveying over 490 FileMaker customers internationally in November/December 2015 they found that teams are building and using custom apps to achieve a meaningful impact for their organisations. The Key Findings included:

  • 74% saw an increase in productivity
  • 81% saw a reduction in inefficient tasks
  • 60% saw a return on investment
  • 73% consider mobility moderately to extremely important
  • 82% built internally and 52% built in less than 3 months

Custom apps are changing the way teams work – Databuzz has helped many organisations to plan, create and deploy a custom app using FileMaker Go for the iPhone and iPad in a wide variety of industries. Customers love to automate inefficient processes and reduce unnecessary paperwork and double data entry, boosting the productivity of their teams.

You can download a copy of the report here.

FileMaker Inc. has also recently released the first in a three-part series of free how-to guides that will lead teams through the process of building a custom app using the FileMaker Platform. The three-part series will cover:

  1. Plan – Your first steps toward creating a successful custom app
  2. Create – Your step-by-step guide to successfully create an app with FileMaker
  3. Deploy  – Your step-by-step guide to successfully deploy an app with FileMaker

Click here to download the Plan ebook – the Create and Deploy eBooks will be released over the next few months.

If you would like to discuss a custom app for your organisation please contact us for a free initial consultation.