在 Propel 中使用 toArray() 时是否可以使用 *RECURSION* 删除字段?
Is it possible to remove fields with *RECURSION* when using toArray() in Propel?
我正在使用 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
会留下。
你试过打电话吗:
unset($return['Customer']['Orders']);
unset($return['Status']['Orders']);
为简洁起见:这个答案提供了一些非常有用的信息,但是是一个解决方案,尽管这个答案说没有。
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;
}
如果该关系存在(假设该关系的 PHPName 与列名匹配),这也应该过滤掉 ***Id 字段。
当您在 Propel ObjectCollection 上调用 toArray
方法时,它会在集合的每个项目(查询结果)上调用 toArray
。
所以有两种方法可以实现你想要做的事情:
1) 覆盖 Customer
和 Status
模型 classes 或 CustomerCollection
和 StatusCollection
模型中的 toArray
方法(一个快速且肮脏的解决方案,因为每次使用 toArray
方法时都会应用它...)。
2) 扩展ArrayFormatter
class 在format
方法中定义一个"skip Customer
and Status
strategy" 然后将其添加为要使用的格式化程序(使用setFormatter
方法集合)仅在您需要此特定行为时。
http://propelorm.org/documentation/reference/model-criteria.html#using-an-alternative-formatter
答案,看起来,似乎很简单。
如果我使用这样的标准 ArrayFormatter
:
$return = OrderQuery::create()
->setFormatter('Propel\Runtime\Formatter\ArrayFormatter');
->joinWith('Customer')
->joinWith('Status')
->find()
->toArray();
returned 是一个 ArrayCollection
,当调用 toArray()
时,除了缺少递归字段外,它与我的原始输出完全相同。
注意,当得到一个结果时,例如 ->findPk(1)
,它将 return 一个关联数组,所以你不应该明确地使用 ->toArray()
。
我正在使用 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
会留下。
你试过打电话吗:
unset($return['Customer']['Orders']);
unset($return['Status']['Orders']);
为简洁起见:这个答案提供了一些非常有用的信息,但是是一个解决方案,尽管这个答案说没有。
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;
}
如果该关系存在(假设该关系的 PHPName 与列名匹配),这也应该过滤掉 ***Id 字段。
当您在 Propel ObjectCollection 上调用 toArray
方法时,它会在集合的每个项目(查询结果)上调用 toArray
。
所以有两种方法可以实现你想要做的事情:
1) 覆盖 Customer
和 Status
模型 classes 或 CustomerCollection
和 StatusCollection
模型中的 toArray
方法(一个快速且肮脏的解决方案,因为每次使用 toArray
方法时都会应用它...)。
2) 扩展ArrayFormatter
class 在format
方法中定义一个"skip Customer
and Status
strategy" 然后将其添加为要使用的格式化程序(使用setFormatter
方法集合)仅在您需要此特定行为时。
http://propelorm.org/documentation/reference/model-criteria.html#using-an-alternative-formatter
答案,看起来,似乎很简单。
如果我使用这样的标准 ArrayFormatter
:
$return = OrderQuery::create()
->setFormatter('Propel\Runtime\Formatter\ArrayFormatter');
->joinWith('Customer')
->joinWith('Status')
->find()
->toArray();
returned 是一个 ArrayCollection
,当调用 toArray()
时,除了缺少递归字段外,它与我的原始输出完全相同。
注意,当得到一个结果时,例如 ->findPk(1)
,它将 return 一个关联数组,所以你不应该明确地使用 ->toArray()
。