FMCakeMix: A Full Read/Write Datasource for FileMaker
2 : Usage Examples
Define Your Database Connection
Below we’ve defined our default connection to use the fmcakemix driver and provided the necessary details for cake’s connection manager to connect with our filemaker database. If your models refer to multiple FileMaker database files, don’t worry we will override the database attribute when defining our models.
<?php
var $default = array(
'driver' => 'fmcakemix',
'persistent' => false,
'dataSourceType' => 'FMPro7',
'scheme' => 'http',
'port' => 80,
'host' => '127.0.0.1',
'login' => 'myUserName',
'password' => 'myPassword',
'database' => 'FMServer_Sample',
'prefix' => '',
);
?>
Define Your Model
In addition to the standard model attributes of name, useDbConfig, and primaryKey, we’ll also want to tell Cake to associate our model with a default FileMaker layout using the defaultLayout attribute and define a fmDatabaseName for the FileMaker file where our layout lives.
Relations are defined through the hasMany, hasOne, belongsTo, and hasAndBelongsToMany attributes (Currently the driver only supports hasMany and belongsTo relations). There are essentially two options you have when working with related data in FileMaker; either use relationships defined within Cake or leverage FileMaker’s ability to relate and retrieve data through portals. Remember when retrieving data through a Cake defined relationship you’re actually making a new call for every related model, this could have a negative impact on performance.
The fmTOtranslations attribute allows you to associate related portal data that may be returned by the model’s layout to a Cake model we may have defined elsewhere within our application. Here we’re associating any data returned from a portal of commentsTO, the name of a FileMaker table occurrence, to a Comments model.
<?php
class Book extends AppModel {
var $name = 'Book';
var $useDbConfig = 'default';
var $primaryKey = 'ID';
// FMCakeMix specific attributes
var $defualtLayout = 'web_books_general';
var $fmDatabaseName = 'FMServer_Sample';
// Optionally assign related models
var $hasMany = array(
'Comment' => array(
'foreignKey' => '_fk_book_id'
),
'History' => array(
'foreignKey' => '_fk_book_id'
)
);
// Optionally provide translations of related FileMaker table occurrences
// that may be returned through FileMaker portals into Cake model names
var $fmTOtranslations = array(
'CommentsTO' => 'Comment'
);
// Optionally provide validation criteria for our model
var $validate = array(
'Title' => array(
'rule' => 'notEmpty'
),
'Author' => array(
'rule' => 'notEmpty'
)
);
}
?>
Controller Examples
Below we’ll cover the basics for creating, reading, deleting, and updating data within our FileMaker database.
Create
saveA basic add method for our controller. Here we’re taking information passed from a form, $this->data, and calling two model methods to save this data to a new record in FileMaker. It’s important to note that cake will continue to automagically handle certain fields, such as created and modified.
<?php
function add() {
if (!empty($this->data)) {
$this->Book->create();
if ($this->Book->save($this->data)) {
$this->Session->setFlash(__('The Book has been saved', true));
$this->redirect(array('action'=>'index'));
} else {
$this->Session->setFlash(__('The Book could not be saved. Please, try again.', true));
}
}
}
?>
saveAll
The saveAll model method will allow us to save multiple models at a time. When using the saveAll method always pass the option atomic is false to tell Cake not to attempt a transactional save to our database.
<?php
$_data = array(
'Comment' => array(
array(
'_fk_article_id' => $this->Book[‘ID’],
'body' => 'New Comment'
),
array(
'_fk_article_id' => $this->Book[‘ID’],
'body' => 'Another Comment'
)
)
);
$this->Comment->create();
$this->Comment->saveAll($_data['Comment'], array('atomic' => FALSE));
?>
Read
findHere we collect a query for a recipe title and perform a find request for recipes containing this title and with a published value of 1.
<?php
function search() {
$query = $this->data['Recipe']['title'];
$recipes = $this->Recipe->find('all', array(
'conditions' => array(
'title’ => $query,
‘published’ => ‘=’.1
)
));
$this->set('recipes, $recipes);
}
?>
paginate
The FMCakeMix datasource supports offsets and sorting, and can be implemented by the paginate function.
<?php
var $paginate = array('limit' => 10, 'page' => 1);
function index() {
$this->Book->recursive = 0;
$this->set('books', $this->paginate('Book'));
}
?>
Delete
del, removeThe del method and its alias remove will delete a single record from your database. FileMaker requires that we send the internal recid of the record we wish to delete with every delete request. A recid is returned as one of the fields in the returned data set whenever we return record data, such as after a find command. Additionally the recid is saved to the model id attribute which leaves the model referencing the record returned on the last query, this is especially useful after a create action. Note however that this is a departure from a CakePHP standard that assumes the primaryKey id will be stored in this attribute.
In the example below the find sets the model id attribute so that when calling the del method FileMaker is passed the appropriate recid of the record to be deleted.
<?php
delete() {
$this->Book->find('first', array(
'conditions' => array(
'Book.ID' => 48
),
'recursive' => 0
));
$model->del()
}
?>
deleteAll
Here’s a more functional example of how you might implement a delete method. Here we pass the recid of the record to delete and provide some user feedback to the view. Instead of using the del method we use deleteAll to be explicit about the record we wish to delete.
<?php
function delete($recid = null) {
if (!$recid) {
$this->Session->setFlash(__('Invalid id for Book', true));
$this->redirect(array('action'=>'index'));
}
if ($this->Book->deleteAll(array('-recid' => $recid), false)) {
$this->Session->setFlash(__('Book deleted', true));
$this->redirect(array('action'=>'index'));
} else {
$this->Session->setFlash(__('Book could not be deleted', true));
$this->redirect(array('action'=>'index'));
}
}
?>
Update
saveAn update works much like a create and uses the same save model method, but instead we pass along the FileMaker required recid of the record we wish to edit. In this example the recid is included in the passed form data, implemented as a hidden input.
<?php
function edit($id = null) {
if (!$id && empty($this->data)) {
$this->Session->setFlash(__('Invalid Book', true));
}
if (!empty($this->data)) {
if ($this->Book->save($this->data)) {
$this->Session->setFlash(__('The Book has been saved', true));
$this->redirect(array('action'=>'index'));
} else {
$this->Session->setFlash(__('The Book could not be saved.', true));
}
}
if (empty($this->data)) {
$this->data = $this->Book->read(null, $id);
}
}
?>
Comments
Question
1 Installation Manual