How to Create Custom Models in MODx 3.x?

I’m trying to learn the proper, pure-MODx method for creating custom models. I know there are a few extras out there that can help with this but I’d like to understand the fundamentals for myself.

I have it on good authority that the docs at Generating the Model - Custom Models | MODX Documentation are outdated. Are the docs for creating a schema (Defining the Database and Tables - Defining a Schema | MODX Documentation) also outdated or is this still applicable to 3.x?

Once one has a schema, I understand that the model-generating step involves running a composer script called parse-schema through the proxy file core/vendor/bin/xpdo. Per the --help option: parse-schema [options] [--] <platform> <schema_file> [<path>].

Here’s an example I was given:
core/vendor/bin/xpdo parse-schema --config=core/model/schema/config.php --update=1 --psr4=MODX\\\\ mysql core/model/schema/modx.mysql.schema.xml core/src/

There’s a few things I’m not clear about here. What should be in the config file? Is update=1 only necessary if the model has been generated previously and, if so, should it be left out when generating the model for the first time? I understand the --psr4 option needs a namespace passed to it: should that be the same namespace I’m using in my CMP or does it need to be MODX and why does it have four slashes after it? Does it matter where the files are generated? 2.x had them in core/components; is that still where they should go?

Once the model is created, is the method shown here for loading the package still applicable to 3.x?
https://docs.modx.com/3.x/en/extending-modx/xpdo/custom-models/loading-package

If I can get this figured out, I plan to update the docs with a new tutorial.

Thanks in advance!

You generally don’t need to modify the config file. It just gets the autoloader, sets up the DB connection, and clears the properties array.

You normally want the update flag on so it will update your class files when you call parseSchema().

I think core/components/ is still the preferred location.

There’s some information here that might help. You might also take a look at the the code of ClassExtender extra, which automates much of what you’re doing.

1 Like

This is outdated as well. Refer to the examples at Namespaces - Extending MODX | MODX Documentation for up-to-date approaches to loading a custom model or adding a src directory to the autoloader. I’ll put together some more information and examples for you as soon as possible.

1 Like

This page of the MODX documentation has been adapted to MODX 3:

https://docs.modx.com/3.x/en/extending-modx/tutorials/using-custom-database-tables

It contains a sample schema, a script to parse the schema with $generator->parseSchema() and information about the “bootstrap.php” file to add the package when MODX is initialized.

2 Likes

Thanks for pointing this out! I will add information about using the xPDO CLI script instead of having to programmatically call $generator->parseSchema…

FWIW, this is not a “composer script”—composer scripts are just a convenient way to keep them handy so you can run them during development. It’s just a CLI script.

I was able to successfully complete this tutorial and create a working custom model. I’d be interested in doing it as a CLI script as well but this definitely works. Thanks to all of you for the help and the work you do, and thanks to whoever wrote that tutorial!

Ah, I see. Thanks for the clarification!

What’s the procedure for updating an existing model? Is there a tutorial somewhere for that? I need to add a field and modifying an existing field.

For the DB, you can delete tables and do the same steps you used before to create them, or you can modify the tables manually to match the new schema.

For the class files, it should be just be a matter of updating the schema and performing the same steps you did before to generate the files.

usually, I add new fields to my schema and hit the button ‘add fields’ in the MIGX CMP.
Not sure, if that works on 3.x

here is the code, which adds new fields from schema to the table