# How to build a transport vehicle for a Parent \> Child category relationship?

**URL:** <https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492>\
**Category:** Extras\
**Created:** [January 14, 2021, 11:14pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492 "2021-01-14T23:14:26Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![jaredfhealy](https://community.modx.com/user_avatar/community.modx.com/jaredfhealy/32/456_2.png) [@jaredfhealy](https://community.modx.com/u/jaredfhealy)\
**Post date:** [January 14, 2021, 11:14pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/1 "2021-01-14T23:14:26Z")

</div>

I can not seem to get this working. Any direction would be greatly appreciated. Below is a Snippet that I am using to test out the concept.

Here’s the structure:

1. Root level category, “Top Category”  
1.a Chunk related to Top Category
2. Child category, “Second Category”  
2.a Chunk related to Second Category

```auto
<?php

$modx->loadClass('transport.modPackageBuilder','',false, true);
$builder = new modPackageBuilder($modx);
$builder->createPackage('test','0.1','alpha');
$builder->registerNamespace('test',false,true,'{core_path}components/test/');

$cat1Attr = [
    xPDOTransport::UNIQUE_KEY => 'category',
    xPDOTransport::PRESERVE_KEYS => false,
    xPDOTransport::UPDATE_OBJECT => true,
    xPDOTransport::RELATED_OBJECTS => true,
    xPDOTransport::RELATED_OBJECT_ATTRIBUTES => [
        'Children' => [
            xPDOTransport::UNIQUE_KEY => 'category',
            xPDOTransport::PRESERVE_KEYS => false,
            xPDOTransport::UPDATE_OBJECT => true,
            xPDOTransport::RELATED_OBJECTS => true,
            xPDOTransport::RELATED_OBJECT_ATTRIBUTES => [
                'Chunks' => [
                    xPDOTransport::UNIQUE_KEY => 'name',
                    xPDOTransport::PRESERVE_KEYS => false,
                    xPDOTransport::UPDATE_OBJECT => true
                ]
            ]
        ],
        'Chunks' => [
            xPDOTransport::UNIQUE_KEY => 'name',
            xPDOTransport::PRESERVE_KEYS => false,
            xPDOTransport::UPDATE_OBJECT => true
        ]
    ]
];

// Setup the first category and chunk
$cat1 = $modx->newObject('modCategory', [
    'category' => 'Top Category'    
]);
$chunk1 = $modx->newObject('modChunk', [
    'name' => 'FirstChunk'    
]);

// Add the chunk to the category
$cat1->addMany($chunk1);

// Setup the second category and chunk
$cat2 = $modx->newObject('modCategory', [
    'category' => 'Child Category'    
]);
$chunk2 = $modx->newObject('modChunk', [
    'name' => 'SecondChunk'    
]);

// Add the chunk to the category
$cat2->addMany($chunk2);

// Add the child category to the parent
$cat1->addMany($cat2);

// Create the vehicle
$vehicle = $builder->createVehicle($cat1, $cat1Attr);
$builder->putVehicle($vehicle);

// Set the attributes
$builder->setPackageAttributes(array(
    'license' => "You can use it",
    'readme' => "Nothing to see here"
));

```

When I check the resulting vehicle in the packages directory, it has the following inside the modCategory folder:

```auto
<?php return array (
  'unique_key' => 'category',
  'preserve_keys' => false,
  'update_object' => true,
  'related_objects' => 
  array (
    'Chunks' => 
    array (
      '675d3eba53ee00d9cbc9eb7ed826eb8b' => 
      array (
        'unique_key' => 'name',
        'preserve_keys' => false,
        'update_object' => true,
        'class' => 'modChunk',
        'object' => '{"id":null,"source":0,"property_preprocess":0,"name":"FirstChunk","description":"Chunk","editor_type":0,"category":0,"cache_type":0,"snippet":null,"locked":0,"properties":null,"static":0,"static_file":"","content":null}',
        'guid' => 'ad0aaa5c8aaf60e197cae079e3230e1a',
        'native_key' => NULL,
        'signature' => 'f11127b591a9b7d0896edcc0390f3918',
      ),
    ),
  ),
  'related_object_attributes' => 
  array (
    'Children' => 
    array (
      'unique_key' => 'category',
      'preserve_keys' => false,
      'update_object' => true,
      'related_objects' => true,
      'related_object_attributes' => 
      array (
        'Chunks' => 
        array (
          'unique_key' => 'name',
          'preserve_keys' => false,
          'update_object' => true,
        ),
      ),
    ),
    'Chunks' => 
    array (
      'unique_key' => 'name',
      'preserve_keys' => false,
      'update_object' => true,
    ),
  ),
  'namespace' => 'test',
  'resolve' => NULL,
  'validate' => NULL,
  'vehicle_package' => 'transport',
  'vehicle_class' => 'xPDOObjectVehicle',
  'guid' => 'bf901ab5dd6885b236f37c2894e69b78',
  'package' => 'modx',
  'class' => 'modCategory',
  'signature' => '71443f211b25e490a91fb3b5626e6e0e',
  'native_key' => NULL,
  'object' => '{"id":null,"parent":0,"category":"Top Category","rank":0}',
);

```

Only the chunk directly related to the top level category is packaged in. I saw reference to Category Closures. Do I need to somehow package those in as well?

If I try and create a vehicle for each category, the files are created and chunks are referenced, but it doesn’t install correctly since the relationship is missing between categories.

Do most/all Extras just have a single category?

---

<div class="post-metadata">

**Author:** ![jaredfhealy](https://community.modx.com/user_avatar/community.modx.com/jaredfhealy/32/456_2.png) [@jaredfhealy](https://community.modx.com/u/jaredfhealy)\
**Post date:** [January 14, 2021, 11:27pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/2 "2021-01-14T23:27:10Z")

</div>

Actually I just found a few discussions from the old forums. I am guessing this is still not possible even though this was 10 years ago?

> **[How can we create subcategories with modx package?](https://forums.modx.com/thread/37958/how-can-we-create-subcategories-with-modx-package)**
>
> The MODX Forum Archive contains a wide ranging variety of questions and rich answers related to MODX Revolution, MODX Evolution and MODX Cloud. Ask new questions and find recent answers at community.modx.com

> **[Category Parents not updating while installing an add-in](https://forums.modx.com/thread/80500/category-parents-not-updating-while-installing-an-add-in)**
>
> The MODX Forum Archive contains a wide ranging variety of questions and rich answers related to MODX Revolution, MODX Evolution and MODX Cloud. Ask new questions and find recent answers at community.modx.com

Anyway… in case people find it on the new forums, responses were:

> splittingred: At this time, to my knowledge, any levels more than 2 deep for RELATED\_OBJECTS wont work. OpenGeek can give you more information on that.

> bobray: …TBH, when I have trouble, I usually end up doing it in a Script resolver where I know it will work. There, you can create the category and get its ID before adding the children to it (or just set their ’parent’ fields as you create them).

---

<div class="post-metadata">

**Author:** ![bruno17](https://community.modx.com/user_avatar/community.modx.com/bruno17/32/71_2.png) [@bruno17](https://community.modx.com/u/bruno17)\
**Post date:** [January 15, 2021, 7:32am UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/3 "2021-01-15T07:32:44Z")

</div>

I’m building with GPM now and use my migxGpmHelper  
[GitHub - Bruno17/migxGpmHelper: Helps to build GPM (Git-Package-Management) Projects. Exports elements and files and updates the config.json.](https://github.com/Bruno17/migxGpmHelper) to collect categories and elements into the config.json  
this is the processor, which does that stuff  
[migxGpmHelper/core/components/migxgpmhelper/processors/mgr/default/writetofiles.php at 3abde5971471ac51a2d1a0de9faac3f719ab57e3 · Bruno17/migxGpmHelper · GitHub](https://github.com/Bruno17/migxGpmHelper/blob/3abde5971471ac51a2d1a0de9faac3f719ab57e3/core/components/migxgpmhelper/processors/mgr/default/writetofiles.php)

I have this PR included in my GPM, so I can work with elements in the db and GPM doesn’t touch my elements when activated this settings.

> <https://github.com/theboxer/Git-Package-Management/pull/133>
>
> Sometimes, I want to use GPM to just build a package without altering anything w…ithin MODX. 
> With this systemsettings enabled, GPM scips creating or updating elements and other stuff in the MODX installation.

---

<div class="post-metadata">

**Author:** ![jaredfhealy](https://community.modx.com/user_avatar/community.modx.com/jaredfhealy/32/456_2.png) [@jaredfhealy](https://community.modx.com/u/jaredfhealy)\
**Post date:** [January 15, 2021, 3:59pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/4 "2021-01-15T15:59:26Z")

</div>

Thanks Bruno! I’ll take a look later today when I have a chance.

---

<div class="post-metadata">

**Author:** ![bobray](https://community.modx.com/user_avatar/community.modx.com/bobray/32/46_2.png) [@bobray](https://community.modx.com/u/bobray)\
**Post date:** [January 15, 2021, 7:42pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/5 "2021-01-15T19:42:19Z")

</div>

It’s very easy to do it in a resolver if you know the name of the category and the name of the parent category you want:

```auto
$parentCategoryName = 'someCategory';
$childCategoryName = 'someSubCategory';

$parentObject = $modx->getObject('modCategory', array('category' => $parentCategoryName);
$childObject = $modx->getObject('modCategory', array('category' => $childCategoryName);

$childObject->set('parent', $parentObject->get('id'))
$childObject->save();

```

BTW, I suspect that the original problem is caused by the fact that the `modCategory` object has no `name` field and uses a field called `category` to hold the name of the category.

I should also mention that when MyComponent creates a project for you, it automatically creates a generic resolver you can use for stuff like this.

---

<div class="post-metadata">

**Author:** ![bruno17](https://community.modx.com/user_avatar/community.modx.com/bruno17/32/71_2.png) [@bruno17](https://community.modx.com/u/bruno17)\
**Post date:** [January 15, 2021, 7:57pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/6 "2021-01-15T19:57:10Z")

</div>

but then you will need to know all subCategories and you will need to resolve the category - ids of all the elements somehow

---

<div class="post-metadata">

**Author:** ![jaredfhealy](https://community.modx.com/user_avatar/community.modx.com/jaredfhealy/32/456_2.png) [@jaredfhealy](https://community.modx.com/u/jaredfhealy)\
**Post date:** [January 16, 2021, 3:14pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/7 "2021-01-16T15:14:43Z")

</div>

Thanks for the contribution here. I think things like this will be helpful so that the new community site has more current and relevant discussion with examples.

---

<div class="post-metadata">

**Author:** ![jaredfhealy](https://community.modx.com/user_avatar/community.modx.com/jaredfhealy/32/456_2.png) [@jaredfhealy](https://community.modx.com/u/jaredfhealy)\
**Post date:** [January 16, 2021, 3:34pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/8 "2021-01-16T15:34:33Z")

</div>

Definitely benefits and challenges with both approaches. I think this is a good discussion for Extra developers to find though.

To summarize my understanding:

1. The current MODX Transport system does NOT handle child categories when creating a transport package.
2. One way to deal with it is a custom and dynamic build process. In your case based on GPM.  
a. Pro: Dynamic, handles categories and sub categories.  
b. Con: You have to learn GPM, and use your PR.
3. Another way is a scripted resolver per Bobray’s method  
a. Pro: Simpler for someone to grasp on a small scale  
b. Con: Not as scalable

I think if you went the resolver script route, if you have a small number of categories, you could probably create a little hash map to show the parent child relationships. Then just loop through and set the parent on each. You’d have to store the category name since they would likely have different IDs when installed.

Anyway. Always multiple ways to do things. So, thanks for both suggestions and feedback. Very helpful.

---

<div class="post-metadata">

**Author:** ![bruno17](https://community.modx.com/user_avatar/community.modx.com/bruno17/32/71_2.png) [@bruno17](https://community.modx.com/u/bruno17)\
**Post date:** [January 16, 2021, 4:41pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/9 "2021-01-16T16:41:10Z")

</div>

another good option is to use teleport with the elements template.  
I didn’t try it, yet, but I think, this could do what you need, too.

> <https://github.com/modxcms/teleport/blob/2519508f1dae16a4b7a136511c9b68501c5d2eab/tpl/elements.tpl.json>

---

<div class="post-metadata">

**Author:** ![bobray](https://community.modx.com/user_avatar/community.modx.com/bobray/32/46_2.png) [@bobray](https://community.modx.com/u/bobray)\
**Post date:** [January 16, 2021, 6:55pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/10 "2021-01-16T18:55:44Z")

</div>

This is from the example config file for MyComponent:

```auto
'categories' => array(
        'Example' => array(
            'category' => 'Example',
            'parent' => '', /* top level category */
        ),
        'category2' => array(
            'category' => 'Category2',
            'parent' => 'Example', /* nested under Example */
        )
    ),

```

You can add as many as you want and they can be nested as far as you want without adding another level to the array as long as the parent always appears in the list before the child. The resolver will be created automatically.

The downside to MyComponent is the effort it takes to get used to using it. It’s too bad the video from the first ModExpo I did on MyComponent was lost. I created a new transport package from scratch complete with snippets, chunks, plugins, resources, and lexicon strings to internationalize the output. It took about 20 minutes. Basically, you just take the “Example” config file, delete the stuff you don’t need, and modify the stuff you do need.

---

<div class="post-metadata">

**Author:** ![evanroman](https://community.modx.com/letter_avatar_proxy/v4/letter/e/8491ac/32.png) [@evanroman](https://community.modx.com/u/evanroman)\
**Post date:** [March 22, 2024, 5:21pm UTC](https://community.modx.com/t/how-to-build-a-transport-vehicle-for-a-parent-child-category-relationship/3492/11 "2024-03-22T17:21:41Z")

</div>

In your code, to ensure proper packaging of nested categories and chunks, consider using the `addOne` method for adding chunks to categories. Additionally, explore Category Closures for establishing relationships between categories during packaging. This approach might address your issue effectively, potentially benefiting moving-services.
