fmRESTor is an object-based PHP library developed to seamlessly interact with databases and custom apps hosted on a FileMaker Server via the new powerful FileMaker Data API from within a PHP code. Forget about learning FileMaker Data API in detail, just create a new object, passing it necessary parameters to connect to the database, and use our easy to understand methods to access or modify your data. fmRESTor will take care of authentication, exceptions, logging, and even session preservation in order for your code to be a well-behaving client for the FileMaker Data API without you having to worry about these technical details.
We have created fmRESTor for ourselves to make it easier and faster to interact with FileMaker databases from within custom web apps we create, without having to waste our valuable time on repeating writing the same patterns over and over again, hunting for unnecessary bugs, and to be able to produce clean, easy to read and easy to maintain code.
We at 24U believe that the whole FileMaker developers community will benefit from the FileMaker Platform not only having new powerful RESTful API, but also developers using the API nicely and efficiently, therefore we decided to make our library available as Open Source, under the GNU LGPLv3 license.
We will greatly appreciate your contributions, although we cannot provide free support for the library. You may, however, hire us to help you with your projects for money by purchasing our services at https://www.24uSoftware.com/fmRESTor or by utilizing our custom development services, available at https://www.24uSoftware.com/custom-apps.
- One object class conveniently handles everything
- Automatically generates authentication token
- Re-uses existing token to avoid unnecessary additional connections
- Automatically re-generates expired token
- Handles exceptions and provides meaningful error results
- Can handle raw form data for easier container uploads
- Provides customizable debug logging
- PHP >= 5.6
- PHP cURL
- FileMaker Server 17, 18, 19 & 20
Install the latest version with:
composer require fmrestor/fmrestor
Usage:
session_start();
require __DIR__ . "/vendor/autoload.php";
use fmRESTor\fmRESTor;
$fm = new fmRESTor($host, $database, $layout, $user, $password, $options, $fmExternalSource);
Include downloaded library file to your project and create new class instance.
session_start();
require_once __DIR__ . '/src/fmRESTor.php';
use fmRESTor\fmRESTor;
$fm = new fmRESTor($host, $database, $layout, $user, $password, $options, $fmExternalSource);
Parameter | Type | Mandatory | Description |
---|---|---|---|
$host | string | yes | Hostname or IP address where FileMaker database is hosted |
$database | string | yes | FileMaker database name |
$layout | string | yes | Database layout name to work on |
$user | string | yes | User login to database |
$password | string | yes | User password to database |
$options | array | optional | Additional library configuration |
$fmExternalSource | array | optional | Providing additional data sources, i.e. if you use a separation model and the current layout needs to access data from external data sources. |
Name | Type | Mandatory | Default value | Description | Possible error |
---|---|---|---|---|---|
logType | string | optional | LOG_TYPE_NONE | LOG_TYPE_DEBUG - Debug logging level LOG_TYPE_ERRORS - Log errors only LOG_TYPE_NONE - Disable logging |
-101 ( Unknown value ) |
logDir | string | optional | "log" (same path as library file) | Custom default folder for log output | -102 (probably the wrong type of variable) |
sessionName | string | optional | "fm-api-token" | Custom session name, available in "$_SESSION['custom_session_name']" | |
tokenExpireTime | number | optional | 14 | Expiration time in minutes. fmRESTor automatically handles database login and saves token with its expiration time (into $_SESSION var) during first request. If expired, fmRESTor automatically reconnects to database on next request. | -104 (probably the wrong type of variable) |
allowInsecure | boolean | optional | false | Valid SSL certificate required unless set to true | -105 (probably the wrong type of variable) |
autorelogin | boolean | optional | true | If request ends with auth error, fmRESTor will try the request again with request new session. It could happened if someone disconnect your session trought Admin Console or if your server was rebooted , but FileMaker Data API Token is still save in session / file on your side | -112 (probably the wrong type of variable) |
curlOptions | array | optional | [] | fmRESTor uses cURL to communicate with FileMaker Server, you can adjust the following options: PHP cURL options list | -113 (probably the wrong type of variable) |
tokenStorage | string | optional | TS_SESSION | TS_SESSION - Save FileFileMaker API token to PHP Session TS_FILE - Save FileMaker API Token to File |
-110 ( Unknown value ) |
tokenFilePath | string | Required if option "tokenStorage" is set to "TS_FILE" | "" | Path to file where to store FileMaker Data API Token. Create an empty file and make it writeable for PHP. | -111 (probably the wrong type of variable) |
session_start();
require_once __DIR__ . '/src/fmRESTor.php';
use fmRESTor\fmRESTor;
$options = array(
"logType" => fmRESTor:: LOG_TYPE_NONE,
"logDir" => dirname(__DIR__) . "/my-logs/",
"sessionName" => "fm-api-token",
"tokenExpireTime" => 14,
"allowInsecure" => true,
"curlOptions" => [
CURLOPT_CONNECTTIMEOUT => 30
],
"tokenStorage" => fmRESTor::TS_FILE,
"tokenFilePath" => dirname(__DIR__) . "/token/filemaker-token.txt"
);
$fmExternalSource = array(
array(
"database" => "fmRESTorEXTERNAL",
"username" => "external",
"password" => "external123456"
)
);
$fm = new fmRESTor("127.0.0.1","fmRESTor", "php_user", "api", "api123456", $options, $fmExternalSource);
Supported FileMaker Server version: 17, 18, 19, 20
Close current session in the FileMaker database.
/**
* @return mixed
*/
public function logout()
Usage
$fm->logout();
Supported FileMaker Server version: 18, 19, 20
Returns useful information about the FileMaker Server you're connecting to, such as version or data & time formats.
/**
* @return bool|mixed
*/
public function getProductInformation()
Usage
$fm->getProductInformation();
Sample Response
array(2) {
["response"]=>
array(1) {
["productInfo"]=>
array(6) {
["name"]=>
string(25) "FileMaker Data API Engine"
["buildDate"]=>
string(10) "04/29/2019"
["version"]=>
string(10) "18.0.1.123"
["dateFormat"]=>
string(10) "MM/dd/yyyy"
["timeFormat"]=>
string(8) "HH:mm:ss"
["timeStampFormat"]=>
string(19) "MM/dd/yyyy HH:mm:ss"
}
}
["messages"]=>
array(1) {
[0]=>
array(2) {
["code"]=>
string(1) "0"
["message"]=>
string(2) "OK"
}
}
}
FileMaker 18 Data API Guide - Get Product Information
Supported FileMaker Server version: 18, 19, 20
Returns array of names of all databases hosted and enabled for access via FileMaker Data API.
/**
* @return bool|mixed
*/
public function getDatabaseNames()
Usage
$fm->getDatabaseNames();
Sample Response
array(2) {
["response"]=>
array(1) {
["databases"]=>
array(1) {
[0]=>
array(1) {
["name"]=>
string(8) "fmRESTor"
}
}
}
["messages"]=>
array(1) {
[0]=>
array(2) {
["code"]=>
string(1) "0"
["message"]=>
string(2) "OK"
}
}
}
FileMaker 18 Data API Guide - Get Database Names
Supported FileMaker Server version: 18, 19, 20
Returns array of names of all available scripts for given database.
/**
* @return bool|mixed
*/
public function getScriptNames()
Usage
$fm->getScriptNames();
Sample Response
array(2) {
["response"]=>
array(1) {
["scripts"]=>
array(1) {
[0]=>
array(2) {
["name"]=>
string(15) "Log request"
["isFolder"]=>
bool(false)
}
}
}
["messages"]=>
array(1) {
[0]=>
array(2) {
["code"]=>
string(1) "0"
["message"]=>
string(2) "OK"
}
}
}
FileMaker 18 Data API Guide - Get Script Names
Supported FileMaker Server version: 18, 19, 20
Returns array of names of all available layouts for given database.
/**
* @return bool|mixed
*/
public function getLayoutNames()
Usage
$fm->getLayoutNames();
Sample Response
array(2) {
["response"]=>
array(1) {
["layouts"]=>
array(3) {
[0]=>
array(3) {
["name"]=>
string(3) "php"
["isFolder"]=>
bool(true)
["folderLayoutNames"]=>
array(2) {
[0]=>
array(1) {
["name"]=>
string(8) "php_user"
}
[1]=>
array(1) {
["name"]=>
string(11) "php_licence"
}
}
}
[1]=>
array(3) {
["name"]=>
string(4) "scpt"
["isFolder"]=>
bool(true)
["folderLayoutNames"]=>
array(1) {
[0]=>
array(1) {
["name"]=>
string(8) "scpt_log"
}
}
}
[2]=>
array(3) {
["name"]=>
string(4) "data"
["isFolder"]=>
bool(true)
["folderLayoutNames"]=>
array(1) {
[0]=>
array(1) {
["name"]=>
string(8) "data_log"
}
}
}
}
}
["messages"]=>
array(1) {
[0]=>
array(2) {
["code"]=>
string(1) "0"
["message"]=>
string(2) "OK"
}
}
}
FileMaker 18 Data API Guide - Get Layout Names
Supported FileMaker Server version: 18, 19, 20
Returns useful information about specific layout, including fields on the layout, portals, and value list data for each field set to use a value list for data entry.
/**
* @return bool|mixed
*/
public function getLayoutMetadata()
Usage
$fm->getLayoutMetadata();
Sample Response
array(2) {
["response"]=>
array(2) {
["fieldMetaData"]=>
array(17) {
[0]=>
array(14) {
["name"]=>
string(2) "id"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(6) "number"
["global"]=>
bool(false)
["autoEnter"]=>
bool(true)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(true)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[1]=>
array(14) {
["name"]=>
string(7) "created"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(9) "timeStamp"
["global"]=>
bool(false)
["autoEnter"]=>
bool(true)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[2]=>
array(14) {
["name"]=>
string(10) "created_by"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "text"
["global"]=>
bool(false)
["autoEnter"]=>
bool(true)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[3]=>
array(14) {
["name"]=>
string(8) "modified"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(9) "timeStamp"
["global"]=>
bool(false)
["autoEnter"]=>
bool(true)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[4]=>
array(14) {
["name"]=>
string(11) "modified_by"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "text"
["global"]=>
bool(false)
["autoEnter"]=>
bool(true)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[5]=>
array(14) {
["name"]=>
string(7) "surname"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "text"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[6]=>
array(14) {
["name"]=>
string(5) "email"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "text"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[7]=>
array(14) {
["name"]=>
string(8) "birthday"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "date"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[8]=>
array(14) {
["name"]=>
string(30) "personal_identification_number"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(6) "number"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[9]=>
array(14) {
["name"]=>
string(7) "address"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "text"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[10]=>
array(14) {
["name"]=>
string(11) "c_record_id"
["type"]=>
string(11) "calculation"
["displayType"]=>
string(8) "editText"
["result"]=>
string(6) "number"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[11]=>
array(14) {
["name"]=>
string(5) "photo"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(9) "container"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[12]=>
array(14) {
["name"]=>
string(5) "g_one"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(6) "number"
["global"]=>
bool(true)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[13]=>
array(14) {
["name"]=>
string(6) "g_text"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "text"
["global"]=>
bool(true)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[14]=>
array(14) {
["name"]=>
string(11) "<No Access>"
["type"]=>
string(7) "invalid"
["displayType"]=>
string(8) "editText"
["result"]=>
string(7) "invalid"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[15]=>
array(14) {
["name"]=>
string(11) "<No Access>"
["type"]=>
string(7) "invalid"
["displayType"]=>
string(8) "editText"
["result"]=>
string(7) "invalid"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[16]=>
array(14) {
["name"]=>
string(11) "<No Access>"
["type"]=>
string(7) "invalid"
["displayType"]=>
string(8) "editText"
["result"]=>
string(7) "invalid"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
}
["portalMetaData"]=>
array(1) {
["portal_licence"]=>
array(4) {
[0]=>
array(14) {
["name"]=>
string(26) "USER_licence::product_name"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "text"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[1]=>
array(14) {
["name"]=>
string(17) "USER_licence::key"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "text"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[2]=>
array(14) {
["name"]=>
string(21) "USER_licence::version"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "text"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
[3]=>
array(14) {
["name"]=>
string(32) "USER_licence::date_of_expiration"
["type"]=>
string(6) "normal"
["displayType"]=>
string(8) "editText"
["result"]=>
string(4) "date"
["global"]=>
bool(false)
["autoEnter"]=>
bool(false)
["fourDigitYear"]=>
bool(false)
["maxRepeat"]=>
int(1)
["maxCharacters"]=>
int(0)
["notEmpty"]=>
bool(false)
["numeric"]=>
bool(false)
["timeOfDay"]=>
bool(false)
["repetitionStart"]=>
int(1)
["repetitionEnd"]=>
int(1)
}
}
}
}
["messages"]=>
array(1) {
[0]=>
array(2) {
["code"]=>
string(1) "0"
["message"]=>
string(2) "OK"
}
}
}
FileMaker 18 Data API Guide - Get Layout Metadata
Supported FileMaker Server version: 17, 18, 19, 20
Create a record in the primary table of the current fmRESTor instance context.
/**
* @param array $parameters
* @return bool|mixed
*/
public function createRecord($parameters)
Usage
$parameters = array(
"fieldData" => array(
"surname" => "Create Name",
"email" => "email@email.com",
"birthday" => "1.1.2001",
"personal_identification_number" => "99",
"address" => "Street 24, City"
)
);
$fm->createRecord($parameters);
Sample Response
array(2) {
["response"]=>
array(2) {
["recordId"]=>
string(2) "11"
["modId"]=>
string(1) "0"
}
["messages"]=>
array(1) {
[0]=>
array(2) {
["code"]=>
string(1) "0"
["message"]=>
string(2) "OK"
}
}
}
Complete list of optional parameters is available at FileMaker 18 Data API Guide
Supported FileMaker Server version: 17, 18, 19, 20
Delete a record of given ID from the primary table of the current fmRESTor instance context.
/**
* @param integer $id
* @param array $parameters
* @return bool|mixed
*/
public function deleteRecord($id, $parameters = null)
Usage
$parameters = array(
"script" => "Log request",
"script.param" => "MyScriptParameters",
"script.prerequest" => "Log request",
"script.prerequest.param" => "MyScriptPreRequestParameters",
"script.presort" => "Log request",
"script.presort.param" => "MyScriptPreSortParameters"
);
$recordID = 4;
$fm->deleteRecord($recordID, $parameters);
Sample Response
array(2) {
["response"]=>
array(0) {
}
["messages"]=>
array(1) {
[0]=>
array(2) {
["code"]=>
string(1) "0"
["message"]=>
string(2) "OK"
}
}
}
Complete list of optional parameters is available at FileMaker 18 Data API Guide
Supported FileMaker Server version: 18, 19, 20
Duplicate a record, specified by ID, found in the primary table of the current fmRESTor instance context.
/**
* @param integer $id
* @param array $parameters
* @return bool|mixed
*/
public function duplicateRecord($id, $parameters = null)
Usage
$parameters = array(
"script" => "Log request",
"script.param" => "MyScriptParameters",
"script.prerequest" => "Log request",
"script.prerequest.param" => "MyScriptPreRequestParameters",
"script.presort" => "Log request",
"script.presort.param" => "MyScriptPreSortParameters"
);
$recordId = 3;
$response = $fm->duplicateRecord($recordId, $parameters);
Sample Response
array(2) {
["response"]=>
array(8) {
["scriptResult.prerequest"]=>
string(28) "MyScriptPreRequestParameters"
["scriptError.prerequest"]=>
string(1) "0"
[