Community

Why does getCollectionGraph() not come back with the composite class?

I’m having trouble understanding how to use getCollectionGraph(). I want to be able to get a subset of Orders and then get all the OrderItems for those Orders and be able to work with that data together. Here’s the code I’ve pieced together from examples I’ve found:

$q = $modx->newQuery('Order');
$q->sortby('deliverDate', 'ASC');
$q->where(["DATE(deliverDate) > CURDATE()"]);
$q->where(array('menu'=>'mp'));

$orders = $modx->getCollectionGraph('Order', '{"OrderItem":{}}', $q);

foreach($orders as $order){
    echo 'order: '.print_r($order->OrderItem->toArray()); //NULL
}

The relevant schema bits:

<object class="Order" table="cat_orders" extends="xPDOSimpleObject">
    <composite alias="Item" class="OrderItem" local="id" foreign="order" cardinality="many" owner="local" />
</object>

<object class="OrderItem" table="cat_orders_item" extends="xPDOSimpleObject">
    <aggregate alias="Order" class="Order" local="order" foreign="id" cardinality="one" owner="foreign" />
    <index alias="order" name="order" primary="false" unique="false" type="BTREE">
        <column key="order" length="" collation="A" null="false" />
    </index>
</object>

What am I missing?

1 Like

That all looks correct to me.

Have you checked the DB to make sure the order field contains a value with the id of an existing OrderItem?

Did you regenerate the class and map files after your last change to the schema? The getCollectionGraph() method doesn’t know anything about the schema, it just goes by the class and map files.

If that’s not it, it’s worth trying manual deletion of the cache files.

One order has many item, so that’ll be an array of objects. Also the alias is Item, so you should adjust that in both the getCollectionGraph and the accessor in the loop.

Duh. Ignore my answer. :zipper_mouth_face:

1 Like

So I changed it to this:

$orders = $modx->getCollectionGraph('Order', '{"Item":{}}', $q);

foreach($orders as $order){
    echo 'order: '.print_r($order->Item);
}

I think I must not have it quite right tho because I’m getting this error:

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 94461952 bytes)

Edit:
I changed the echo line to this:

echo 'order: '.$order->Item->name;

And now the error is gone and the page loads but there’s no data. It echos that line the appropriate number of times tho.

Trying to use var_dump() instead of print_r() results in the same out of memory error.

This outputs “order: NULL” for each one:

echo 'order: '.gettype($order->get('Item'));

This tells me that the type is “array”:

$item = $order->Item;
echo 'order: '.gettype($item);

But both $item[0] and $item[‘name’] are empty and print_r crashes.

1 Like

I think I got it now:

foreach($orders as $order){
    $items = $order->Item;
    foreach($items as $i)
        echo $i->get('name');
}

Makes sense now that I understand what’s going on better. :smiley:

1 Like

You’ve already figured it out, but just to elaborate and add some more explanation…

print_r($order->Item)

This will cause a memory error because it’s an (array of) xPDOObject(s) - that’s an object holding references to all sorts of other objects, which gets big if you try to dump it. Instead, you can use print_r($object->toArray()) or var_dump($object->toArray()) to inspect an xPDOObject.

In $order->Item, which is an array as you found, the indexes refer to the ID of the object. So $item[0] is empty because it’s probably $item[52] or whatever.

2 Likes

Thanks for the help and the elaboration!

1 Like