Error connecting custom table to MIGXdb

I created a Package using MIGX Package Manager along with a Custom Manager Page by following the guides linked below.

I have done something wrong though as accessing the CMP outputs Undefined on the Tab and the Description bar, and the Grid is empty stating No items found.

At this point it may be relevant that I had this working as a single table but I’d prefer to join tbl.catalog_products to tbl.catalog_options.

The MODX Error Log shows errors in xpdo.class.php No class specified for loadClass, Could not load class, ::getSelectColumns() is not a valid static method (detailed error below).

There are no errors in the php_error.log.

Outline of steps taken

  • created an empty package with name ‘catalog’ using Create Package’ in MIGX Package Manager

  • pasted the content of my schema.xml file on the Xml Schema tab and selecting ‘Save Schema’

  • selecting Parse Schema creates a new directory at ‘/components/model/catalog/’ with what look like the correct mysql and schema files.

  • selecting ‘create Tables’ creates the database tables successfully

  • select ‘Add Item’ on the MIGX tab and enter Name = product, unique MIGX ID = product on Settings tab, enter Classname = product on the MIGXdb-Settings tab as per ysanmiguel’s post at
    Connect custom Table with MigXdb - #7 by ysanmiguel

  • edit the new Item ‘product’ and add ‘Formtabs’ fieldname = ‘name’, caption = ‘name’

Actually, I don’t think it matters what else I added if the MODX Error is Could not load class.

Can anyone point me in the right direction please?

Thanks

Environment

  • MODX 2.8.3

  • MIGX 3.0.0-alpha5

  • pdoTools 2.13.2-pl

  • PHP 7.4.29

  • MySQL MariaDB 10.5.15

My schema.xml file

<?xml version="1.0" encoding="UTF-8"?>
<model package="catalog" baseClass="xPDOObject" platform="mysql" defaultEngine="INNODB" version="1.1">
    <!-- define object
        - prefix tables with package name to group and separate them from modx core tables or tables created by other packages
    -->
    <object class="product" table="catalog_products" extends="xPDOSimpleObject" >
        <!-- available fields
             - category
             - name
             - colour
             - description
             - image
        -->
        <field key="category" dbtype="varchar" precision="255" phptype="string" null="false" default="" index="index" />
        <field key="name" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        <field key="colour" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        <field key="description" dbtype="text" phptype="string" index="fulltext" />
        <field key="image" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        <!-- used by MIGX -->        
        <field key="deleted" dbtype="tinyint" precision="1" attributes="unsigned" phptype="integer" null="false" default="0" />
        <field key="published" dbtype="tinyint" precision="1" attributes="unsigned" phptype="integer" null="false" default="0" /> 
        <!-- good practice for tracking -->       
        <field key="createdon" dbtype="datetime" phptype="datetime" null="true"/>
        <field key="createdby" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
        <field key="editedon" dbtype="datetime" phptype="datetime" null="true"/>
        <field key="editedby" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
        <!-- link related tables
             - base table (catalog_products) to subordinate table (catalog_options)
             - note 'id' is created automatically
        -->
        <composite alias="option" class="option" local="id" foreign="rel_product_id" cardinality="many" owner="local" /> 
        
        <aggregate alias="CreatedBy" class="modUser" local="createdby" foreign="id" cardinality="one" owner="foreign"/>
        <aggregate alias="EditedBy" class="modUser" local="editedby" foreign="id" cardinality="one" owner="foreign"/>
    </object>
    <!-- define object
         - prefix tables with package name to group and separate them from MODX core tables or tables created by other packages
    -->
    <object class="option" table="catalog_options" extends="xPDOSimpleObject">
        <!-- available fields
             - rel_product (catalog_products.id)
             - name (dimensions)
             - price
        -->
        <!-- related core table id -->
        <field key="rel_product_id" dbtype="int" precision="11" phptype="integer" null="false" default=""/>
        <field key="name" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        <field key="price" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        <!-- used by MIGX -->        
        <field key="deleted" dbtype="tinyint" precision="1" attributes="unsigned" phptype="integer" null="false" default="0" />
        <field key="published" dbtype="tinyint" precision="1" attributes="unsigned" phptype="integer" null="false" default="0" /> 
        <!-- used by MIGX -->         
        <field key="createdon" dbtype="datetime" phptype="datetime" null="true"/>
        <field key="createdby" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
        <field key="editedon" dbtype="datetime" phptype="datetime" null="true"/>
        <field key="editedby" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
        <!-- link related tables
             - subordinate table (catalog_options) back to base table (catalog_product)
             - note 'id' is created automatically
        -->
        <aggregate  alias="Product" class="product" local="rel_product_id" foreign="id" cardinality="one" owner="foreign" /> 
        
        <aggregate alias="CreatedBy" class="modUser" local="createdby" foreign="id" cardinality="one" owner="foreign"/>
        <aggregate alias="EditedBy" class="modUser" local="editedby" foreign="id" cardinality="one" owner="foreign"/>
    </object>
</model>

Full MODX Error Log

[2022-05-17 21:20:19] (ERROR @ F:\webs\domain.co.uk\subdomains\stage\httpsdocs\core\xpdo\xpdo.class.php : 592) No class specified for loadClass
[2022-05-17 21:20:19] (ERROR @ F:\webs\domain.co.uk\subdomains\stage\httpsdocs\core\xpdo\xpdo.class.php : 1618) Could not load class 
[2022-05-17 21:20:19] (ERROR @ F:\webs\domain.co.uk\subdomains\stage\httpsdocs\core\xpdo\xpdo.class.php : 592) No class specified for loadClass
[2022-05-17 21:20:19] (ERROR @ F:\webs\domain.co.uk\subdomains\stage\httpsdocs\core\xpdo\xpdo.class.php : 592) No class specified for loadClass
[2022-05-17 21:20:19] (ERROR @ F:\webs\domain.co.uk\subdomains\stage\httpsdocs\core\xpdo\xpdo.class.php : 762) ::getSelectColumns() is not a valid static method.

Guides

In this tab, you also have to set the field “Package” to catalog.

My apologies, I missed that from my first post.

Package is already set to catalog for both the product and option MIGX items.

Any further suggestions I can investigate?

image

Can you provide the complete Json of your MIGX configuration?
(Right-click on the config → select “Export/Import” → copy the content of the field “Json”.)

There are two MIGX Items, product and option. Product is the main one, option is to be nested inside product so that each product can have multiple entries in the option table.

updated to add

The current JSON does not include all the database fields, I deleted my original attempts and reverted to trying to get a couple of fields working for each.

product json

{
  "formtabs":[
    {
      "MIGX_id":13,
      "caption":"product",
      "print_before_tabs":"0",
      "fields":[
        {
          "MIGX_id":56,
          "field":"name",
          "caption":"name",
          "description":"",
          "description_is_code":"0",
          "inputTV":"",
          "inputTVtype":"",
          "validation":"",
          "configs":"",
          "restrictive_condition":"",
          "display":"",
          "sourceFrom":"config",
          "sources":"",
          "inputOptionValues":"",
          "default":"",
          "useDefaultIfEmpty":"0",
          "pos":1
        }
      ],
      "pos":1
    }
  ],
  "contextmenus":"",
  "actionbuttons":"addItem",
  "columnbuttons":"update||duplicate||publish||unpublish||remove",
  "filters":"",
  "extended":{
    "migx_add":"",
    "disable_add_item":"",
    "add_items_directly":"",
    "formcaption":"",
    "update_win_title":"",
    "win_id":"product",
    "maxRecords":"",
    "addNewItemAt":"bottom",
    "media_source_id":"",
    "multiple_formtabs":"",
    "multiple_formtabs_label":"",
    "multiple_formtabs_field":"",
    "multiple_formtabs_optionstext":"",
    "multiple_formtabs_optionsvalue":"",
    "actionbuttonsperrow":4,
    "winbuttonslist":"",
    "extrahandlers":"",
    "filtersperrow":4,
    "packageName":"catalog",
    "classname":"product",
    "task":"",
    "getlistsort":"",
    "getlistsortdir":"",
    "sortconfig":"",
    "gridpagesize":"",
    "use_custom_prefix":"0",
    "prefix":"",
    "grid":"",
    "gridload_mode":1,
    "check_resid":1,
    "check_resid_TV":"",
    "join_alias":"",
    "has_jointable":"no",
    "getlistwhere":"",
    "joins":"",
    "hooksnippets":"",
    "cmpmaincaption":"",
    "cmptabcaption":"",
    "cmptabdescription":"",
    "cmptabcontroller":"",
    "winbuttons":"",
    "onsubmitsuccess":"",
    "submitparams":""
  },
  "permissions":{
    "apiaccess":"",
    "view":"",
    "list":"",
    "save":"",
    "create":"",
    "remove":"",
    "delete":"",
    "publish":"",
    "unpublish":"",
    "viewdeleted":"",
    "viewunpublished":""
  },
  "fieldpermissions":"",
  "columns":[
    {
      "MIGX_id":1,
      "header":"name",
      "dataIndex":"name",
      "width":"",
      "sortable":"false",
      "show_in_grid":1,
      "customrenderer":"",
      "renderer":"",
      "clickaction":"",
      "selectorconfig":"",
      "renderchunktpl":"",
      "renderoptions":"",
      "editor":""
    },
    {
      "MIGX_id":2,
      "header":"published",
      "dataIndex":"published",
      "width":"",
      "sortable":"false",
      "show_in_grid":1,
      "customrenderer":"",
      "renderer":"this.renderClickCrossTick",
      "clickaction":"",
      "selectorconfig":"",
      "renderchunktpl":"",
      "renderoptions":"",
      "editor":""
    },
    {
      "MIGX_id":3,
      "header":"id",
      "dataIndex":"id",
      "width":"",
      "sortable":"false",
      "show_in_grid":1,
      "customrenderer":"",
      "renderer":"",
      "clickaction":"",
      "selectorconfig":"",
      "renderchunktpl":"",
      "renderoptions":"",
      "editor":""
    }
  ],
  "category":""
}

option json

{
  "formtabs":[
    {
      "MIGX_id":14,
      "caption":"option",
      "print_before_tabs":"0",
      "fields":[
        {
          "MIGX_id":57,
          "field":"name",
          "caption":"name",
          "description":"",
          "description_is_code":"0",
          "inputTV":"",
          "inputTVtype":"",
          "validation":"",
          "configs":"",
          "restrictive_condition":"",
          "display":"",
          "sourceFrom":"config",
          "sources":"",
          "inputOptionValues":"",
          "default":"",
          "useDefaultIfEmpty":"0",
          "pos":1
        },
        {
          "MIGX_id":58,
          "field":"price",
          "caption":"price",
          "description":"",
          "description_is_code":"0",
          "inputTV":"",
          "inputTVtype":"",
          "validation":"",
          "configs":"",
          "restrictive_condition":"",
          "display":"",
          "sourceFrom":"config",
          "sources":"",
          "inputOptionValues":"",
          "default":"",
          "useDefaultIfEmpty":"0",
          "pos":2
        }
      ],
      "pos":1
    }
  ],
  "contextmenus":"",
  "actionbuttons":"",
  "columnbuttons":"",
  "filters":"",
  "extended":{
    "migx_add":"",
    "disable_add_item":"",
    "add_items_directly":"",
    "formcaption":"",
    "update_win_title":"",
    "win_id":"option",
    "maxRecords":"",
    "addNewItemAt":"bottom",
    "media_source_id":"",
    "multiple_formtabs":"",
    "multiple_formtabs_label":"",
    "multiple_formtabs_field":"",
    "multiple_formtabs_optionstext":"",
    "multiple_formtabs_optionsvalue":"",
    "actionbuttonsperrow":4,
    "winbuttonslist":"",
    "extrahandlers":"",
    "filtersperrow":4,
    "packageName":"catalog",
    "classname":"option",
    "task":"",
    "getlistsort":"",
    "getlistsortdir":"",
    "sortconfig":"",
    "gridpagesize":"",
    "use_custom_prefix":"0",
    "prefix":"",
    "grid":"",
    "gridload_mode":1,
    "check_resid":1,
    "check_resid_TV":"",
    "join_alias":"",
    "has_jointable":"yes",
    "getlistwhere":"",
    "joins":"",
    "hooksnippets":"",
    "cmpmaincaption":"",
    "cmptabcaption":"",
    "cmptabdescription":"",
    "cmptabcontroller":"",
    "winbuttons":"",
    "onsubmitsuccess":"",
    "submitparams":""
  },
  "permissions":{
    "apiaccess":"",
    "view":"",
    "list":"",
    "save":"",
    "create":"",
    "remove":"",
    "delete":"",
    "publish":"",
    "unpublish":"",
    "viewdeleted":"",
    "viewunpublished":""
  },
  "fieldpermissions":"",
  "columns":[
    {
      "MIGX_id":1,
      "header":"name",
      "dataIndex":"name",
      "width":"",
      "sortable":"false",
      "show_in_grid":1,
      "customrenderer":"",
      "renderer":"",
      "clickaction":"",
      "selectorconfig":"",
      "renderchunktpl":"",
      "renderoptions":"",
      "editor":""
    },
    {
      "MIGX_id":2,
      "header":"price",
      "dataIndex":"price",
      "width":"",
      "sortable":"false",
      "show_in_grid":1,
      "customrenderer":"",
      "renderer":"",
      "clickaction":"",
      "selectorconfig":"",
      "renderchunktpl":"",
      "renderoptions":"",
      "editor":""
    }
  ],
  "category":""
}

When I test it with these configs, everything works.

Maybe the “Parameters” field in your menu item is wrong? (&configs=product).

I have the Parameters field is set to &configs=catalog because catalog is the package name defined in the schema.

<?xml version="1.0" encoding="UTF-8"?>
<model package="catalog" ...

Changing it to &configs=product returns the same error No class specified for loadClass.

Product is the first class in the schema rather than the package name <object class="product" ....

The menu should use the package name according to the two tutorials linked above - this is correct isn’t it?

When you edit your config, can you select db fields, on the columns tab or is the dropdown with the db fields empty?

the configs - parameter has to be the name of your MIGX configuration

The dropdown on the Columns tab shows the database fields.

image

My apologies to @halftrainedharry, where I said

It appears I must have misread the timestamps in the MODX error log. And also didn’t recognise the update to the CMP - it still shows undefined twice.

image

Now I realise, with the top menu Parameters set to &configs=product, selecting the Add Item button opens a lightwindow to enter data which is stored in the database when saved.

Now I need to go back an add the full set of Product fields, and figure how to join the Options table.

Thanks both for your help thus far, it’s much appreciated.

    "cmpmaincaption":"",
    "cmptabcaption":"",
    "cmptabdescription":"",

you have to set this fields for the CMP main caption, the tab caption and the description of what they can do in that tab

Perfect thank you.

I missed this throughout because

  • the MIGX > CMP-Settings tab isn’t visible (and I didn’t hit the right slider arrow)
  • the terms used for cmpmaincaption etc. in the JSON example I was following were worded strangely and I didn’t recognse the significance
  • I’m an idiot

Thanks again everyone.

I’ll post a copy of my JSON configuration once complete in case it is useful for anyone in future.