将ObjectCollection转换为JSON()时,Propel2:小写/ camelCase键

时间:2015-11-18 19:10:07

标签: php json propel camelcasing propel2

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

查询:

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

结果:

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

默认情况下似乎是PascalCase。 如何在json结果上获得小写属性?

我所指的功能可以找到here and is applied to an ObjectCollection.

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

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

2 个答案:

答案 0 :(得分:0)

每次更改行为

我不认为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 ] )   返回一个数组,其中包含来自数组小写或大写的所有键。   编号索引保持不变。

<强>参数

阵列 要处理的数组

情况下 CASE_UPPER或CASE_LOWER(默认)

返回值

返回一个数组,其键为lower或uppercased,如果array不是数组,则返回FALSE。

适用于(PHP 4&gt; = 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);,因为小写是默认值。

答案 1 :(得分:0)

有一种方法可以将生成的类配置为使用camelCase键。在你的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,因此会将所有密钥作为camelCase返回。

问题的根源在于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()会将所有键都设为camelCase。

所以遗憾的是,如果不修改源代码,就不能使toJSON使用camelCase。我认为exportTo方法应该使用defaultKeyType,因此我们可以使用配置来修改此行为。话虽如此,可能有一个很好的理由来获得硬编码值而不是可配置值。

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

行走/运行时间/收集/ 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()));
}

行走/运行时间/收集/ 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,那将会很好,但不幸的是,它不会起作用。