This project provides access to FileMaker Server databases using the XML Web publishing interface.
This package builds with Swift Package Manager and is part of the Perfect project. It was written to be stand-alone and so does not need to be run as part of a Perfect server application.
Ensure you have installed and activated the latest Swift 4.1.1 tool chain.
Ensure that you have installed curl and libxml2.
sudo apt-get install libcurl4-openssl-dev libxml2-dev
Add this project as a dependency in your Package.swift file.
.package(url: "https://github.com/PerfectlySoft/Perfect-FileMaker.git", from: "3.0.0")
To utilize this package, import PerfectFileMaker.
This snippet connects to the server and has it list all of the hosted databases.
letfms=FileMakerServer(host: testHost, port: testPort, userName: testUserName, password: testPassword)
fms.databaseNames{
result indo{
// Get the list of names
letnames=tryresult()fornamein names {print("Got a database name \(name)")}}catchFMPError.serverError(let code,let msg){print("Got a server error \(code)\(msg)")}catchlet e{print("Got an unexpected error \(e)")}}List all of the layouts in a particular database.
letfms=FileMakerServer(host: testHost, port: testPort, userName: testUserName, password: testPassword)
fms.layoutNames(database:"FMServer_Sample"){
result inguardlet names =try?result()else{return // got an error
}fornamein names {print("Got a layout name \(name)")}}List all of the field names on a particular layout.
letfms=FileMakerServer(host: testHost, port: testPort, userName: testUserName, password: testPassword)
fms.layoutInfo(database:"FMServer_Sample", layout:"Task Details"){
result inguardlet layoutInfo =try?result()else{return // error
}letfieldsByName= layoutInfo.fieldsByName
for(name, value)in fieldsByName {print("Field \(name) = \(value)")}}Perform a findall and print all field names and values.
letquery=FMPQuery(database:"FMServer_Sample", layout:"Task Details", action:.findAll)letfms=FileMakerServer(host: testHost, port: testPort, userName: testUserName, password: testPassword)
fms.query(query){
result inguardlet resultSet =try?result()else{return // error
}letfields= resultSet.layoutInfo.fields
letrecords= resultSet.records
letrecordCount= records.count
foriin0..<recordCount {letrec=records[i]forfieldin fields {switch field {case.fieldDefinition(let def):letfieldName= def.name
iflet fnd = rec.elements[fieldName], case .field(_,let fieldValue)= fnd {print("Normal field: \(fieldName) = \(fieldValue)")}case.relatedSetDefinition(let name, _):guardlet fnd = rec.elements[name], case .relatedSet(_,let relatedRecs)= fnd else{continue}print("Relation: \(name)")forrelatedRecin relatedRecs {forrelatedRowin relatedRec.elements.values {if case .field(let fieldName,let fieldValue)= relatedRow {print("\tRelated field: \(fieldName) = \(fieldValue)")}}}}}}}To add skip and max, the query above would be amended as follows:
// Skip two records and return a max of two records.
letquery=FMPQuery(database:"FMServer_Sample", layout:"Task Details", action:.findAll).skipRecords(2).maxRecords(2)...Find all records where the field "Status" has the value of "In Progress".
letqfields=[FMPQueryFieldGroup(fields:[FMPQueryField(name:"Status", value:"In Progress")])]letquery=FMPQuery(database:"FMServer_Sample", layout:"Task Details", action:.find).queryFields(qfields)letfms=FileMakerServer(host: testHost, port: testPort, userName: testUserName, password: testPassword)
fms.query(query){
result inguardlet resultSet =try?result()else{return // error
}letfields= resultSet.layoutInfo.fields
letrecords= resultSet.records
letrecordCount= records.count
foriin0..<recordCount {letrec=records[i]forfieldin fields {switch field {case.fieldDefinition(let def):letfieldName= def.name
iflet fnd = rec.elements[fieldName], case .field(_,let fieldValue)= fnd {print("Normal field: \(fieldName) = \(fieldValue)")if name =="Status", case .text(let tstStr)= fieldValue {print("Status == \(tstStr)")}}case.relatedSetDefinition(let name, _):guardlet fnd = rec.elements[name], case .relatedSet(_,let relatedRecs)= fnd else{continue}print("Relation: \(name)")forrelatedRecin relatedRecs {forrelatedRowin relatedRec.elements.values {if case .field(let fieldName,let fieldValue)= relatedRow {print("\tRelated field: \(fieldName) = \(fieldValue)")}}}}}}}



