Shopware 5.3 Plugin 101 | Model erstellen

Wir haben uns in den vorherigen Beiträgen mit verschiedenen Punkten der Pluginentwicklung beschäftigt (Events, Controller etc.) – nun kommen wir zu einem Interessanten Punkt für’s entwickeln – Models.

Model Basics

Grundstruktur

Ich gehe hier davon aus, dass Ihr bereits ein Plugin mit der üblichen Struktur habt (Base File, services.xml etc.) Wir gehen also in cd custom/plugins/MiHoMeinPlugin  und legen uns dort zuerst den Order Models an.

mkdir Models

dort erstellen wir uns das/die jeweilige/n Model/s. Ich möchte zum Beispiel ein Model namens Bug anlegen.

touch Bug.php

Wie auch bei Subscribern und Controllern geben wir zuerst unseren Namespace an:

<?php

namespace MiHoMeinPlugin\Models;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Shopware\Components\Model\ModelEntity;

Wir nutzen hier ORM-Annotationen von Doctrine und erstellen und Klasse

/**
 * @ORM\Entity
 * @ORM\Table(name='miho_bugs')
 */
class Bug extends ModelEntity{

}

Datenfelder

Danach legen wir unsere Datenfelder an – hier im Beispiel werde ich nur 4 Felder anlegen: id, short_description, description,created

/**
	 * @ORM\Id
	 * @ORM\Column(type="integer")
	 * @ORM\GeneratedValue(strategy="IDENTITY")
	 */
	private $id;

	/**
	 * @ORM\Column(name="short_description", type="string", nullable=false)
	 */
	private $short_desciption;

	/**
	 * @ORM\Column(name="description", type="text", nullable=false)
	 */
	private $description;

	/**
	 * @ORM\Column(name="created", type="datetime", nullable=false)
	 */
	private $created;

Außerdem referenzieren wir noch den Kunden

/**
	 * @ORM\ManyToOne(targetEntity="\Shopware\Models\Customer\Customer")
	 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
	 */
	protected $customer;

Mit ManyToOne bestimmen wir das viele Bugs auf einen Kunden referenziert werden, aber jeder Bug nur einen Kunden hat („ManyToOne – Many instances of the current Entity refer to One instance of the refered Entity.“ – Quelle)

Mit der JoinColumn bestimmen wir in name wie die Spalte in unserer späteren Table heißen wird (user_id) und auf welche Sie in der Customer Table referenziert (id).

Nun müssen wir noch unseren Konstruktor sowie Getter und Setter definieren.

Konstruktor

public function __construct()
    {
        $this->time = new \DateTime();
    }

Getter und Setter

Jetzt müssen wir die Getter und Setter definieren, das kann je nach Größe der Table aufwendig sein – falls Ihr Phpstorm nutzt empfehle ich auch die  Code -> Generate Funktion

Phpstorm Code generate Setter and getter

Das ganze generiert uns folgenden Code (in unserem Fall auch den Setter für ID, den möchten wir aber nicht haben, das soll unsere Datenbank für uns machen, sobald wir eine Entity anlegen (löscht diesen dann einfach raus, oder wählt bei id nur den Getter im Phpstorm Dropdown)

 

	/**
	 * @return mixed
	 */
	public function getId() {
		return $this->id;
	}

	/**
	 * @return mixed
	 */
	public function getShortDesciption() {
		return $this->short_desciption;
	}

	/**
	 * @param mixed $short_desciption
	 */
	public function setShortDesciption( $short_desciption ) {
		$this->short_desciption = $short_desciption;
	}

	/**
	 * @return mixed
	 */
	public function getDescription() {
		return $this->description;
	}

	/**
	 * @param mixed $description
	 */
	public function setDescription( $description ) {
		$this->description = $description;
	}

	/**
	 * @return mixed
	 */
	public function getCreated() {
		return $this->created;
	}

	/**
	 * @param mixed $created
	 */
	public function setCreated( $created ) {
		$this->created = $created;
	}

	/**
	 * @return mixed
	 */
	public function getCustomer() {
		return $this->customer;
	}

	/**
	 * @param mixed $customer
	 */
	public function setCustomer( $customer ) {
		$this->customer = $customer;
	}

Datenbanktabelle erzeugen

Nun legen wir uns eine Datenbanktabelle an, richtig? Das ist gar nicht notwendig, dank Doctrine. Wir nutzen dafür das ORM Tool SchemaTool – mit dem können ganz einfach beim installieren und deinstallieren Tables angelegt und auch wieder gelöscht werden. So ersparen wir uns die müßige Arbeit des anlegens/löschens und verhindern Daten Missstände.

Dazu fügen wir unserer Basis Klasse die eigenen  und referenzierten Models und weitere Abhängigkeiten hinzu:

use Doctrine\ORM\Tools\SchemaTool;
use MiHoMeinPlugin\Models\Bug;
use Shopware\Components\Model\ModelManager;
use Shopware\Components\Plugin\Context\InstallContext;
use Shopware\Components\Plugin\Context\UninstallContext;
use Shopware\Models\Customer\Customer;

Wir nutzen dann zwei Methoden die in jedem Plugin genutzt werden können: install und uninstall

class MiHoMeinPlugin extends Plugin
{

public function install(InstallContext $context)
	{
		$this->updateSchema();
		$this->createDemo();
	}

	public function uninstall(UninstallContext $context)
	{
		/** @var ModelManager $entityManager */
		$entityManager = $this->container->get('models');

		$tool = new SchemaTool($entityManager);

		$classMetaData = [
			$entityManager->getClassMetadata(Bug::class)
		];

		$tool->dropSchema($classMetaData);
	}

}

In install() rufen wir zwei private Methoden auf, welche ich gleich noch vorstelle. Ihr müsst hier eigentlich nur die verschiedenen Klassen in der uninstall() Methode eintragen und zwar im $classMetaData Array:

$entityManager->getClassMetadata(Bug::class)

Das SchemaTool zieht sich wie oben schon beschrieben alle nötigen Daten direkt aus dem jeweiligen Model. Unsere beiden privaten Methoden könnten wie folgt aussehen:

private function updateSchema()
	{
		/** @var ModelManager $entityManager */
		$entityManager = $this->container->get('models');

		$tool = new SchemaTool($entityManager);

		$classMetaData = [
			$entityManager->getClassMetadata(Bug::class)
		];

		$tool->createSchema($classMetaData);
	}

	private function createDemo()
	{
		/** @var ModelManager $entityManager */
		$entityManager = $this->container->get('models');

		$customer = $entityManager->getRepository(Customer::class)->find(1);

		$bug = new Bug();
		$bug->setDescription('Das ist ein Testbug');
		$bug->setShortDesciption('Bugtitel');
		$bug->setUrl('www.test.de');
		$bug->setCustomer($customer);
                $bug->setCreated(date('y-m-d H:i:s'));


		$entityManager->persist($bug);
		$entityManager->flush($bug);
	}

updateSchema() hier erstellt hier das Datenbankschema bzw. die Datenbanktabelle (createSchema()) – in createDemo() legen wir einfach einen ersten Eintrag an. Dazu holen wir uns wieder über den entityManager unsere Models erstellen mit new Bug() eine neue Entity und finden einen User mit der id = 1 (müsst Ihr eventuell anpassen).

Installieren

Jetzt können wir unser Plugin testweise mal installieren. Ich bekam am Anfang direkt einen Error

Error
[Syntax Error] Expected PlainValue, got ''' at position 31 in class MiHoMeinPlugin\Models\Bug.

Ich hatte in den Doctrine Annotationen aus versehen ein ‚ statt “ gesetzt. Die Zeile Code hat leider nicht gestimmt, es war Zeile 15, daher hat es 5 Minuten gedauert… ärgerlich, aber eventuell hilft es nochmal jemanden 😉

weiter im Text – nach der Installation sollte eine Tabelle in eurer Datenbank erstellt worden sein.

 

 

Deinstallieren

In manchen Fällen möchte man die Daten in der gerade angelegten Tabelle selbst nach der Deinstallation behalten, das erreichen wir mit der Abfrage über keepUserData().

public function uninstall(UninstallContext $context)
{
   ...

   if ($context->keepUserData()) {
      return;
   }

   $tool->dropSchema($classMetaData);

}

 

5 Antworten auf „Shopware 5.3 Plugin 101 | Model erstellen“

  1. Hallo,

    ich habe das Listing Plugin durch das Model erweitert.
    Allerdings lässt sich das Plugin nicht mehr installieren,
    wenn ich die Install Prozeduren in die ListingErweiterung.php einfüge.
    class GwenListingErweiterung extends Plugin {
    public function install( InstallContext $context ) {
    ….
    }
    usw.

  2. Ich habe jetzt den gleichen Error
    Error
    [Syntax Error] Expected PlainValue, got “‘ at position 31 in class GwenListingExtension\Models\Bug.

    Finde aber keinen Anhaltspunkt wo die Annotation falsch sein soll.

  3. Warum sich mein Plugin vorher nicht installieren ließ, liegt daran, dass du vergessen hast, für die Url eine Spalte im Model anzulegen.
    Und wenn die Spalten nullable false haben sollen, muss schließlich auch etwas reingeschrieben werden, was bei getCreated() im setter auch nicht geschieht, wenn man nullable nicht auf true setzt.

    Also, die function createDemo() um

    $date = date(‚y-m-d H:i:s‘);
    $bug->setCreated($date);

    und im Entity Model um

    /**
    * @ORM\Column(name=“url“, type=“text“, nullable=true)
    */
    private $url;

    public function getUrl() {
    return $this->url;
    }

    public function setUrl( $url ) {
    $this->url = $url;
    }

    erweitern. Dann funktioniert das auch.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert