7

我正在使用 Propel 2。我正在通过关系为对象补水,如下所示:

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

生成的 Array 看起来像这样:

{
  "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(3rd) 参数,toArray()但这似乎没有帮助。我也可以通过unset()调用进行某种形式的数组行走,但我希望有更好的方法,也许使用格式化程序或其他东西?

对于加分,我很想删除定义外键关系的列。例如,CustomerId会去,但Customer会留下。

4

4 回答 4

3

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


RECURSION字符串在 propel 中几乎是硬编码的(在 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 与列名匹配)。

于 2016-07-05T13:16:30.157 回答
2

当您toArray在 Propel ObjectCollection 上调用方法时,它将调用toArray集合的每个项目(查询的结果)。因此,有两种方法可以实现您想要做的事情:1)覆盖and模型类或 and 类中的方法toArray(一个快速而肮脏的解决方案,因为每次使用该方法时都会应用它......)。2) 扩展类以在方法中定义“跳过和策略”,然后将其添加为格式化程序以仅在您需要此特定行为时使用(与集合上的方法一起)。CustomerStatusCustomerCollectionStatusCollectiontoArrayArrayFormatterCustomerStatusformatsetFormatter

一些参考: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

于 2016-07-11T15:50:00.773 回答
1

答案似乎很简单。

如果我使用这样的标准ArrayFormatter

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

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

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

于 2016-07-12T11:11:24.650 回答
0

您是否尝试致电:

unset($return['Customer']['Orders']);
unset($return['Status']['Orders']);
于 2016-06-29T14:04:29.457 回答