在Propel中使用toArray()时,是否可以删除带* RECURSION *的字段?

时间:2016-06-29 13:28:15

标签: php propel propel2

我正在使用Propel 2.我通过关系来保湿对象,如下:

$return = OrderQuery::create()
    ->joinWith('Customer')
    ->joinWith('Status')
    ->find()
    ->toArray(TableMap::TYPE_PHPNAME, true, [], true);

生成的数组看起来像这样:

{
  "Id": 1,
  "CustomerId": 1,
  "StatusId": 1,
  "Initiated": "2016-01-01T01:01:01+00:00",
  "Customer": {
    "Id": 1,
    "Forname": "Test",
    "Surname": "Smith",
    "Orders": [
      "*RECURSION*"
    ]
  }
  "Status": {
    "Id": 1,
    "Title": "title 1",
    "Priority": 1,
    "Orders": [
      "*RECURSION*"
    ]
  },
}

我想删除值为*RECURSION*的字段。我尝试将$alreadyDumpedObjects(第3个)参数用于toArray(),但这似乎没有帮助。我也可以使用unset()调用进行某种形式的数组行走,但是我希望有更好的方法,可能还有格式化程序或其他东西?

对于奖励积分,我非常想删除定义外键关系的列。例如,CustomerId会继续,但Customer会保留。

4 个答案:

答案 0 :(得分:3)

请注意简洁:这个答案有一些非常有用的信息,但 是一个解决方案,尽管这个答案说没有。

RECURSION 字符串在推进中非常硬编码(在src / Propel / Generator / Builder / Orm / ObjectBuilder.php中):

if (isset(\$alreadyDumpedObjects['$objectClassName'][\$this->hashCode()])) {
    return '*RECURSION*';
}

我想你可以覆盖对象构建器,但我怀疑你正在寻找什么。因此,唯一可行的方法是你不想做的事情,循环遍历数组并使用unset。像这样:

$array = StudyQuery::create()
    ->leftJoinWithInstitute()
    ->find()
    ->toArray();

var_dump($array);
echo PHP_EOL . PHP_EOL . PHP_EOL;
var_dump(cleanupData($array));

/**
 * @param array $array
 *
 * @return array
 */
function cleanupData(array $array)
{
    $relationsFound = [];
    foreach ($array as $key => $item) {
        if ($item === ["*RECURSION*"] || $item == "*RECURSION*") {
            unset($array[$key]);
        } elseif (is_array($item)) {
            $array[$key] = cleanupData($item);
            $relationsFound[] = $key;
        }
    }

    foreach ($relationsFound as $relation) {
        $key = $relation . 'Id';
        if (isset($array[$key])) {
            unset($array[$key]);
        }
    }

    return $array;
}

如果存在该关系,则还应过滤掉*** Id字段(前提是该关系的PHPName与列名匹配)。

答案 1 :(得分:2)

当您在Propel ObjectCollection上调用toArray方法时,它将在集合的每个项目上调用toArray(查询结果)。 因此,有两种方法可以实现您尝试做的事情: 1)覆盖toArrayCustomer模型类或StatusCustomerCollection模型中的StatusCollection方法(自应用以来快速和肮脏的解决方案)每次使用toArray方法时......)。 2)扩展ArrayFormatter类以定义"跳过CustomerStatus策略"在format方法中,然后将其添加为要使用的格式化程序(在集合上使用setFormatter方法)仅在您需要此特定行为时。

一些参考: http://propelorm.org/documentation/reference/model-criteria.html#using-an-alternative-collection-class

http://propelorm.org/documentation/reference/model-criteria.html#using-an-alternative-formatter

答案 2 :(得分:1)

答案似乎很简单。

如果我使用这样的标准ArrayFormatter

$return = OrderQuery::create()
    ->setFormatter('Propel\Runtime\Formatter\ArrayFormatter');
    ->joinWith('Customer')
    ->joinWith('Status')
    ->find()
    ->toArray();

返回的是ArrayCollection,当toArray()被调用时,除了递归字段之外,它与原始输出完全相同。

注意,当获得一个结果时,例如->findPk(1),它将返回一个关联数组,因此您不应该明确使用->toArray()

答案 3 :(得分:0)

您是否尝试过致电:

trim()