2017年3月30日 星期四

FMSync - 自製 FileMaker 同步工具 (Not plugin)

目前市面上已經有許多 FileMaker Sync 的解決方案,但不外乎是透過 Plugin 或者將 Server 當作外部資料來源( External Data Source ),這些方法各有優缺點,比較有名的應該就是 FMEasySync:

FMEasySync 是將 Server Side當作外部資料來源進行同步,特點是也可以將 Clent 端作為 Server 使用,使用 FileMaker 內部通訊方式,有加密較安全。

支援 FileMaker Go , 但由於 Runtime solution 不支援 Perform Script On Server 和外部資料來源,因此無法用於 Runtime solution。

而其餘 plugin 類型的雖然可用於 Runtime solution 但大多要錢,而且重點是 FileMaker Go 不支援,剛好在目前的需求中,必須同時要能夠讓 Runtime 和 Go 使用,因此自行設計了一套 FileMaker Sync 的 Framework : FMSync (PS: 後來發現已經有同名的 plugin...)




底下說明都採雙語方式,先中文後英文。

This article is written with Chinese(TW) and followed by English.
And sorry about my bad English....


FMSync 採用 FileMaker PHP API 作為資料交換的工具

優點:
  • 同時支援 FileMaker Pro , Go 以及 Runtime solution
  • 使用 FileMaker 內部功能達成,不須使用額外 plugin
  • 如需加密傳輸可使用 https 協定 (預設沒有)
  • 可設定不同步欄位或整份資料表(上傳下載可分開設定)
  • 可設定只下載特定條件的資料
  • Container 資料同步最佳化設定(需要先設定)
  • 免費且開放原始碼
缺點:
  • 設定步驟稍微繁複 ( 類似 FMEasySync )
  • Server 端必須在 FileMaker Server 上

FMSync transfer data with FileMaker PHP API

Advantage :
  • Support FileMaker Pro , Go and Runtime solution
  • Use native FM script , no plugins are needed
  • Can turn on https protocol if you need (default is http)
  • Support "Skip field"  and "Skip table" (Push and Pull are separated)
  • Pull data from server with condition
  • Container Sync optimize (need set up)
  • Free and open source
Disadvantage :
  • Need take some times to configure (like FMEasySync)
  • Hosted database must be on FileMaker Server


伺服器需求  Server requirement
  • FileMaker Server 13+ ( Tested on FMS 14 )
  • PHP 5.6+ with Web Server ( IIS , apache ... etc. )
  • cURL and mb_string module in PHP
  • FileMaker PHP API
  • EzFMB php library ( On my Github )
  • Increase max post limit size in php.ini (or .htaccess ...etc)
  • Suppress PHP warning messages


基本設定  Basic Setup

請開啟你要處理的 FM 檔案以及 FMSync_darkk6.fmp12 檔案(底下稱為 FMSync 檔案)備用,建議是還沒任何資料時就先行建立,若 FM 檔案中已經有資料,之後可用 Script 處理。

Open your FM solution and the FMSync_darkk6.fmp12 file(I will call it FMSync file in this article). It will be better to use a clean database (no records inside), if you are already have some records inside , I've provide a script to help you fix that.



1. 複製必要欄位 Copy SYNC_ fields

所有要同步的資料表加上幾個必要欄位,這些欄位分別為 : SYNC_UUID , SYNC_UTC , SYNC_CLIENTID , SYNC_DELETE ,若資料表中含有 Container 並要啟用最佳化,也請一併先根據底下的 Container optimize 章節設定。
建議直接開啟 FMSync 檔案,並複製 FMSync_darkk6 資料表中的欄位過去,可以避免設定錯誤。

Open FMSync_darkk6 table in FMSync file and copy necessary fields into all tables you want to sync in your FM solution , those fields are : SYNC_UUID , SYNC_UTC , SYNC_CLIENTID , SYNC_DELETE.

If your table have Container field you can see Container optimize section below before you continue.




2. 新增關係圖表 Add table occurrence

開啟「資料庫管理」的「關係圖」介面,將所有要同步的資料表,都複製一份,並將名稱加上 「SYNC_」 前綴字樣。

Open "Manage Databases" and switch to "Relationships" tab, add a new table occurrence for every table you want to sync and rename it with "SYNC_" prefix




3. 新增對應布局 Create layouts

對於所有剛剛建立的「SYNC_」資料表,都建立一個同名的 Layout ,並使用該資料表。

For all table occurrence ( with "SYNC_" prefix ) you've just created , add a new layout with the same name to use them.




4. 設定布局 Set up layouts

每一個剛才所建立的 Layout , 都務必將所有欄位都放置在 Layout 上面,否則 FMSync 會無法運作。 若欄位含有 Repetition , 也務必將所有 Repetition 放置到 Layout 上

For every layouts you've just created, you MUST put all the fields on the layout. If your fields have repetitions, you have to put them on the on the layout too. Check twice all fields are OK , FMSync will not work if you do wrong here.


到此為止都是 Server 和 Client 共同的步驟,底下開始區分 Client 和 Server。

Setting up Client and Server side are all the same until this step.


5. 複製工作區資料表 Copy working tables

開啟 FMSync 檔案,並參考資料表「關係圖」的說明,依照指示,將表格複製到 Client 或 Server 的檔案中。

Open FMSync file go to Relationships tab ( in Manage Databases ) and follow the instruction to copy tables into Client and Server side.



6. 設定同步工作區 Set up working layout for Sync

這個動作為 Client Only,開啟 FMSync 檔案,並到「FMSync_Working」Layout 中,複製 Layout 內所有的元件到你自己 FM 檔案裡面的對應 Layout 上 (也就是 FMSync_Working 這個 Layout)。

底下三個欄位是必要的: LAST_SYNC_UTCURLResultPullContainer
其餘可以根據自己的喜好設定排版。


This step is Client side only. Open the FMSync file and go to layout "FMSync_Working". Copy all the stuffs into the same name layout on your FM solution (client side).

The following fields are necessary you MUST put them on layout : 
LAST_SYNC_UTC, URLResult, PullContainer

For other stuffs you can customize at your own style.



7. 匯入腳本 Import scripts

根據 Server 或 Client 匯入指定的 Script:
  • Server : 匯入 「FMSync_Server」中的 Script (共 2 個)
  • Client : 匯入「FMSync_Client」中的 Script (共 15 個)
其中「FMSync_Util」提供一些工具給兩端都可以使用,如有需要也可以一併匯入。
若假設都匯入,包含資料夾計算, Client 共會匯入 24 個;Server 9 個

Import scripts to your Client and Server solutions.
  • Server : Import scripts in "FMSync_server" folder. ( 2 Scripts )
  • Client : Import scripts in "FMSync_Client" folder. ( 15 Scripts )
The "FMSync_Util" is utility for both side, import them if you need.
Assume that you import all the scipts with folders , it will be 24 items imported on Client, and 9 items on Server.



8. 設定 PHP 程式 Set up PHP files

將 PHP 資料夾中的檔案放置到 Web Server 中,並注意要自行下載、放置 EzFMDB 以及 FileMaker PHP API 的檔案。 放置檔案完成後開啟 config/Config.php 設定與 FileMaker Server 的連線資訊。

第一次佈署完成時,請將 Config.phpCHECK_SETUP_ACCESS 設定改為 true ,並透過瀏覽器連線到 http://YourServerHost/Folder/CheckSetup.php 執行 FMSync 簡易檢查,請確認呈現內容是否無誤(參考下圖)。
※ 請記得檢查完畢後,將其改回 false 以免他人可以由此得知伺服器資訊

注意,在 FileMaker Server 主機中才可下載 Container 資料,若 Web Server 和 FileMaker是不同主機,則必須透過 CrossSiteContainerBridge.phpContainerBridge.php 處理。

Copy files in PHP folder into your Web Server, note that you have to download and place EzFMDB and FileMaker PHP API to the right place yourself. After that, open config/Config.php to change your connection setting.

You can change the value of CHECK_SETUP_ACCESS to true in Config.php and open browser go to URL : http://YourServerHost/Folder/CheckSetup.php , check if there it any error.(See the figure below)
** Remember set the value to false after check or everybody will see your server setting.

Your Web Server MUST be the same with your FileMaker Server to download container data. If you want to run Web Server on another computer, you will need using CrossSiteContainerBridge.php and ContainerBridge.php to transfer data.




9. 調整 FMSync 設定 Tuning FMSync settings

所有該設定的東西設定完後,最後記得在 Client 端的 FMSync_Setting Script 中設定 Web Server URL 以及調整需要的選項。 最後當要進行同步時,只要呼叫 StartSync 即可。Script 執行若傳回 ERROR 代表錯誤, OK 代表成功。

After all the steps are done. Remember to configure your sync setting in Client FMSync_Setting script. ( like your Web Server URL... etc. )

Just perform the script StartSync to start sync and this script will return ERROR on error occur and OK means it's done.




容器優化  Container Optimize

FMSync 支援同步 Container 資料,而通常 Container 資料不太會更動,但若這筆紀錄的其他資料變動時(例如:文字),同步時就會連 Container 資料一起重新傳送,假設 Container 中的資料是幾十 MB 的檔案時,會浪費很多不必要的時間以及流量。

因此 FMSync 支援當某筆資料只有文字被更動時,會先檢查 Container 中的資料是否有更動,若有,才會重新傳送 Container,以節省時間和流量。

若要使用此功能,請在有 Container 的資料表中,針對每一個 Container Field,建立對應的SYNC_MD5_」 Calculation Field,例如:
  • Container 欄位名稱:binSample
  • Calculation 欄位名稱:SYNC_MD5_binSample
Calculation 傳回格式設定為 Text , 其計算內容如下:
GetContainerAttribute ( GetRepetition (binExample; Get ( CalculationRepetitionNumber ) ) ; "MD5" )
注意:若你的 Container field 具有 Repetition , 這個 Calculation 也必須定義相同數量的 Repetition

設定可參考下圖,而欄位定義與範例可以在 FMSync 檔案的「FMSync_darkk6」中找到。


FMSync support container data sync. But if a record have large files (like 20MB) in container and I only change a text field data, it will transfer whole record( include the large file).
It's really wasting time and network resource.

FMSync support MD5 check before syncing container data. When a record needs to be sync, FMSync will check Container's MD5 and trasfer container data only when needed.

To enable this feature, please add a Calculation field named "SYNC_MD5_xxxx" for each container field in your table. ( xxxx is the target container name )
For example :
  • Container field Name : binSample
  • Calculation field Name : SYNC_MD5_binSample
Calculation field must save data as Text , and the calculation is :
GetContainerAttribute ( GetRepetition (binExample; Get ( CalculationRepetitionNumber ) ) ; "MD5" )
NOTE that , if target container is a repetition field, this calculation field must have the same repetition number with the target.

The calculation field definition sample can be found in FMSync file "FMSync_darkk6" table.



進階設定  Advanced Setting

1. 設定不同步欄位或資料表 Skip sync field or table

FMSync 可以設定指定 table 中的特定欄位或整個 table 不進行同步, Push (上傳給伺服器端) 和 Pull(從伺服器端下載) 都可分開設定,只要進入 FMSync_Skip 中,新增資料即可。
使用方式以及範例:
  • tableName : 指定的 table 名稱,必須是 SYNC_ 開頭
  • fieldName : 指定的 field 名稱,可以使用 * 代表整份 table
  • noPush : 若設為 1 , 則指定 field 的資料不會上傳給 Server
  • noPull : 若設為 1 , 則指定 field 的資料不會從 Server 上下載

上圖代表:

  • SYNC_學生資料::id 不會送給 Server 也不會被 Server 資料覆蓋
  • SYNC_學生資料::name 不會將資料送給 Server,只會取得 Server 資料
  • SYNC_班級資料::grade 只會將資料送給 Server ,不會被 Server 資料覆蓋
  • SYNC_DataTable 整個 table 將不參與同步作業


FMSync support skip pushing or pulling specific field or table during sync.
Just go to FMSync_skip layout and fill the table :
  • tableName : Specific table name , starts with SYNC_
  • fieldName : Specific field name , use " * " means whole table
  • onPush : Set to 1 means don't push data to server.
  • onPull : Set to 1 means don't replace data from server
This example means :
  • SYNC_StudentInfo::id Won't push and pull it's data
  • SYNC_StudentInfo::name Won't push data to server
  • SYNC_ClassInfo::grade Won't be replaced by server data
  • SYNC_DataTable Whole table won't be sync.



2. 條件化更新 Pull data with conditions

若每個 Client 只關心自己的資料,不需要將其他 Client 的資料也抓下來時,可以使用條件化的 Pull 設定,前往「FMSync_PullFactor」填寫即可:
  • tableName : 指定的 table 名稱,必須是 SYNC_ 開頭
  • fieldName : 指定的欄位名稱,這裡不可以使用 *
  • factor : 條件,用法和 Perform Find[] 相同
FMSync 在取得該 table 資料時,只會將符合這些條件(AND)的資料取出,並傳回給 Client


If a client is only concerned about his data and don't want pull other clients data.
You can just go to FMSync_PullFactor and write the pull condition:
  • tableName : Specific table name , starts with SYNC_
  • fieldName :Specific field name , don't use " * " here
  • factor : The condition to the field , act like Perfom Find[]



這個表格的意義是:
  1. 從 Server 取得 SYNC_Students 資料時,只找 class_id 為 10 age 小於 15 的資料
  2. 從 Server 取得 SYNC_Class 資料時,只找出  disabled 為 0 的資料

The meaning of this table :
  1. When pulling data from SYNC_Students , only the record matches class_id equals to 10 AND age less then 15 will be pulled.
  2. When pulling data from SYNC_Class , only pull the data where disabled is equals to 0



3. 刪除記錄 Deleting Records

同步的資料若要刪除,會比較建議使用 flag 方式處理,例如,建立一個 is_deleted 欄位,被刪除的資料將其設為 1。( 當然,若這筆資料沒有尚未同步給 Server 或設計流程中,資料不會被其他人動到,是可以直接刪除的 )

由於 FMSync 只會尋找存在的資料進行同步和交換,因此若某筆資料真的被刪除時,就不會被讀取到。 因此,若真的需要刪除資料,請改成將該資料的 SYNC_DELETE 設為 1;並於 FMSync_Setting 中啟用 $$FMSYNC_DELETE_MARK_RECORD

如此設定完成後, Client 端會於同步完成時刪除所有 SYNC_DELETE 為 1 的資料。
注意: Server 端的該資料不會刪除,因為要通知其餘 Client 刪除該筆資料。
 

If you really want to delete records with synced data, you can set SYNC_DELETE to 1 instead of real delete them. And enable $$FMSYNC_DELETE_MARK_RECORD in FMSync_Setting. So that FMSync will delete all records which SYNC_DELETE = 1 after sync.

Server side will not delete those records because it need keep those data to tell other clients to delete. (But real delete the record is not recommended.)



1 則留言:

  1. 您好,
    依您的步驟設定,但在CheckSetup.php只出現一頁空白,不知道可能是那裡做錯?建議可以從那裡著手?
    另有其它技術參考來源?
    麻煩您了,謝謝。
    PS:使用的是FileMaker Server 16

    回覆刪除