【问题标题】:Propel2: lowercase/camelCase keys when converting ObjectCollection toJSON()Propel2:将 ObjectCollection 转换为 JSON() 时的小写/驼峰式键
【发布时间】:2015-11-18 19:10:07
【问题描述】:

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

查询:

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

结果:

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

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

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

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

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

【问题讨论】:

    标签: php json propel camelcasing propel2


    【解决方案1】:

    有一种方法可以将生成的类配置为使用 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 并因此返回所有键作为驼峰式。

    问题的根源在于 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 使用 camelCase。我认为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,那就太好了,但不幸的是,这不起作用。

    【讨论】:

      【解决方案2】:

      每次都改变行为

      我不认为 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(默认)

      返回值

      返回一个键值小写或大写的数组,如果数组不是数组,则返回 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);,因为小写是默认值。

      【讨论】:

      • 感谢您的输入,但我已经了解 array_change_key_case。我想将它集成到推进查询中,这样我就不必为每个数据库调用转换结果。
      • @scripton 我不认为 propel 提供了这个选项,但是如果你重写基类的 JSON 方法,它只是一行代码,可以做你想做的事。我编辑了我的答案以提及这一点。您还可以解码 JSON,添加另一个自定义属性,然后重新编码。 (这对你没有用,但我认为这是覆盖它的更常见的原因。)
      • 感谢您的更新。我尝试在我的 EntityQuery 类中使​​用该函数,但这似乎不起作用,因为父级没有该函数。我需要在哪个 Propel 类中添加该功能?
      猜你喜欢
      • 2011-02-27
      • 2016-08-07
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 2018-12-18
      • 2016-07-30
      • 2017-08-18
      相关资源
      最近更新 更多