L5SimpleFM v 1.0 – A Composer and Laravel 5 friendly PHP package for interacting with hosted FileMaker data

 TLDR Overview

L5SimpleFM is a PHP package used to provide a simple, readable, declarative syntax for accessing data hosted on a FileMaker Server from a composer-friendly PHP project. The package also has a ServiceProvider class which allows it to be easily pulled into a Laravel 5 project. The L5SimpleFM package is now available as a 1.0 release on github. It can also be installed from packagist via composer.

A brief example:

Selecting the first 10 records from a layout Inventory with the status “active” would look like:

 use L5SimpleFMFileMakerModelsBaseModel;  // The model class class Inventory extends BaseModel {     protected $layoutName = 'Inventory'; }  // The controller use AppFileMakerModelsInventory;  class InventoryController extends Controller  {      protected $inventory;      public function __construct(Inventory $inventory)     {         $this->inventory = $inventory;     }      public function getActiveInventoryItems(Request $request)     {         $returnCount = $request->input('count');         $result = $this->inventory->findByFields(['status' => 'active'])->max($returnCount)->executeCommand();         $records = $result->getRows();         return compact('records');     }  }  

The tool is a wrapper around the Soliant Consulting tool SimpleFM. SimpleFM handles the actual sending and receiving of data to and from FileMaker server, L5SimpleFM creates a human readable syntax and allows for the creation of Model classes for an MVC project pattern. A simple example Task project I created using L5SimpleFM can be found here on github.


The need

Recently I started working on a web project for Skeleton Key that used FileMaker as a back end database. I had worked with the FileMaker PHP API in the past and while it was useful, it had a couple of drawbacks that made me want to explore other tools. Namely:

  • It contains code that has been deprecated by PHP which causes errors when running from a modern version of PHP.
  • It is not PSR friendly which makes it harder to work with a modern PHP framework (e.g. Laravel which is my favorite framework).

Ultimately, I tried to include the FileMaker PHP API into a Laravel project via composer classmap and ran into so many roadblocks for the simplest database call that I scrapped the idea of trying to fit it in. From there I explored a couple of other tools as far as accessing FileMaker from a PHP framework. I explored Goya’s RestFM and Soliant Consulting’s SimpleFM. Both are amazing tools and I can see using both of them in various kinds of applications. In the end, I chose SimpleFM for a number of reasons, but the most important reason was that I wanted to be able to point my project to any FileMaker Server, not just the one I configured RestFM for.

Wrapping SimpleFM

I pulled SimpleFM into my project and started using it directly. It’s fairly straight forward to use if you’re familiar and comfortable with FileMaker’s XML web publishing syntax, but the look and feel of the code I was writing wasn’t as readable as I would like:

         // A contrived example:     public function index(Request $request)     {         $returnCount = $request->input('count');          // This would normally be included in some global file accessible by any php page that will use the adapter         // I'm showing this here with the credentials inline to show the full picture.         $hostConnection = new HostConnection('', 'L5SimpleFMExample', 'web_user', 'webdemo!');         $this->adapter = new Adapter($hostConnection);          // within an InventoryController         $this->adapter->setLayoutName('Inventory');         $commandArray = [             'status' => 'active',             '-max' => $returnCount,             '-find' => null,         ];          $result = $this->adapter->setCommandArray($commandArray)->execute();         $records = $result->getRows();          return compact("records");     } 

The action being performed is defined by the data rather than a class. There isn’t an issue with this, it’s a very transparent way of interfacing with FileMaker XML web publishing, but keeping it this way makes the code less portable. Rather than coding common commands into data each time I want to interact with FileMaker in my application I would prefer to structure those common commands into a class and inject that class into my code as needed. This is how L5SimpleFM started. The construction and instantiation of the host connection and adapter were moved out to a ServiceProvider for easier Laravel integration. Note: This is the standard ServiceProvider for L5SimpleFM. You do not have to code this, you only need to add the service provider reference to your laravel `config/app.php` file.

 use IlluminateSupportServiceProvider; use L5SimpleFML5SimpleFM; use SoliantSimpleFMAdapter; use SoliantSimpleFMHostConnection;  class L5SimpleFMServiceProvider extends ServiceProvider {     public function register()     {         $this->constructAndBindL5SimpleFM();     }      protected function constructAndBindL5SimpleFM()     {         $this->app->bind('L5SimpleFMContractsFileMakerInterface', function ($app) {             // credentials are pulled from the laravel `.env` file.             $username = env('FM_USERNAME');             $password = env('FM_PASSWORD');             $host = env('FM_HOST);             $database = env('FM_DATABASE');              $hostConnection = new HostConnection($host, $database, $username, $password);             return new L5SimpleFM(new Adapter($hostConnection));         });     } }  

Common commands could be fired from a L5SimpleFM class method:

 use L5SimpleFMContractsFileMakerInterface; use IlluminateHttpRequest;  class InventoryController extends Controller {      protected $fm;      public function __construct(FileMakerInterface $fm)     {         $this->fm = $fm;     }      public function index(Request $request)     {         $max = $request->input('max');         $skip = $request->input('skip');         $result = $this->fm->setLayout('Inventory')->findAll()->max($max)->skip($skip)->executeCommand();         $records = $result->getRows();         return compact('records');     } }  

FileMaker Models

This worked but seemed a bit disorganized within an MVC framework. Any time I built up and fired a command I was dealing with one context/entity within my database at a time. The next logical step in organizing the tool was to use it to create FileMaker Model classes. I created a BaseModel abstract class that acts as a map between the L5SimpleFM service and whatever new model you extend from the BaseModel. Now a FileMaker model class can be created that clearly defines an entity within the Laravel project:

 use L5SimpleFMFileMakerModelsBaseModel;  class Inventory extends BaseModel {     protected $layoutName = 'Inventory'; }  

The layout name specified sets the context for all commands fired from the model. Now I can inject the new model into my controller and clean up my command just a bit:

 use AppFileMakerModelsInventory; use IlluminateHttpRequest;  class InventoryController extends Controller {     protected $inventory;      public function __construct(Inventory $inventory)     {         $this->inventory = $inventory;     }      public function index(Request $request)     {         $max = $request->input('max');         $skip = $request->input('skip');         $result = $this->inventory->findAll()->max($max)->skip($skip)->executeCommand();         $records = $result->getRows();         return compact('records');     } } 

The L5SimpleFM service class can still be used directly via the FileMakerInterface which is ideal for building small services that interact with FileMaker but don’t necessarily need a model class, but for cases where creating a dedicated model makes better sense the BaseModel abstract can be used.

Using the package

The L5SimpleFM package is now available as a 1.0 release on github. It can also be installed from packagist via composer. The tool is open source so feel free to explore. If you have any feedback you can post questions to github, shoot me an email at chris.schmitz@skeletonkey.com, or post to me on twitter @cschmitz81. Christopher Schmitz is a Certified Developer at Skeleton Key. About Skeleton Key Skeleton Key helps turn complex, complicated, and outdated systems into true information platforms. Our team of consultants and developers do this by developing custom-fit software tools and reporting dashboards that help businesses find, use, and understand their data, freeing them to focus on and grow their core business. In addition to custom databases and applications, we also provide training and coaching for getting the most out of your existing systems and understanding your unruly data. Skeleton Key is an open-book management company and active player of the Great Game of Business.