Using the Modx newQuery() method with relational objects

In Modx when an object has a 'many' relationship defined we can access related objects by calling the getMany() method on the object. But did you know, you can use the $modx->newQuery() method to improve the efficiency of the call to only retrieve the related objects we want? In this article, we'll look at a simple example so you can start optimising you’re PDO calls.

Note: This article has been written for Modx 2

Magic boxes

We're going to use an example of a box that can hold many different items

<?xml version="1.0" encoding="UTF-8"?>

<model package="boxes" baseClass="xPDOObject" platform="mysql" defaultEngine="InnoDB" phpdoc-package="" phpdoc-subpackage="" version="1.1">

    <object class="box" table="box" extends="xPDOSimpleObject">
        <field key="name" dbtype="varchar" phptype="string" precision="255" null="true" default="" />
        <field key="description" dbtype="text" phptype="string" null="false" default="" /> 

        <composite alias="Items" class="item" local="id" foreign="box" cardinality="many" owner="local" />

    </object>

    <object class="item" table="item" extends="xPDOSimpleObject">
        <field key="box" dbtype="int" precision="10" phptype="integer" null="false" default="" />

        <field key="name" dbtype="varchar" phptype="string" precision="255" null="true" default="" />
        <field key="description" dbtype="text" phptype="string" null="false" default="" /> 

        <field key="length" dbtype="varchar" phptype="string" precision="255" null="true" default="" />
        <field key="height" dbtype="varchar" phptype="string" precision="255" null="true" default="" />
        <field key="width" dbtype="varchar" phptype="string" precision="255" null="true" default="" />
        <field key="weight" dbtype="varchar" phptype="string" precision="255" null="true" default="" />

        <aggregate alias="Box" class="box" local="box" foreign="id" cardinality="one" owner="foreign" />

    </object>
</model>

Getting items from a box

We now have our schema for boxes and the items they can hold. We can access these boxes and their items using simple PDO queries

<?php

// Get the box with ID 1
$box = $modx->getObject('box', 1);

// Get all items
$items = $box->getMany('Items');

Now our $box var contains the box object with ID 1, while our $items var contains an array of items that are related to box with an ID of 1.

Using newQuery()

Now we have our box, we can create a new query to pass to our getMany method to return only the items we want. For example, say we only want to return 10 items, order alphabetically, that weigh more than 15. To accomplish this we simply need to write a newQuery().

<?php

// Get the box with ID 1
$box = $modx->getObject('box', 1);

// Create a new query for the item Class (Not the Items alias)
$query = $modx->newQuery('item');
$query->where([
    'weight:>=' => 15
]);
// Add a sort to the Name of the item ascending in value
$query->sortby('name','ASC');
// Limit the number of items to 10 with an offset of 0
$query->limit(10, 0);

// Get filtered items
$items = $box->getMany('Items', $query);

Now our $items var contains an array of a maximum 10 items that have been ordered ascending according to the item name.

Conclusion

An easy enhancement that can make a huge difference in performance, especially if you’ve ever grabbed all related objects and looped through them to filter out the ones you want.