This is my first entry in my blog and I wish to start by sharing some code I wrote recently whilst integrating the Filemaker API into Yii. I started by looking in the Extensions section of the Yii main website to see if I could find anything that someone else had written but without success. I came to the realization that this had not been done yet or not created as an extension so I began on integrating it myself. The following are the steps I followed to get a functional Filemaker/Yii website working ( most likely not the best way but it works ).
- I started by creating a vendors folder within the protected folder of my Yii site and imported the API.
- I added an entry into config/main.php to automatically import the API.
'import'=>array( 'application.models.*', 'application.components.*', 'application.vendors.*', ),
- I then added a few application-level parameters for connection to the API.
'params'=>array( 'fm_host' => 'example.com', 'fm_file' => 'myfile.fp7', 'fm_user' => 'myusername', 'fm_pass' => 'mypass', ),
- I decided that creating a new behaviour class would be the best approach since I can attach this to any class. So I created a CFilemakerBehaviour class and placed it within the components sections of the protected folder. Here are some basics of the class.
class CFileMakerBehaviour extends CBehavior { public $fm; public $layout; public function __construct($layout,$attributes = array()) { $host = Yii::app()->params['fm_host']; $file = Yii::app()->params['fm_file']; $user = Yii::app()->params['fm_user']; $pass = Yii::app()->params['fm_pass']; $this->fm = new FileMaker($file,$host,$user,$pass); $this->layout = $layout; } //conditions requires an associative array i.e key => value //if you want to add less than or greater than add it to the value i.e price => '> 15' //gets all records for the layout public function findAllRecords($conditions=array()) { $find_command = $this->fm->newFindCommand($this->layout); if (FileMaker::isError($find_command)) { throw new FileMakerException($find_command->getMessage(),$find_command->getCode()); } if (count($conditions) > 0) { foreach ($conditions as $label => $value) $find_command->addFindCriterion($label,$value); } $result = $find_command->execute(); if (FileMaker::isError($result)) { throw new FileMakerException($result->getMessage(),$result->getCode()); } return $result->getRecords(); } //conditions requires an associative array i.e key => value //if you want to add less than or greater than add it to the value i.e price => '> 15' //gets a single record public function findRecord($conditions=array()) { $find_command = $this->fm->newFindCommand($this->layout); if (FileMaker::isError($find_command)) { throw new FileMakerException($find_command->getMessage(),$find_command->getCode()); } if (count($conditions) > 0) { foreach ($conditions as $label => $value) { $find_command->addFindCriterion($label,$value); } } $find_command->setRange(0,1); $result = $find_command->execute(); if (FileMaker::isError($result)) { return false; } return $result->getFirstRecord(); } //gets the maximum value of a specific field public function getFieldMaximum($field,$conditions=array()) { $find_command = $this->fm->newFindCommand($this->layout); if (FileMaker::isError($find_command)) { throw new FileMakerException($find_command->getMessage(),$find_command->getCode()); } if (count($conditions) > 0) { foreach ($conditions as $label => $value) { $find_command->addFindCriterion($label,$value); } } $find_command->addSortRule($field,1,FILEMAKER_SORT_DESCEND); $find_command->setRange(0,1); $result = $find_command->execute(); if (FileMaker::isError($result)) { return false; } $record = $result->getFirstRecord(); return $record->getField($field); } //gets the minimum value of a specific field public function getFieldMinimum($field,$conditions=array()) { $find_command = $this->fm->newFindCommand($this->layout); if (FileMaker::isError($find_command)) { throw new FileMakerException($find_command->getMessage(),$find_command->getCode()); } if (count($conditions) > 0) { foreach ($conditions as $label => $value) { $find_command->addFindCriterion($label,$value); } } $find_command->addSortRule($field,1,FILEMAKER_SORT_ASCEND); $find_command->setRange(0,1); $result = $find_command->execute(); if (FileMaker::isError($result)) { return false; } $record = $result->getFirstRecord(); return $record->getField($field); } } class CFileMakerException extends Exception { }
- I also created a dataprovider class which is handy for cGridView:
class CFileMakerProvider extends CDataProvider { public $keyField; private $fields; private $result; private $keys_array = array(); private $image_columns = array(); private $select = array(); private $where = array(); public function __construct($layout,$config = array()) { $this->attachBehaviour('filemakerbehaviour',new FileMakerBehaviour($layout)); $this->fields = $this->layout->getFields(); foreach($config as $key=>$value) $this->$key=$value; } protected function fetchData() { $find_command = $this->fm->newFindCommand($this->layout); if (count($this->where)) { foreach ($this->where as $label => $value) $find_command->addFindCriterion($label,$value); } if(($pagination=$this->getPagination())!==false) { $pagination->setItemCount($this->getTotalItemCount()); $find_command->setRange($pagination->getOffset(), $pagination->getLimit()); $this->result = $find_command->execute(); if (FileMaker::isError($this->result)) { return 0; } return $this->convertRecordsToArray($this->result->getRecords()); } else { $this->result = $find_command->execute(); if (FileMaker::isError($this->result)) { return 0; } return $this->convertRecordsToArray($this->result->getRecords()); } } protected function convertRecordsToArray($records) { $data = array(); foreach ($records as $i => $record) { foreach ($this->fields as $field) { $field_name = $field->getName(); if (!count($this->select) || in_array($field_name,$this->select)) { if (in_array($field_name,$this->image_columns)) { $field_data = $record->getField($field_name); if (!empty($field_data)) { $raw_image = $this->fm->getContainerData($field_data); if (preg_match('/\.(jpg|jpeg|JPG)/',$field_data)) $mime = 'image/jpeg'; if (preg_match('/\.png/',$field_data)) $mime = 'image/png'; if (preg_match('/\.gif/',$field_data)) $mime = 'image/gif'; if (isset($mime)) { $data[$i][$field_name] = CHtml::image("data:{$mime};base64,".base64_encode($raw_image),''); } else { $data[$i][$field_name] = 'No Image.'; } } else { $data[$i][$field_name] = 'No Image.'; } } elseif (in_array($field_name,$this->doc_columns)) { $field_data = $record->getField($field_name); $data[$i][$field_name] = $record->getField($field_name); } else $data[$i][$field_name] = $record->getField($field_name); } } $this->keys_array[$i] = $record->getField($this->keyField); } return $data; } protected function fetchKeys() { return $this->keys_array; } protected function calculateTotalItemCount() { $find_command = $this->fm->newFindCommand($this->layout); if (count($this->where)) { foreach ($this->where as $label => $value) $find_command->addFindCriterion($label,$value); } if(($pagination=$this->getPagination())!==false) $find_command->setRange($pagination->getOffset(), $pagination->getLimit()); $this->result = $find_command->execute(); if (FileMaker::isError($this->result)) { return 0; } return $this->result->getFoundSetCount(); } } class FileMakerProviderException extends Exception{}
To use the above classes I created models that extended the CFormModel then attached the CFileMakerBehaviour and manually loaded in what I needed.
Anyway these are the real basics and is only for a readonly website at the moment. I might create an extension later if I end up using this API more often (hopefully not).
I just added this feed to my bookmarks. I have to say, I really enjoy reading your blogs. Thanks!
F*ckin’ awesome things here. I am very satisfied to look your post. Thank you so much and i am having a look forward to contact you. Will you kindly drop me a e-mail?