将数据传递到 PHP 的选项有哪些?

What are the options for passing data to PHP?

凭借最少的 "real" 编程经验,我正在开发一个项目,该项目将我已经构建的 FileMaker Pro 解决方案与使用 FileMaker Server PHP 的本机 iOS 应用程序集成在一起] API。 iOS 申请是针对 iPhone 的,写在 Swift.

我们正在尝试了解处理某些场景的最有效方法,尤其是在将数据写回服务器时。让我们使用地址簿的简单示例。当用户导航到联系人记录时,he/she 可以 select 一个字段,编辑然后保存它的内容。

虽然我们已经实现了一些向服务器写入数据的功能,但它们都相对简单(比如扫描条形码,发送 php 请求触发 FM Server 中的脚本,然后将结果呈现给客户)。看起来,在具有许多字段的联系人记录的情况下,通过标准 PHP URL 将每个字段的值作为变量发送,其中一些可能是段落或照片,效率低且笨重。

对于那些不熟悉 FileMaker PHP API 的人,下面是一些示例代码来演示更新特定联系人记录的过程。示例代码执行以下操作:

  1. 将从客户端传递的参数设置为变量。
  2. 定义应在其上执行代码的布局(FM PHP API 适用于布局,而不是像 SQL 这样的表格)
  3. 查找记录并更新字段。

示例代码:

<?php
require_once 'Filemaker.php';

//connect to db
$fm = new FileMaker();
$fm->setProperty('database', 'fmDbName');
$fm->setProperty('hostspec', '123.45.67.89');
$fm->setProperty('username', 'user');
$fm->setProperty('password', 'password');

//define layout on which to process
$layout = 'php_contacts';

//define variables passed from client
$contactId = $_GET['contactId'];
$first = $_GET['firstName'];
$last = $_GET['lastName'];
$mobile = $_GET['mobile'];
$office = $_GET['office'];
$note = $_GET['note'];

//Find the contact which is being updated
$find = $fm->newFindCommand($layout);
$find->addFindCriterion('contactId', $contactId);

//execute the find
$results = $find->execute();

//check for error
if (FileMaker::isError($result)) {
    echo "     Error: ".$results."     ";
    exit;
}

//declare the record being updated
$record = $results->getFirstRecord();

//update the fields
$record->setField('firstName', $first);
$record->setField('lastName', $last);
$record->setField('mobile', $mobile);
$record->setField('office', $office);
$record->setField('note', $note);

?>

我们面临的挑战不是如何实施特定方法,而是首先要了解选项是什么,以及相关的最佳实践和他们在一起。

例如,将变量作为数组或字典从客户端发送到 PHP 是否比将它们作为独立变量发送到 URL 更好?将本地应用程序中多个字段的数据巧妙地推送到 PHP 服务器的其他选项有哪些?

谢谢!

我很确定 PHP 基本上适用于 HTTP 请求,基本上是 POST 和 GET。

您发送的结构应该根据您的需要来定义,没有完美的解决方案。

您应该检查 HTTP 请求的工作方式: http://www.w3schools.com/tags/ref_httpmethods.asp

根据我的理解,

$_GET$_POST 慢得多。您应该从将传输字符串的应用程序向服务器发送 POST 请求。通过 Internet 发送原始图像很容易导致失真和数据丢失。为了将图像作为字符串发送,您将使用 Base-64 编码。这意味着您会将图像二进制文件转换为 returns 字符串的编码方案。您可以将此字符串发送到服务器或应用程序进行解码。 (注意:您可以使用 Base-64 编码的图像作为 URL,这可能会派上用场。)

我认为除了使用 POST 消息或原始 JSON 之外,没有更好的方法在服务器和客户端之间发送数据。 Swift 和 Objective-C 有一个名为 NSJSONSerialization 的 class,您可以使用它来转换从 PHP 脚本返回的 JSON,以便稍后在您的应用程序中使用.

从您的服务器,您可以简单地在脚本开头的变量中创建一个空数组供以后使用,然后在该数组可用时将信息附加到该数组(如果您的服务器上有图像,您需要对其进行 Base-64 编码,然后仅在 Base-64 编码完成后将字符串附加到数组)。在脚本的末尾——当您将要发送给应用程序的所有数据附加到该数组时——您可以编写 echo json_encode($thatArray) 将数组作为 JSON 发送回应用程序.当然,这意味着您从一开始就希望它是一个关联数组,因为您将拥有键值对。

我会依靠该方法从服务器获取信息并将其翻转(在 Swift 应用程序中创建一个 Dictionary 然后使用 NSJSONSerialization.JSONObjectWithData(data: NSData, options: NSJSONReadingOptions, error: NSErrorPointer) 转换 Dictionary 到 JSON。然后创建一个请求,该请求将通过 POST 请求将 JSON 发送到服务器。当然,您的 PHP 脚本将使用 json_decode($_POST['thatJSONFromTheApplication'])) 以便应用程序将 JSON 发送到服务器。

这就是我为让我的应用程序和服务器协同工作所做的工作。如果您阅读本文并且有更好的想法,请分享!

因此,您可以或应该做几件事。

应该做:

将凭据移出文档

将您的数据库连接信息从您的 php 代码中移出并放入存储在服务器文档根目录 外部 的配置文件中,即如果您的文档根目录位于:

/var/www/myapp/public/

您可以将配置文件存储在:

/var/www/myapp/config/

这样,如果 php 以某种方式失败并且 returns 作为文本与 php 代码,您的凭据不会暴露。您可以通过多种方式做到这一点,但我见过的最简单的方法是将它们定义为常量。例如:

// File config.php
define('FM_DATABASE', 'fmdbname');
define('FM_HOSTSPEC', '123.45.67.89');
define('FM_USERNAME', 'user');
define('FM_PASSWORD', 'password);

并在代码中要求配置文件并在连接对象中使用常量:

$fm = new FileMaker(FM_DATABASE, FM_HOSTSPEC, FM_USERNAME, FM_PASSWORD);

如果出现错误,切勿转储整个结果

您没有在您的代码中执行此操作,但知道您是否在处理 FileMaker PHP API 是一件好事。如果您遇到障碍 ,返回的错误结果对象将包含您的连接凭据。我不知道为什么会这样,但确实如此。切勿将整个对象转储到客户端,因为您会将这些凭据公开为转储的一部分。

FileMaker 的 Error 对象扩展了 Pear Error Object,因此如果您最终想要传回有关遇到的错误的信息,您可以使用任何 pear 错误方法。

使用连接对象来测试错误

FileMaker API 代码在 php 方面已经过时了。静态方法 FileMaker::isError 实际上没有在 API 代码中定义为静态方法。这意味着除非你在你的网络服务器上抑制不推荐使用的消息,否则你将让网络服务器向你咆哮。问题是,您已经创建了 FileMaker 对象的一个​​实例,因此您可以使用它来检查您的结果是否有误:

if($fm->isError($result)){ // this won't produce the deprecated warning.
    ...

也就是说,由于 api 中的其他弃用代码,您可能会看到一堆其他错误:P

可以做到:

在您的客户端应用程序中缓存记录 ID

现在您正在查找记录、更新它的字段并提交它。这模拟了 FileMaker 的体验,但由于您是通过 php 界面编辑数据,因此您可以稍微缩短它。

如果您的客户端应用程序(swift 应用程序)知道它正在更新的记录的记录 ID,那么您可以使用 newEditCommand 来更新记录。编辑命令使用 FileMaker internal 记录 ID(即 FileMaker 提供记录的 ID,而不是用户添加的主键的 ID)来确定要更新的记录。这是您如何使用它的示例:

$editQuery = $fm->newEditCommand('my_layout', $recordId);
$editQuery->setField('Status', $newStatus);
$editResult = $editQuery->execute();

这样做的好处是 FileMaker Server 的处理时间更少。你不是在要求服务器找到记录以便你可以编辑它,你是在告诉它要编辑什么记录。

根据业务逻辑如何在您的应用程序中流动,这可能不是一个选项,但如果您可以将记录 ID 存储在客户端,它可能有助于使通信更加快捷。

批量处理更新

看起来您已经在这样做了,但请务必一次将数据分批发送到一个字段。我同意 Arcrammer 关于使用 POST 而不是 GET 的评论,因为 POST 是将数据发送到服务器的预期方法。


这些是我对您的代码的建议。我还建议深入研究 API 代码。我发现查看对象和方法为我回答了很多问题,而 FileMaker 为 API 提供的文档和教程却没有。

祝你好运!