Skip to content

[Question/help] Abstract class / MappedSuperClass #1984

@markusgillmeister

Description

@markusgillmeister

Hi,

this is primarily more a question than an issue:

I'm preparing to migrate a legacy api implementation to API Platform. I was happy to see
that symfony serializer supports now (in 4.1) abstract classes (https://symfony.com/blog/new-in-symfony-4-1-serialize-and-deserialize-from-abstract-classes) which seem to solve my problem.

So I set up a project with symfony 4.1(beta2/3) and api platform but I was not successful.

Let me explain the "model": In my project I have items (called ci) which can be from a different type (called product) with different attributes, which are stored in separate tables (not an EAV model, but similar).

Database layout looks like this

ci
-----
id         PK, int
product_id FK, int   --> ci_product
....


ci_product
-------
id   PK, int  
name string   (e.g. "Client", "Server"...)
....

product_client
--------------
id     PK, int
ci_id  FK, int       --> ci
attributeA string
attributeB ip
...

product_server
--------------
id     PK, int
ci_id  FK, int     --> ci
attributeC string
attributeD int
....

The goal is that API platform can return attributes (store in tables like product_client, product_server depending on product_id of ci) of a ci (and do insert/update operations).

I tried around with abstract class ("AbstractProduct") , DiscriminatorMap and MappedSuperClass but I didn't get it working.

Perhaps someone can give me a hint what I'm doing wrong or how should I implement this.

Here is one of my attempts which results in

...
"hydra:title":` "An error occurred",
"hydra:description": "Could not resolve type of column \"id\" of class \"App\\Entity\\AbstractProduct\"",
...

Ci.php

...
/**
 * Ci
 *
 * @ORM\Table(name="ci")
 * @ORM\Entity()
 * @ApiResource(
 *     attributes={
 *          "normalization_context"={"groups"={"read"}, "enable_max_depth"=true}
 *      },
 * )
 */
class Ci
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="bigint", nullable=false, options={"default"="ci_id_seq"})
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName="ci_id_seq", allocationSize=1, initialValue=1)
     * @Groups({"read"})
     */
    private $id = 'ci_id_seq';

    /**
     * @var \AbstractProduct
     * @Groups({"read"})
     * @ORM\OneToOne(targetEntity="AbstractProduct",inversedBy="ci")
     *
     */
    public $attributes;
  ...
}

AbstractProduct.php

...
/**
 *
 * @DiscriminatorMap(typeProperty="product", mapping={
 *    "Server"="App\Entity\ProductServer",
 *    "Client"="App\Entity\ProductClient"
 * })
 * @ORM\MappedSuperclass()
 */
abstract class AbstractProduct
{
    /**
     * @var int
     * @Groups({"read"})
     */
    public $id;
}
...

ProductClient.php

...
/**
 * ProductClient
 *
 * @ORM\Table(name="product_client", indexes={@ORM\Index(name="ixfk_product_client_ci", columns={"ci_id"})})
 * @ORM\Entity
 * @ApiResource()
 */
class ProductClient extends AbstractProduct
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="bigint", nullable=false, options={"default"="product_client_id_seq"})
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName="product_client_id_seq", allocationSize=1, initialValue=1)
     * @Groups({"read"})
     */
    public $id = 'product_client_id_seq';

    public function getId() :?int
    {
        return $this->id;
    }

  ....
}
...

Does anyone have a hint what's wrong?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions