PHP 7.2 - SQL Server 2017 - 创建嵌套数组响应

PHP 7.2 - SQL Server 2017 - Create Nested Array response

我有一个从 SQL 服务器数据库检索数据的存储过程。

根据查询结果,我需要填充 SOAPClient 方法的参数数组

目前我正在手动创建数组,但我想知道是否有可能(并且值得)以 SOAP 方法要求的方式直接从 TSQL:

使用 PHP 7.2 - SQL 服务器 2017

我举个例子说明一下: 这是我的查询结果:

Array
(
    [Key] => R******l
    [Password] => c*************z
    [AccountNumber] => 0****1
    [MeterNumber] => 2******5
    [ShipTimestamp] => 2020-10-29T10:24:19+01:00
    [ServiceType] => INTERNATIONAL_ECONOMY
    [PackagingType] => YOUR_PACKAGING
    [PreferredCurrency] => EUR
    [Weight_Units] => KG
    [TotalWeight] => 0.02
...
)

虽然它应该 return 像这样:

Array
(
    [Authentication] => Array
    (
        [User] => Array
        (
            [Key] => R******l
            [Password] => c*************z
        )
    )

    [Client] => Array
    (
        [Account] => 0*******1
        [Meter] => 2*******5
    )

    [Shipment] => Array
    (
        [ShipTimestamp] => 2020-10-29T10:41:26+01:00
        [DropoffType] => REGULAR_PICKUP
        [ServiceType] => INTERNATIONAL_ECONOMY
        [PackagingType] => YOUR_PACKAGING
        [PreferredCurrency] => EUR
        [TotalWeight] => Array
        (
            [Units] => KG
            [Value] => 0.02
        )
    )
    ...
)

是否可行且值得?

你可以 return 一行一 JSON 列使用 FOR JSON PATH1 in SQL and in PHP json_decode($json, true)3$assoc 参数设置为 true 以将 JSON 解码为数组。

SELECT (
  SELECT user_key [Authentication.User.Key]
       , user_password  [Authentication.User.Password]
       , client_account [Client.Account]
       , client_meter   [Client.Meter]
      --- and so on
  FROM my_table
  FOR JSON PATH
) [json]

结果应该是JSON

{ 
 "Authentication": { "User": { "Key": "XXX", "Password": "XXX" } },
 "Client": { "Account": "YYY", "Meter": 200500 }
}

现在您可以在 PHP 中获取该值,对其进行解码并提供给 SOAP。

  $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
  $json = json_decode($row['json'], true);

但在 SQL 中,您需要一种特殊的语法来格式化这些类型:

  1. 日期CONVERT(varchar(10), date_col, 120) - 120 得到 2020-10-29 11:32:00 格式,varchar(10) trim 只是日期部分,varchar(20) 得到整个日期+时间2
  2. 布尔值CAST(boolean_col as bit) (0 -> false, 1 -> true)

更多信息:

  1. SQL: Format query results as JSON with FOR JSON
  2. SQL: CAST and CONVERT with datetime in different formats
  3. PHP: json_decode

举个例子,这也可以通过映射来完成。

数据定义为

$data = [
    'Key'               => 'R******l',
    'Password'          => 'c*************z',
    'AccountNumber'     => '0****1',
    'MeterNumber'       => '2******5',
    'ShipTimestamp'     => '2020-10-29T10:24:19+01:00',
    'ServiceType'       => 'INTERNATIONAL_ECONOMY',
    'PackagingType'     => 'YOUR_PACKAGING',
    'PreferredCurrency' => 'EUR',
    'Weight_Units'      => 'KG',
    'TotalWeight'       => '0.02',
];

用散列定义的映射 table。名字可改,群可加深。

$mapping = [
    'Key'               => ['name' => 'Key',               'group' => ['Authentication', 'User']],
    'Password'          => ['name' => 'Password',          'group' => ['Authentication', 'User']],
    'AccountNumber'     => ['name' => 'Account',           'group' => ['Client']],
    'MeterNumber'       => ['name' => 'Meter',             'group' => ['Client']],
    'ShipTimestamp'     => ['name' => 'ShipTimestamp',     'group' => ['Shipment']],
    'ServiceType'       => ['name' => 'ServiceType',       'group' => ['Shipment']],
    'PackagingType'     => ['name' => 'PackagingType',     'group' => ['Shipment']],
    'PreferredCurrency' => ['name' => 'PreferredCurrency', 'group' => ['Shipment']],
    'Weight_Units'      => ['name' => 'Units',             'group' => ['Shipment', 'TotalWeight']],
    'TotalWeight'       => ['name' => 'Value',             'group' => ['Shipment', 'TotalWeight']],
];

现在是一个简单的例程,通过映射 table 重新映射数据并放入 $mappedData

$mappedData = [];
foreach($data as $key => $value) {
    $map = $mapping[$key];
    $root = array_shift($map['group']);
    krsort($map['group']);
    $value = [$map['name'] => $value];
    foreach($map['group'] as $group) {
        $value = [$group => $value];
    }
    $new[$root] = $value;
    $mappedData = array_replace_recursive ($mappedData, $new);
}

执行时看起来像这样

Array
(
    [Authentication] => Array
        (
            [User] => Array
                (
                    [Key] => R******l
                    [Password] => c*************z
                )

        )

    [Client] => Array
        (
            [Account] => 0****1
            [Meter] => 2******5
        )

    [Shipment] => Array
        (
            [ShipTimestamp] => 2020-10-29T10:24:19+01:00
            [ServiceType] => INTERNATIONAL_ECONOMY
            [PackagingType] => YOUR_PACKAGING
            [PreferredCurrency] => EUR
            [TotalWeight] => Array
                (
                    [Units] => KG
                    [Value] => 0.02
                )

        )

)