Extend shopware database, creating relations

Hi there, I’m trying to implement a plugin to add sales representative data to my shop and associate this data to users. On this context (users and sales representative) I have: sales_rep - Sales representative table sales_rep_user - Relation between User and Sales Representative 1st For the swg_sales_rep and swg_sales_rep_user relation (OneToMany) I could create that without problems SwgSalesRepresentative.php ... \*\* \* @ORM\Entity \* @ORM\Table(name="swg\_sales\_rep") \*/ class SwgSalesRepresentative extends ModelEntity { ... /\*\* \* INVERSE SIDE \* \* @var \Doctrine\Common\Collections\ArrayCollection \* \* @ORM\OneToMany( \* targetEntity="Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentative", \* mappedBy="salesRepresentative", \* orphanRemoval=true \* ) \*/ protected $salesRepresentativeUsers; ... SwgSalesRepresentativeUsers.php /\*\* \* @ORM\Entity \* @ORM\Table(name="swg\_sales\_rep\_users") \*/ class SwgSalesRepresentativeUsers extends ModelEntity { ... /\*\* \* \* @ORM\ManyToOne(targetEntity="Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentative") \* @ORM\JoinColumn(name="sales\_rep\_id", referencedColumnName="id") \*/ protected $salesRepresentative; /\*\* \* @return mixed \*/ public function getSalesRepresentative() { return $this-\>salesRepresentative; } /\*\* \* @param $salesRepresentative \* @return ModelEntity \*/ public function setSalesRepresentative($salesRepresentative) { return $this-\>setManyToOne( $salesRepresentative, '\Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentative', 'salesRepresentativeUsers' ); } And after install I get my tables with foreign key ok. For the relation between swg_sales_rep_user and s_user (OneToOne) I have problems. My first idea was extend the User model and add the additional logic I need. But this implies to overwrite my users table, take the risk to lose data. I would like to create only the relation with my swg_sales_rep_users table. What I did was create a SwgUser model that extends User model, like SwgSalesRepresentativeUsers.php /\*\* \* @ORM\Entity \* @ORM\Table(name="swg\_sales\_rep\_users") \*/ class SwgSalesRepresentativeUsers extends ModelEntity { ... /\*\* \* @var \Shopware\CustomModels\SwagUserSalesRepresentative\SwgUser $user \* \* @ORM\OneToOne(targetEntity="Shopware\CustomModels\SwagUserSalesRepresentative\SwgUser", inversedBy="salesRepresentative") \* @ORM\JoinColumn(name="user\_id", referencedColumnName="id") \*/ protected $user; /\*\* \* @return mixed \*/ public function getUser() { return $this-\>user; } /\*\* \* @param $user \* @return ModelEntity \*/ public function setUser($user) { return $this-\>setOneToOne( $user, '\Shopware\CustomModels\SwagUserSalesRepresentative\SwgUser', 'user', 'salesRepresentative' ); } ... SwgUser.php /\*\* \* @ORM\Entity \* @ORM\Table(name="s\_user") \*/ class SwgUser extends User { /\*\* \* \* @ORM\OneToOne(targetEntity="Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentativeUsers", mappedBy="user") \*/ protected $salesRepresentative; ... And Bootstrap install/uninstall looks like /\*\* \* Install method \* \* @return bool \*/ public function install() { $this-\>updateSchema(); return true; } /\*\* \* Uninstall method \* \* @return bool \*/ public function uninstall() { $this-\>registerCustomModels(); $em = $this-\>Application()-\>Models(); $tool = new \Doctrine\ORM\Tools\SchemaTool($em); $classes = array( $em-\>getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentative'), $em-\>getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgUser'), $em-\>getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentativeUsers') ); $tool-\>dropSchema($classes); return true; } /\*\* \* Creates the database scheme from existing doctrine models. \* \* Will remove the table first, so handle with care. \*/ protected function updateSchema() { $this-\>registerCustomModels(); $em = $this-\>Application()-\>Models(); $tool = new \Doctrine\ORM\Tools\SchemaTool($em); $classes = array( $em-\>getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentative'), $em-\>getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgUser'), $em-\>getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentativeUsers') ); try { $tool-\>dropSchema($classes); } catch (Exception $e) { //ignore } $tool-\>createSchema($classes); } I tried to use the unidirectional http://doctrine-orm.readthedocs.org/pro … irectional and it creates the field but not the relation with s_user table (Foreign key). So question is, how can I create relations with core tables on shopware without have to recreate (drop/create) the core tables? Is it possible to alter tables programmatically? what is the best approach for these needs. Do you have an example that demonstrate this? Thanks for helping.

Hi,

this is a limitation we have - you cannot do it, without potentially loosing forward compatiblity or compatibility with other plugins doing the same. 

We have similar situations in our own plugins: E.g. here:

/**
 * @ORM\OneToOne(targetEntity="Shopware\Models\Article\Article")
 * @ORM\JoinColumn(name="article_id", referencedColumnName="id")
 */
private $article;

As you see, the plugin model has a notion of the article model - but not vice versa. This is not ideal, because from having the article model you cannot directly resolve the plugin’s relation. Usually, you can work around it, however, using doctrine repositories with methods for your use case. I’m not too happy about it - but from my experience, it does not really stop you from doing things - and it saves you from a lot of quirks and complexity that would come with a completly automated data model generation.

Best regards,

Daniel

1 Like