extjs model (many-to-many) s_filter_options assoziation speichern

ich bastel gerade an eine plugin der in seine eigenen tabelle eine assoziation zu shopware tabelle s_filter_options haben soll, und dazu ein shopware-backend maske zum editieren. (die doctrine entity zu s_filter_options ist Shopware\Models\Property\Option und extjs model ist Shopware.apps.Article.model.PropertyOption)

also habe ich in meine doctrine entity folgenden feld:

/**
 * @ORM\ManyToMany(targetEntity="Shopware\Models\Property\Option")
 * @ORM\JoinTable(name="foo_tab_tab_filters")
 */
private $filters;

und mein extjs modelle:

Ext.define('Shopware.apps.FooTab.model.Filter', {
    extend: 'Shopware.apps.Article.model.PropertyOption',
    configure: function() {
       return {
          related: 'Shopware.apps.FooTab.view.detail.Filter'
       }
    }
});

Ext.define('Shopware.apps.FooTab.model.Tab', {
    extend: 'Shopware.data.Model',

    configure: function() {
        return {
            controller: 'FooTab',
            detail: 'Shopware.apps.FooTab.view.detail.Tab'
        };
    },

    fields: [
        { name: 'id', type: 'int', useNull: true },
        { name: 'name', type: 'string'},
    ],

    associations: [
        {
            relation: "ManyToMany",
            type: "hasMany",
            model: "Shopware.apps.FooTab.model.Filter",
            name: "getFilter",
            associationKey: "filters"
        }
    ]
});

denn kompletten code kann man hier finden: GitHub - hlb-schmidt/FooTab

 

problem 1 : ein bug?

wenn ich in shopware-backend durch Artikel->FooTab - was durch diesen plugin addiert wird - eine neue eintrag hinzufügen will, kommt fehler:

Shopware.apps.FooTab.model.Filter has to be an instance of Shopware.data.Model

und weil Shopware.apps.FooTab.model.Filter erweitert Shopware.apps.Article.model.PropertyOption, müssen wir Shopware.apps.Article.model.PropertyOption anpassen? oder was ist der richtige weg um diesen fehler?

hab es zum testen mal direkt in shopware code angepasst:

diff --git a/themes/Backend/ExtJs/backend/article/model/property_option.js b/themes/Backend/ExtJs/backend/article/model/property_option.js
index edc2b10..6010bf6 100644
--- a/themes/Backend/ExtJs/backend/article/model/property_option.js
+++ b/themes/Backend/ExtJs/backend/article/model/property_option.js
@@ -39,7 +39,7 @@ Ext.define('Shopware.apps.Article.model.PropertyOption', {
     * Extends the standard Ext Model
     * @string
     */
- extend: 'Ext.data.Model',
+ extend: 'Shopware.data.Model',

     /**
      * Fields array which contains the model fields

und die fehlermeldung ist weg…
(ist problem 2 wegen dies?)

 

problem 2 : der eigentliche problem

wenn ich jetzt in shopware-backend mit Artikel->FooTab eine neue eintrag hinzufüge, und filter(s) auswähle, bekomme ich beim speichern die meldung “eintrag wurde erfolgreich gespeichert”, aber tabelle foo_tab_tab_filters bleibt trotzdem leer :frowning:

was mache ich falsch (bzw. fehlt) das die filter assoziatonen nicht automagisch ins foo_tab_tab_filters gespeichert werden?

was will denn extjs überhaupt in meine doctrine modell haben, um diese assoziation zu speichern? setFilters()? addFilter()?

muss ich was in meine extjs model fürs speichern addieren?

ich dachte ich hätte alles genau so gemacht wie in Backend Components - Associations

und was ist überhaupt die name in associations in extjs model? in Backend Components - Associations ist zbs. für category getCategory drin, aber getCategory ist nirgens anderswo definiert…

ps. diese wurde mit shopware 5.3.27 getestet.

paar tests für doctrine entity speichern in frontend controller

addFilter() funktionert:

$em = $this->getModelManager();

$tab = new Tab();
$tab->setName("test1");
$filter = $em->find("Shopware\Models\Property\Option", 1046);
$tab->addFilter($filter);

$em->persist($tab);
$em->flush();

 

setFilter() mit kopie von filters funktioniert auch:

$em = $this->getModelManager();

$tab = new Tab();
$tab->setName("test2");
$filter = $em->find("Shopware\Models\Property\Option", 1046);
$filters = $tab->getFilters();
$filters->add($filter);
$tab->setFilters($filters);

$em->persist($tab);
$em->flush();

 

aber setFilter() mit neuen filters funktioniert NICHT:

$em = $this->getModelManager();

$tab = new Tab();
$tab->setName("test3");
$filter = $em->find("Shopware\Models\Property\Option", 1046);
$filters = new \Doctrine\Common\Collections\ArrayCollection();
$filters->add($filter);
$tab->setFilters($filters);

$em->persist($tab);
$em->flush();

 

mysql> select * from foo_tab_tab left join foo_tab_tab_filters on id = tab_id;
+----+-------+--------+-----------+
| id | name | tab_id | option_id |
+----+-------+--------+-----------+
| 1 | test1 | 1 | 1046 |
| 2 | test2 | 2 | 1046 |
| 3 | test3 | NULL | NULL |
+----+-------+--------+-----------+

ich wundere wieso das letztere nicht die filters speichert, und ob extjs genau dies benutzt zum speichern…

jup, shopware-backend speichert die model/entity/ding durch hier:

und debug der “$method gets value $value” in fromArray() gibt mir dies:

setFilters gets value Array
(
    [0] => stdClass Object
        (
            [__CLASS__] => Shopware\Models\Property\Option
            [values] => Array
                (
                    [0] => Shopware\Models\Property\Value
                )

            [attribute] =>
            [id] => 1138
            [name] => Antrieb
            [filterable] => 1
            [groups] => Array
                (
                    [0] => Shopware\Models\Property\Group
                )

            [relations] => Array
                (
                    [0] => Shopware\Models\Property\Relation
                )

        )

)

 

also bin ich 99% sicher das mein problem ist “test3”, wenn setFilters() eine neue arraycollection bekommt, wird es nicht gespeichert…

aber wenn eine (leere!) arraycollection mit getFilters() geholt wird, und dann filter da rein addiert wird, und dann zurück an setFilters() gefüttert wird, wird die neue filter gespeichert! was ist denn da der unterschied? mit print_r kann ich keine erkennen…

whatever, diese workaround erlaubt test3 zu speichern, und dadurch auch extjs.

public function setFilters ($filters)
{
	$this->filters->clear();
	foreach ($filters as $filter) {
		$this->filters->add($filter);
	}
}

 

ps. leider ist jetzt test2 kaputt…