Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to remove fields with *RECURSION* when using toArray() in Propel?

I am using Propel 2. I am hydrating objects through the relations, like so:

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

The resulting Array would look something like this:

{
  "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*"
    ]
  },
}

I want to remove the fields where the value is *RECURSION*. I tried using the $alreadyDumpedObjects (3rd) parameter to toArray() but that didn't seem to help. I could also do some form of array walking with unset() calls, but I'm hoping there's a better way, maybe with a formatter or something?

For bonus points, I'd quite like to remove the columns which define the foreign key relationship. For instance, CustomerId would go, but Customer would remain.

like image 410
LeonardChallis Avatar asked Jun 29 '16 13:06

LeonardChallis


1 Answers

Note for brevity: This answer has some really helpful information, but there is a solution, despite this answer saying there isn't.


The RECURSION string is pretty much hardcoded in propel (in src/Propel/Generator/Builder/Orm/ObjectBuilder.php):

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

I suppose you could override the object builder, but I doubt that's what you are looking for. Thus, the only other viable way is what you did not want to do, looping over the array and using unset. Something like this:

$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;
}

This should also filter out the ***Id-fields, if that relation is present (provided the PHPName for the relation matches the column name).

like image 137
chocochaos Avatar answered Nov 06 '22 20:11

chocochaos