SortableRelation with plugin extension

In the documentation, there is an option to sort M:N relations using SortableRelation. For example, categories and books. The book has several categories.
If all relationships are defined in one plugin, then everything works correctly.
If I create two plugins. One plugin contains categories. The second plugin contains books. I will extend the category model with a relation to books. Subsequently, sorting books in categories using SortableRelation does not work.

What is the problem? Is there a bug in OctoberCMS?

Extending the category model:

\SecondPlugin\Models\Category::extend(function ($model) {
        $model->belongsToMany['books'] = [
            Book::class,
            'table'    => 'second_plugin_category_book',
            'key'      => 'category_id',
            'otherKey' => 'product_id',
            'pivotSortable' => 'sort_order'
        ];
});

The second_plugin_category_book table has columns:

$table->increments('id')->unsigned();
$table->integer('category_id')->nullable()->unsigned();
$table->integer('product_id')->nullable()->unsigned();
$table->integer('sort_order')->nullable()->unsigned();

In config_relation I have:

books:
   ...
   structure:
      showTree: false
      showReorder: true
      maxDepth: 1

There is one caveat with this approach at the moment. The sorting will only work on existing records since the sort_order is within the deferred binding table. We are working on a solution to this in a later version.

Could it be that in your extended example, the primary record does not exist yet?

I only sort in category update action. So the category (primary record) exists. Books (secondary record) also exist.
If I have both categories and books in one plugin. There is a sort_order field in the data that is sent when sorting.
If I have categories and books split into two plugins. The sort_order field is missing in the data sent when sorting.

Try calling the resetSortableOrdering method on the model to repair it. Hopefully it helps.

The resetSortableOrdering method is in the Sortable class. I am using the SortableRelation class.

GitHub link to a simple project that simulates the error:
https://github.com/xmelic8/OctoberCMS-Extend-plugins-with-relation

If the category binding is - the book is created in the Category class (Fiestplugin\Models\Category, line 33). Then book sorting works. Data sent to the server:

If the binding is a category - the book is created as an extension of the Category model (Secondplugin\Plugin.php, line 26). Then the sorting doesn’t work. The sort_order field is missing from the data:

The images are from a request to the server that is sent when sorting.

Oh, you’re right, sorry about that.

Can you reproduce it using the test plugin? In the Galleries → Event tab, the countries use the SortableRelation trait.

Yes, this is how (in the test plugin) sorting works. Because all models are in one plugin. The problem occurs when Galleries is in one plugin and Event is in another plugin.
If we extend the plugin and add sessions (Gallery → Event), the sorting does not work.

Can you share the code you used to extend the plugin?

I put the source code on github.
https://github.com/xmelic8/OctoberCMS-Extend-plugins-with-relation/tree/master

The “firstplugin” folder is the base plugin containing the category model. The “secondplugin” folder is an extension plugin. Contains a model for the book. The extension code is in the file “secondplugin/Plugin.php”. Model, controller and form extensions. The SortableRelation property is located directly in the “firstmodel/model/Category” model.

Thanks, we reproduced it finally and have a patch coming for it:

1 Like

Yes, I confirm that the fix is working. Thanks, great job :slight_smile:
Will you add a fix in the next build?

Confirmed this will be available in v3.4.18