Backend Modul schreiben??

Hy, ich versuche mich gerade dabei ein Backend Modul zu schreiben. Die Funktion soll ganz Simpel sein. Ein Grid aus einer Datenbank 1:1 mit Editierfunktion der einzelnen Felder(Spalten) und das löschen der Einträge. Leider fängt es schon beim Tut. aus der Wiki an. Ich versteh nur Bahnhof. :wink: Komme aus dem PHP, C#, Delphi, Smarty, Jquery, CSS, HTML Bereich. Also Frontend kein Problem. Aus dem Tut. SwagProduct. Kann ich null entnehmen. Die app.js ist wie spanisch :wink: Sprich der Einstieg ist für mich gerade nicht zu finden. Vielleicht habe ich auch nur ein Knoten im Kopf. Aber wie muss ich überhaupt anfangen? Also einfach ein Fenster, mit Grid. z.b. Beste Grüße

Hi, 1. Erstelle einen Menüpunkt im Backend : über die Methode “createMenuItem” $this-\>createMenuItem( array( 'label' =\> 'Dein Plugin Name', 'controller' =\> 'DeinControllerName', 'class' =\> 'DeineClassCssCKlasseFürEinIcon', 'action' =\> 'Index', 'parent' =\> $this-\>Menu()-\>findOneBy('label', 'Einstellung') ) ); Damit erzeugst du einen Menüeintrag für den Reiter Einstellungen im Backend. Und wenn du auf den Eintrag klickst wird die IndexAction aus deinem Controller aufgerufen. Dann ein Event für dein backend-controller: $this-\>subscribeEvent( 'Enlight\_Controller\_Dispatcher\_ControllerPath\_Backend\_DeinControllerName', 'onGetUiControllerPath' ); Methode für dein Backend Controller: public function onGetUiControllerPath(Enlight\_Event\_EventArgs $args) { /\*\* register template dir \*/ $this-\>Application()-\>Template()-\>addTemplateDir( $this-\>Path() . 'Views/' ); $this-\>registerCustomModels(); return $this-\>Path() . '/Controllers/Backend/DeinControllerName.php'; } Somit hast du mal, das registriert was für dein Aufruf für den Controller getan werden muss. Natürlich musst du die anderen Sachen die relevant sind für eine Bootstrap.php noch schreiben. Wichtig: Dein Backend Controller für die GUI leitet von der Shopware_Controllers_Backend_ExtJs ab. Für die Views brauchst du folgende Ordner-Struktur: Plugin-Ordner/Views/backend/Dein_Controller_Name Nicht vergessen ExtJs verwendet “_” als CamelCase (zumindest in Shopware muss es so sein). Danach legts du in dem Verzeichnis eine “app.js” an. // {namespace name=backend/ApplicationName} // {block name=backend/ApplicationName/application} Ext.define('Shopware.apps.ApplicationName', { name: 'Shopware.apps.ApplicationName', extend: 'Enlight.app.SubApplication', loadPath: '{url action=load}', bulkLoad: true, controllers: ['Main'], views: [], stores: [], models: [], launch: function () { var me = this, mainController = me.getController('Main'); return mainController.mainWindow; } }); // {/block} Als nächstes erstellst du das Verzeichnis: “controller” mit der JS Datei main.js // {namespace name=backend/ApplicationName/controller} // {block name=backend/ApplicationName/controller/main} Ext.define('Shopware.apps.ApplicationName.controller.Main', { extend: 'Ext.app.Controller', mainWindow: null, init: function () { var me = this; me.mainWindow = me.subApplication.getView('Main').create().show(); me.callParent(arguments); } }); // {/block} Somit sollte eigentlich schon ein Fenster aufgehen. Man sollte sich mit Extjs etwas auskennen und auch mit den eigenheiten von JS selbst. Oder wenn man es lernen will viel Zeit mitbringen :slight_smile: Ich hoffe ich habe nichts vergessen. Falls doch einfach schreiben, wenn ich Zeit finden Antworte ich auch :slight_smile: Grüß Basti

Hallo Basti, dafür für den Tipp. Leider bekomme ich dadurch nur das “… wird geladen” zu sehen. app.js // {namespace name="backend/mein\_modul\_name/view/main"} // {block name="backend/mein\_modul\_name/application"} Ext.define('Shopware.apps.MeinModulName', { name: 'Shopware.apps.MeinModulName', extend: 'Enlight.app.SubApplication', loadPath: '{url controller="MeinModulName" action=load}', bulkLoad: true, controllers: ['Main'], views: [], stores: [], models: [], launch: function () { var me = this, mainController = me.getController('Main'); return mainController.mainWindow; } }); // {/block} main.js // {namespace name="backend/mein\_modul\_name/controller"} // {block name="backend/mein\_modul\_name/controller/main"} Ext.define('Shopware.apps.MeinModulName.controller.Main', { extend: 'Ext.app.Controller', mainWindow: null, init: function () { var me = this; me.mainWindow = me.subApplication.getView('Main').create().show(); me.callParent(arguments); } }); // {/block} Als Error Meldung bekomme ich: TypeError: cls is null cls.prototype.subApp = this;

Hi, ändere mal das // {namespace name="backend/mein\_modul\_name/view/main"} // {block name="backend/mein\_modul\_name/application"} in // {namespace name="backend/MeinModulName/"} // {block name="backend/MeinModulName/application"} kannst du mal deinen Bootstrap.php Code zeigen? Grüße Basti

Hy, mit dem namespace hats leider garnicht funktioniert. Ich habe mir nun die Infos aus posting.php?mode=reply&f=103&t=28656 gezogen und die app.js und die Ordner und js Dateien darunter kopiert. Damit bekomme ich schon mal das gewünschte Grid so hin, wie ich mir das vorgestellt habe. Jetzt muss ich nur noch raus finden, wie das ganze tickt und wie ich meine eigene Tabelle einbinden kann. Leider bekomme ich nun auch eine Fehlermeldung : Ups! Ein Fehler ist aufgetreten! Die nachfolgenden Hinweise sollten Ihnen weiterhelfen. Action "Backend\_MeinModulName\_listAction" not found failure in Enlight/Controller/Action.php on line 389 Stack trace: #0 Enlight/Controller/Action.php(159): Enlight\_Controller\_Action-\>\_\_call('listAction', Array) #1 Enlight/Controller/Action.php(159): Shopware\_Proxies\_ShopwareControllersBackendMeinModulNameProxy-\>listAction() #2 Enlight/Controller/Dispatcher/Default.php(528): Enlight\_Controller\_Action-\>dispatch('listAction') #3 Enlight/Controller/Front.php(228): Enlight\_Controller\_Dispatcher\_Default-\>dispatch(Object(Enlight\_Controller\_Request\_RequestHttp), Object(Enlight\_Controller\_Response\_ResponseHttp)) #4 Shopware/Kernel.php(145): Enlight\_Controller\_Front-\>dispatch() #5 vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpCache/HttpCache.php(471): Shopware\Kernel-\>handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #6 Shopware/Components/HttpCache/AppCache.php(256): Symfony\Component\HttpKernel\HttpCache\HttpCache-\>forward(Object(Symfony\Component\HttpFoundation\Request), true, NULL) #7 vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpCache/HttpCache.php(242): Shopware\Components\HttpCache\AppCache-\>forward(Object(Symfony\Component\HttpFoundation\Request), true) #8 Shopware/Components/HttpCache/AppCache.php(102): Symfony\Component\HttpKernel\HttpCache\HttpCache-\>pass(Object(Symfony\Component\HttpFoundation\Request), true) #9 shopware.php(109): Shopware\Components\HttpCache\AppCache-\>handle(Object(Symfony\Component\HttpFoundation\Request)) #10 {main} In den JS Dateien finde ich allerdings nichts dazu… Muss also etwas sein, das Shopware generiert. Kann es sein, das dies was mit dem \Doctrine\ORM\Tools\SchemaTool Zutun hat? Beste Grüße

Für mich sieht der Fehler aus als würde er versuchen eine Conttoller - Action aufzurufen diese gibt es aber nicht in deinem Controller? Um dein Grid mit deinen Daten zu befüllen brauchst du einen Store und ein Model in Extjs. Das Model repräsentiert deine Daten die du anzeigen willst. Model-Doku Store-Doku Du musst dann nur ein json String aus dem PHP an Extjs zurück geben nachdem aufruf deine Action. Grid-Doku Grüße Basti

Hy, danke für den Hinweis. Also bis jetzt sehe ich in dem Beispiel und meinem Modul nur den Unterschied mit dem ORM. Ich habe mir das mal versucht nach zubauen, mit meiner Datenbank. Aber bekomme dann immer eine Fehlermeldung beim Installieren des Moduls. Plugin-Manager Plugin MeinModulName konnte nicht erfolgreich installiert werden. Class 'Shopware/CustomModels/MeinModulName/MeinModulName' does not exist Das ganze ist eingebunden mit : protected function updateSchema() { //Backend Schema einfügen/Updaten $this-\>registerCustomModels(); $em = $this-\>Application()-\>Models(); $tool = new \Doctrine\ORM\Tools\SchemaTool($em); $classes = array( $em-\>getClassMetadata('Shopware/CustomModels/MeinModulName/MeinModulName') ); try { $tool-\>dropSchema($classes); } catch (Exception $e) { //ignore } $tool-\>createSchema($classes); } Das ganze ist in der install() eingebunden. In der /Model/MeinModulName/MeinModulName/MeinModulName.php habe ich dann stehen: [code]<?php namespace Shopware\CustomModels\MeinModulName;

use Shopware\Components\Model\ModelEntity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
*

  • @ORM\Entity

  • @ORM\Table(name=„lighthouse_MeinModulName“)
    /
    class MeinModulName extends ModelEntity
    {
    /
    *

    • @var integer $id
    • @ORM\Column(name=„id“ type=„integer“ nullable=false)
    • @ORM\Id
    • @ORM\GeneratedValue(strategy=„IDENTITY“)
      */
      private $id;

    /**

    • @var string $ordernumber
    • @ORM\Column(type=„text“ unique=true)
      */
      private $ordernumber;

    /**

    • @var string $MeinModulName_name
    • @ORM\Column(type=„text“, nullable=false)
      */
      private MeinModulName_name;

    /**

    • @var string $MeinModulName_articles
    • @ORM\Column(type=„text“, nullable=false)
      */
      private MeinModulName_articles;

    /**

    • @var string $price
    • @ORM\Column(type=„double“, nullable=false)
      */
      private $price = 0;

    /**

    • @var integer $discount
    • @ORM\Column(type=„integer“, nullable=false)
      */
      private $discount = 0;

    /**

    • @return int
      */
      public function getId()
      {
      return $this->id; } /** * @param int $ordernumber */ public function setOrdernumber($ordernumber) { $this->ordernumber = $ordernumber; } /** * @return int */ public function getOrdernumber() { return $this->ordernumber; } /** * @param string $MeinModulName_name */ public function setMeinModulName_name($MeinModulName_name) { $this->MeinModulName_name = $MeinModulName_name; } /** * @return \MeinModulName_name */ public function getMeinModulName_name() { return $this->MeinModulName_name; } /** * @param string $MeinModulName_articles */ public function setMeinModulName_articles($MeinModulName_articles) { $this->MeinModulName_articles = $MeinModulName_articles; } /** * @return \MeinModulName_articles */ public function getMeinModulName_articles() { return $this->MeinModulName_articles; } /** * @param double $price */ public function setPrice($price) { $this->price = $price; } /** * @return double */ public function getPrice() { return $this->price; } /** * @return integer discount */ public function getDiscount() { return $this->discount; } /** * @param intger $discount */ public function setDiscount($discount) { $this->discount = $discount; } } [/code] Tabelle hat auf id ein primary mit auto_inc sowie ein unique auf ordernumber .

Hy, ich habs nun soweit hin bekommen. Ich bekomme die Einträge aus der Datenbank dargestellt und kann diese auch editieren, löschen, einfügen etc. Jetzt habe ich noch zwei Sachen. Beim Preisfeld ist es mir nicht möglich Nachkommastellen in die Datenbank zu bringen. Wenn ich diese Eintrage, z.b. “11,99” speichert er 1199. Punkt kann nicht nicht eingeben, nur wenn ich es per copy&paste einfüge. Allerdings bekomme ich dann trotzdem 1199 als Wert in der Datenbank. Zudem ist es mir nicht möglich die Spaltennamen zu ändern. Wenn ich dies tue, bleiben die Zeilen entsprechend leer. (Er findet diese dann nicht in der Datenbank) Zudem lassen sich die Fenster Titel nicht bestimmen. Obwohl ich diese in den JS Dateien geändert habe.

Push. Vielleicht einer von Shopware eine Ahnung, woran das liegt?

Hi, sorry das ich mich länger nicht gemeldet habe. Um die Gridspaltenname zu ändern muss du in der View wo du das grid erstellst für jede Spalte die Property „header“ setzen … bsp.: header: ‚Mein Spaltenname‘, … Über die Property bestimmst du den Namen der Spalte. Was genau wird gesendet wenn du auf Speichern klickst? Hat dein Preisfeld in deinem .js - Model evtl. den falschen Typ hinterlegt sieht so aus als wäre das Feld vom Typ „int“. Grüße Basti

Hallo, danke für die Antwort. ich habe die Felder mit header erweitert. Allerdings ohne Erfolg. Das Feld für den Preis habe ich nun von float auf string geändert, damit ich dort überhaupt mal eine Zahl mit Komma einfügen kann. Im PHP Teil, mache ich dann aus dem String ein Float. Dann klappt es. Problem wird wohl später sein, das jemand hier mal Buchstaben eingibt. Der fängt das zwar artig ab und mach eine 0 davon. Aber schön ist was anderes. aus der model/product.js Ext.define('Shopware.apps.PraemienNachArtikelnummern.model.Product', { extend: 'Shopware.data.Model', configure: function() { return { controller: 'PraemienNachArtikelnummern', detail: 'Shopware.apps.PraemienNachArtikelnummern.view.detail.Product' }; }, fields: [{ name : 'id', type: 'int', useNull: true }, { name : 'ordernumber', type: 'string', header: 'Artikelnummer' }, { name : 'premium\_name', type: 'string', header: 'Alternativer Artikelname'}, { name : 'premium\_articles', type: 'string', header: 'Nötige Artikel' }, { name : 'price', type: 'string', scale: 2, header: 'Sonderpreis' }, { name : 'discount', type: 'int', header : '% Rabatt' }] }); Beste Grüße

Hi, habe aktuell ein ähnliches Problem in Sw5. Meine Bootstrap.php enthält neben den anderen Bereichen // ...... /\*\* \* Install \*/ public function install() { $this-\>subscribeEvent('Enlight\_Controller\_Dispatcher\_ControllerPath\_Backend\_MeinPlugin', 'onGetUiControllerPath'); $this-\>\_createMenuItem(); // ...... } /\*\* \* Controller \*/ public function onGetUiControllerPath(Enlight\_Event\_EventArgs $args) { $this-\>Application()-\>Template()-\>addTemplateDir($this-\>Path() . 'Views/'); $this-\>registerCustomModels(); return dirname(\_\_FILE\_\_) . '/Controllers/Backend/MeinPlugin.php'; } Mein /MeinPlugin/Controllers/Backend/MeinController.php hat folgenden Teil als Inhalt und ist eine Erweiterung zu Shopware_Controllers_Backend_ExtJs: // ...... /\*\* \* init \*/ public function init() { $this-\>View()-\>addTemplateDir(dirname( dirname(\_\_FILE\_\_) ) . '/Views/'); parent::init(); } /\*\* \* Index action \*/ public function indexAction() { $this-\>View()-\>loadTemplate('backend/mein\_plugin/app.js'); } // ...... Die ExtJs app.js besteht aus folgendem Inhalt: //{namespace name="backend/MeinPlugin"} //{block name="backend/MeinPlugin/application"} Ext.define('Shopware.apps.MeinPlugin', { name: 'Shopware.apps.MeinPlugin', extend: 'Enlight.app.SubApplication', bulkLoad: true, loadPath: '{url action=load}', controllers: ['Main'], models: ['Main'], views: ['main.Window'], stores: ['Detail'], launch: function () { var me = this, mainController = me.getController('Main'); return mainController.mainWindow; } }); //{/block} Die ExtJs - Controller Datei main.js besteht aus: // {namespace name="backend/MeinPlugin/"} // {block name="backend/MeinPlugin/controller/main"} Ext.define( 'Shopware.apps.MeinPlugin.controller.Main', { extend: 'Ext.app.Controller', mainWindow: null, init: function () { var me = this; me.mainWindow = me.subApplication.getView('Main').create().show(); me.callParent(arguments); } }); //{/block} Rufe ich über das Menü “Einstellungen” den Menüpunkt “Mein Plugin” auf, erhalte ich ein Fehlerfenster mit HTTP-Statuscode 503. Ergänzend zu meinem Plugin, möchte ich in dem sich öffnenden Fenster einen Infotext ausgeben und ein Form einbinden, welcher es ermöglicht, eine Datei hochzuladen und zwar dahin, wo ich es quasi festlege. Hat mir jemand Hilfe oder Tipp zu diesem Thema?

Hi, dann erstellst du in deinem Fenster eine Form-Komponente mit einem Upload - Field. Danach musst du noch die Daten die dir Extjs sendet verarbeiten und die Datei dahin schreiben wo du es haben willst. Extjs Upload-Form Grüße Basti

Hi kurzi, vielen Dank für die Info. Im Grunde bin ich bislang dem Beitrag programmierung-f103/backend-modul-schreiben-t28656.html?hilit=url:%20model= gefolgt. Lediglich die url für den submit passt nicht. Darüber hinaus möchte ich gerne den Controller erreichen und nicht eine zusätzliche Datei erstellen. Ist das möglich? Wenn ja, wie ist die url (z.B. {url model=„xy“ …}) zu definieren, dass der Controller erreicht wird mti der entsprechenden Methode? VG sailas

Hi, um auf deinen Shopware-Backend Controller zuzugreifen, gibst du entweder folgendes an: url: '{url action=deineMethodeInDeinemControllerOhneActionAmEnde}' deine Methode in deinen Controller sollte wie folgt heisen: public function deineMethodeInDeinemControllerOhneActionAmEndeAction(){} oder du rufst das ganze wie folgt auf: url: 'NameDeinesControllers/deineMethodeInDeinemControllerOhneActionAmEnde' Methode im Controller bleibt gleich. Bsp.: Ajax-Request Ext.Ajax.request({ method: 'POST', url: 'NameDeinesControllers/deineMethodeInDeinemControllerOhneActionAmEnde', success: function () {}, failure: function () {} }); Bsp.: Data-Store ... proxy: { type: 'ajax', api: { read: '{url action=deineMethodeInDeinemControllerOhneActionAmEnde}' } } ... Grüße Basti