Propel2:将 ObjectCollection 转换为 JSON() 时的 lowercase/camelCase 个键

Propel2: lowercase/camelCase keys when converting ObjectCollection toJSON()

我们如何将 toJson() 返回对象的键转换为小写或驼峰式? 考虑以下示例:

查询:

     $foo = FooQuery::create()
        ->filterByBar($bar)
        ->findOne()
        ->toJson();

结果:

{"Id": 1, "Bar":"Whosebug"}

好像默认是PascalCase。 如何获得 json 结果的小写属性?

可以找到我指的函数here and is applied to an ObjectCollection.

更新: 我想避免使用数组,因为:array_change_key_case() 在处理复杂对象时不适用于多维数组。

我知道这可以通过一些修改来实现,但我想知道是否有更好的方法,最好不要先转换为数组以提高性能。

每次都改变行为

我认为 Propel 不会通过您传递给方法的选项为您提供直接简单的方法来执行此操作。但是,您可以覆盖 类.

中的 *Base 方法
public function toJSON() {
  $fields = array_change_key_case(parent::toJSON());
  return $fields;
}

对于一次性案例更改

仍在使用上面的函数,但更详细:array_change_key_case 更改数组中所有键的大小写。您可以在 PHP official docs.

中阅读相关信息

array_change_key_case ( array $array [, int $case = CASE_LOWER ] ) Returns an array with all keys from array lowercased or uppercased. Numbered indices are left as is.

参数

数组 要处理的数组

案例 CASE_UPPER 或 CASE_LOWER(默认)

Return 值

Returns 一个数组,其键小写或大写,如果数组不是数组,则为 FALSE。

适用于 (PHP 4 >= 4.2.0, PHP 5, PHP 7)

例子

<?php
$input_array = array("FirSt" => 1, "SecOnd" => 4);
print_r(array_change_key_case($input_array, CASE_UPPER));
?>

输出

Array
(
    [FIRST] => 1
    [SECOND] => 4
)

给你...

在您的示例中,您可以在下一行简单地键入 $lower_foo = array_change_key_case($foo);,因为小写字母是默认值。

有一种方法可以将生成的 类 配置为使用驼峰式键。在您的 propel.json(或 .yaml、.php .ini .xml)配置文件中添加 objectModel,如下所示:

"generator": {
  "defaultConnection": "bookstore",
  "connections": [ "bookstore" ],
  "objectModel": {
    "defaultKeyType": "camelName"
  }
}

这将使您所有的键都采用驼峰式命名,但事实证明这仅适用于 toArray() 方法。当您调用 toJSON() 时,您实际上是在使用 exportTo('JSON') 方法。如果您查看 exportTo 方法,您会发现它正在调用:

$this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)

这会强制 exportTo('JSON')toJSON() 使用 TableMap::TYPE_PHPNAME 作为密钥类型。如果您查看 toArray 方法定义,它使用您的 "defaultKeyType" 作为默认值 $keyType。如果你在没有任何参数的情况下调用 toArray() 并且你有 "defaultKeyType": "camelName" 那么它将使用 TableMap::TYPE_CAMELNAME 并且因此 return 所有键都是驼峰式。

问题的根源在于 Propel 的发电机 类。基数 类 生成于 propel/src/Propel/Generator/Builder/Om/ObjectBuilder.php 如果我们查看它如何生成 toArray 方法,我们会发现:

public function toArray($keyType = TableMap::$defaultKeyType, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array()" . ($hasFks ? ", $includeForeignObjects = false" : '') . ")

这里重要的一点是它使用的是TableMap::$defaultKeyType。现在如果我们查看 exportTo 方法生成,我们必须查看 templates/baseObjectMethods.php 并且 exportTo 方法定义如下:

public function exportTo($parser, $includeLazyLoadColumns = true)
{
    if (!$parser instanceof AbstractParser) {
        $parser = AbstractParser::getParser($parser);
    }

    return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true));
}

这里的重点是它使用了硬编码值TableMap::TYPE_PHPNAME。如果您将该硬编码值更改为 TableMap::TYPE_CAMELNAME 并重新生成 类,则 toJSON() 会将所有键作为驼峰式命名。

很遗憾,您不能 toJSON 在不修改源代码的情况下使用驼峰式命名法。我认为 exportTo 方法应该使用 defaultKeyType 以便我们可以使用配置来修改此行为。话虽如此,使用硬编码值而不是可配置值可能是一个非常好的理由。

更新: 看起来这只适用于每个生成模型的单个实例 类。对于 ObjectCollectionCollection 类,toArrayexportTo 方法使用 TableMap::TYPE_PHPNAME

的硬编码值

Propel/Runtime/Collection/Collection.php

public function exportTo($parser, $usePrefix = true, $includeLazyLoadColumns = true)
{
    if (!$parser instanceof AbstractParser) {
        $parser = AbstractParser::getParser($parser);
    }

    $array = $this->toArray(null, $usePrefix, TableMap::TYPE_PHPNAME, $includeLazyLoadColumns);

    return $parser->listFromArray($array, lcfirst($this->getPluralModelName()));
}

Propel/Runtime/Collection/ObjectCollection.php

public function toArray($keyColumn = null, $usePrefix = false, $keyType = TableMap::TYPE_CAMELNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = [])
{
    $ret = [];
    $keyGetterMethod = 'get' . $keyColumn;

    /** @var $obj ActiveRecordInterface */
    foreach ($this->data as $key => $obj) {
        $key = null === $keyColumn ? $key : $obj->$keyGetterMethod();
        $key = $usePrefix ? ($this->getModel() . '_' . $key) : $key;
        $ret[$key] = $obj->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true);
    }

    return $ret;
}

因此,如果我们可以使用配置文件将这些设置为 TableMap::CAMELNAME,那会很好,但不幸的是,这不起作用。