Icevarta
Icevarta

Reputation: 190

Custom entity and extended entity one to one association

I am writing a shopware 6 plugin that adds a custom entity and associate it via a one to one association with an existing entity.

This are the important parts of my custom entity:

class OAuthUserDefinition extends EntityDefinition
{
  [...]
  protected function defineFields(): FieldCollection {
    return new FieldCollection([
       (new IdField('id', 'id'))->addFlags(new Required(), new PrimaryKey()),
       (new FkField('customer_id', 'customerId', CustomerDefinition::class)),
       new OneToOneAssociationField('customer', 'customer_id', 'id', CustomerDefinition::class)
     ]);
   }
}

And i extended the customer entity like this:

class CustomerExtension extends EntityExtension{
  public function extendFields(FieldCollection $collection): void {
    $collection->add(
      (new OneToOneAssociationField(
        'oAuthUser',
        'id',
        'customer_id',
        OAuthUserDefinition::class
       ))
     );
  }
  
  public function getDefinitionClass(): string
  {
     return CustomerDefinition::class;
  }
}

This is my migration:

    public function update(Connection $connection): void
    {
        $connection->executeUpdate('
            CREATE TABLE IF NOT EXISTS `nt_oauth_user` (
              `id` BINARY(16) NOT NULL,
              `customer_id` BINARY(16) NULL,
              `oauth_user_id` VARCHAR(36) NOT NULL,
              `created_at` DATETIME(3) NOT NULL,
              `updated_at` DATETIME(3) NULL,
              PRIMARY KEY (`id`),
              CONSTRAINT `fk.oauth_user.customer_id` FOREIGN KEY (`customer_id`)
                REFERENCES `customer` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
        ');
    }

And my service.xml

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>

        <service id="Nt\OAuthClient\Core\System\OAuthUser\OAuthUserDefinition">
            <tag name="shopware.entity.definition" entity="nt_oauth_user" />
        </service>


        <service id="Nt\OAuthClient\Core\Checkout\Customer\CustomerExtension">
            <tag name="shopware.entity.extension"/>
        </service>

    </services>
</container>

Now with this code shopware breaks totally and i get an HTTP-error 503 on most of the Endpoints. I think it runs into a recursion because if i set the OneToOneAssociationField autoload property to false in the customer extension the 503 error vanishes. But the store-api/v1/account/customer gives me a

"status": "500",
"title": "Internal Server Error",
"detail": "Argument 1 passed to Shopware\\Core\\System\\SalesChannel\\Api\\StructEncoder::encode() must be an instance of Shopware\\Core\\Framework\\Struct\\Struct, null given, called in /app/vendor/shopware/platform/src/Core/System/SalesChannel/Api/StructEncoder.php on line 214",

because customer->extensions->oAuthUser is null.

If i swap it, set OneToOneAssociationField autoload on the extension back to true and to false in my custom entity everything seems to work but that is not very practical.

The recursion part of it seems like an error in shopware to me or do i have an error on my side? Do i need to supply a custom struct somehow?

Upvotes: 3

Views: 2547

Answers (2)

Daniel Ifrim
Daniel Ifrim

Reputation: 287

I had the same issue. Added an extension on product entity. In my custom definition class (e.g. OAuthUserDefinition) I've set autoloading to false. And I left autoloading to true in extension class (e.g. CustomerExtension).

No more infinite loop. I guess the 2 classes were trying to load each other but the instances of the classes were other always. Would not know exactly. I saw in shopware code that there are a few examples using OneToOneAssociationField. This is why I'm not autoloading in both objects. To this point I do not know if this infinite loop is a bug or miss use of code features.

I still got errors in admin on edit product page. The only way that worked was to fill my table with NULL/empty values for all products. Also having in migration script something like:

$this->updateInheritance($connection, 'product', 'myLoremIpsum');

will create a column myLoremIpsum in product table. I had to put the value from field id from table product. I saw what value to put by installing this example: https://github.com/shopware/swag-docs-bundle-example

https://docs.shopware.com/en/shopware-platform-dev-en/how-to/indepth-guide-bundle/introduction?category=shopware-platform-dev-en/how-to/indepth-guide-bundle

Would be nice to have official documentation and an example with OneToOneAssociationField.

Upvotes: 2

Skoenig
Skoenig

Reputation: 462

Did you define a getDefinitionClass-Function in your CustomerExtension-Class?

public function getDefinitionClass(): string
{
    return CustomerDefinition::class;
}

Could your also please share your Database-Migration?

Upvotes: 0

Related Questions