My entities are as follows:
a Portfolio has many Series [OneToMany-ManyToOne]
a Serie has many Assets [OneToMany-ManyToOne]
a Serie can have an Asset (as a thumbnail) [OneToOne]
I also used the cascade={"remove"} property in order to remove the Series and Assets if the corresponding Portfolio has been deleted.
Serie
/**
* Serie
*
* #ORM\Table(name="serie")
* #ORM\HasLifecycleCallbacks
*/
class Serie
{
/**
* #var \Portfolio
*
* #ORM\ManyToOne(targetEntity="Portfolio", inversedBy="series")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="portfolio", referencedColumnName="id")
* })
*/
private $portfolio;
/**
* #var \Image
*
* #ORM\OneToOne(targetEntity="Image")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="preview", referencedColumnName="id", nullable=true, onDelete="SET NULL")
* })
*/
private $preview;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\OneToMany(targetEntity="Asset", mappedBy="serie", cascade={"remove"})
**/
private $assets;
/**
* #ORM\PostRemove
*/
public function removeDirectory(){
rmdir(...);
}
Asset
/**
* #ORM\Table(name="asset")
* #ORM\HasLifecycleCallbacks
*/
class Asset
{
/**
* #var \Serie
*
* #ORM\ManyToOne(targetEntity="Serie", inversedBy="assets")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="serie", referencedColumnName="id")
* })
*/
protected $serie;
/**
* #ORM\PostRemove()
*/
public function removeFile()
{
unlink($this->filename);
}
I put the cascade={"remove"} property in Asset's side of the relationship because the other way around would result in a foreign key constraint error.
The postRemove method in Serie is called but not the one in Asset. Am I doing something wrong, is there a way to fix it?
Related
I am new to both Symfony and API platform and trying to understand how to get all unique brands and product types of my products in a list so that I can use them later to display a list of filters to use in my frontend.
I'm a bit lost as to how to do this. I want to have a custom endpoint products/filters that would return me the list.
I would like to have it in this form:
{
brands: [
"Agilent",
"Comtr"
"Anot
],
types:[
"Accelerometer",
"Sonometer",
"Micro-amplifier"
]
}
Both brand and type are nested properties of my entity Product, they come from my entity ProductModel. I am using Api platform for my api that is why there is a lot of annotations.
class Product
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #Groups({"product_get", "product_list"})
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity=ProductModel::class, cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
* #Groups({"product_get", "product_list"})
*/
private $idProductModel;
/**
* #ORM\Column(type="string", length=50)
* #Groups({"product_get", "product_list"})
* #Assert\NotBlank(message="The field serial number is mandatory.")
*/
private $serialNumber;
/**
* #ORM\Column(type="text", nullable=true)
* #Groups({"product_get"})
*/
private $comment;
/**
* #ORM\Column(type="datetime")
* #Groups({"product_get", "product_list"})
*/
private $createdAt;
/**
* #ORM\Column(type="datetime", nullable=true)
* #Groups({"product_get", "product_list"})
*/
private $updatedAt;
/**
* #ORM\Column(type="datetime", nullable=true)
* #Groups({"product_get"})
*
*/
private $deletedAt;
/**
* #ORM\Column(type="boolean")
* #Groups({"product_get", "product_list"})
* #Assert\NotBlank(message="The field confidential is mandatory.")
*
*/
private $confidential;
/**
* #ORM\ManyToOne(targetEntity=Storage::class, cascade={"persist"})
* #Groups({"product_get", "product_list"})
*/
private $idStorage;
/**
* #ORM\ManyToOne(targetEntity=User::class, cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
* #Groups({"product_get", "product_list"})
*/
private $idUser;
/**
* #ORM\ManyToOne(targetEntity=User::class, cascade={"persist"})
* #Groups({"product_get"})
*/
private $idUserDelete;
/**
* Many products can have many products
* #ORM\ManyToMany(targetEntity=Product::class, mappedBy="myProducts")
*/
private $partOfthisProduct;
/**
* Many products can have many products
* #ORM\ManyToMany(targetEntity=Product::class, inversedBy="partOfthisProduct")
* #JoinTable(name="product_has_product",
* joinColumns={#JoinColumn(name="product_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="related_product_id", referencedColumnName="id")}
* )
* #Groups({"product_get", "product_list"})
*/
private $myProducts;
/**
* #ORM\OneToMany(targetEntity=Sensor::class, mappedBy="product", cascade={"persist"})
* #Groups({"product_get", "product_list"})
* #ApiSubresource()
*/
private $sensors;
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
use App\Repository\ProductModelRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\ManyToMany;
use Symfony\Component\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping\JoinTable;
use Doctrine\ORM\Mapping\JoinColumn;
/**
* #ORM\Entity(repositoryClass=ProductModelRepository::class)
* #ApiResource(
* itemOperations={"get"},
* collectionOperations={"get"},
* normalizationContext={
* "groups"={"read"}}
* )
*/
class ProductModel
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #Groups({"read", "product_get", "product_list"})
*/
private $id;
/**
* #ORM\Column(type="string", length=50)
* #Groups({"read", "product_get", "product_list"})
*/
private $modelName;
/**
* #ORM\ManyToOne(targetEntity=ProductType::class, cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
* #Groups({"read", "product_get", "product_list"})
*/
private $idProductType;
/**
* #ORM\ManyToOne(targetEntity=Unit::class)
*/
private $idInputUnit;
/**
* #ORM\ManyToOne(targetEntity=Unit::class)
*/
private $idOutputUnit;
/**
* #ORM\ManyToOne(targetEntity=Brand::class, cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
* #Groups({"read", "sensor_get", "product_list"})
*/
private $idBrand;
/**
* #ORM\ManyToMany(targetEntity=TestType::class)
* #Groups({"read", "sensor_get", "product_get"})
*/
private $idTestsTypes;
/**
* #ORM\Column(type="integer", nullable=true)
* #Groups({"read", "sensor_get"})
*/
private $periodicity;
/**
* #ORM\Column(type="float", nullable=true)
* #Groups({"read", "sensor_get", "product_get"})
*/
private $nominalSensitivity;
/**
* #ORM\ManyToOne(targetEntity=TestType::class)
* #Groups({"read", "sensor_get", "product_get"})
*/
private $periodicityTest;
/**
* Many ProductModel have Many SensorModel.
* #ManyToMany(targetEntity="SensorModel")
* #JoinTable(name="productModel_sensorModels",
* joinColumns={#JoinColumn(name="Product_model_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="Sensor_Model_id", referencedColumnName="id", unique=true)}
* )
* #Groups({"read", "sensor_get", "product_get"})
*/
private $sensorModels;
What would be the way to do this ? Thank you for your help.
Think the best way to do it is with a custom action that calls a method from the entity's repository.
First you add a custom operation to your #ApiResource definition, in the collectionOperations part in this case.
/**
* #ApiResource(
* itemOperations={"get","put","delete"},
* collectionOperations={
* "get","post",
* "types"={
* "method"="GET",
* "path"="/product_models/brands",
* "controller"=DistinctBrandsAction::class,
* "openapi_context"={
* "parameters"={}
* },
* "read"=false,
* }
* }
* )
* #ORM\Entity(repositoryClass=Repository::class)
*/
Then you add a method to your entity's repository (it would be ProductModelRepository in your case).
This method will query the collection and get the distinct values of the desired column. You'll have to modify this a bit to get the exact output you want (add the product types etc.):
//..blah blah.. use statements etc.
class ProductModelRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Report::class);
}
//this is the method you're adding:
//for symfony 3+ you use groupBy() instead of distinct() to get distinct values for a column
public function getDistinctBrands() {
return $this->createQueryBuilder('r')
->select('r.idBrand')
->groupBy('r.idBrand')
->getQuery()
->getResult();
}
}
Then you need to create a controller for your configured action that calls the method you added to the repository and then outputs it. (This would go in src/Controller/Action/DistinctBrandsAction.php if you're using autowiring)
<?php
namespace App\Controller\Action;
use App\Entity\Report;
use App\Repository\ProductModelRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
/**
* Class DistinctBrandsAction
*/
final class DistinctBrandsAction extends AbstractController
{
/**
* #param ProductModelRepository $productRepository
* #return Array
*/
public function __invoke(ProductModelRepository $productRepository): Array
{
return $productRepository->getDistinctBrands();
}
}
You can use the console to see what your resulting route is. It should be grouped with your ProductModel routes when running php bin/console debug:router
Further reading:
https://api-platform.com/docs/core/pagination/#custom-controller-action
I'm new to Symfony and am having trouble getting my entities set up. I want to be able to access the tag names from my Acasset entity.
Here are the relevant entities:
class Actag
{
/**
* #var string
*
* #ORM\Column(name="tag_name", type="string", length=200, nullable=true)
*/
private $tagName;
/**
* #var integer
*
* #ORM\Column(name="tag_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $tagId;
/**
* Acassettag
*
* #ORM\Table(name="acAssetTag", indexes={#ORM\Index(name="IDX_7C4A2A745DA1941", columns={"asset_id"}), #ORM\Index(name="IDX_7C4A2A74BAD26311", columns={"tag_id"})})
* #ORM\Entity
*/
class Acassettag
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var \AdminBundle\Entity\Acasset
*
* #ORM\ManyToOne(targetEntity="AdminBundle\Entity\Acasset", inversedBy="asset", cascade="PERSIST")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="asset_id", referencedColumnName="asset_id")
* })
*/
private $asset;
/**
* #var \AdminBundle\Entity\Actag
*
* #ORM\ManyToOne(targetEntity="AdminBundle\Entity\Actag")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="tag_id", referencedColumnName="tag_id")
* })
*/
private $tag;
/**
* Acasset
*
* #ORM\Table(name="acAsset", indexes={#ORM\Index(name="IDX_3B81679E68BA92E1", columns={"asset_type"}), #ORM\Index(name="IDX_3B81679E12469DE2", columns={"category_id"})})
* #ORM\Entity(repositoryClass="AdminBundle\Repository\AcAssetRepository")
*/
class Acasset
{
/**
* #var string
*
* #ORM\Column(name="asset_name", type="string", length=100, nullable=false)
*/
private $assetName;
/**
* #var integer
*
* #ORM\Column(name="asset_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $assetId;
/**
* #var \AdminBundle\Entity\Acassettype
*
* #ORM\OneToOne(targetEntity="AdminBundle\Entity\Acassettype", mappedBy="asset", fetch="EAGER", cascade={"persist"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="asset_type_id", referencedColumnName="asset_type_id")
* })
*/
private $assetType;
/**
* #var \AdminBundle\Entity\Actag
*
* #ORM\ManyToOne(targetEntity="AdminBundle\Entity\Actag")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="tag_id", referencedColumnName="tag_id")
* })
*/
private $assetTags;
/**
* Set tag
*
* #param \AdminBundle\Entity\Actag $tag
*
* #return Acassettag
*/
public function setAssetTags(\AdminBundle\Entity\Actag $tag = null)
{
$this->tag = $tag;
return $this;
}
/**
* Get tag
*
* #return \AdminBundle\Entity\Actag
*/
public function getAssetTags()
{
return $this->tag;
}
So in my Acasset entity I have created $assetTags but I am getting an error: Invalid column name 'tag_id'.
But $tag in the Acasettag entity works, which is set up the same way. What am I missing, still struggling a little with this part of Symfony.
I didnt't include all the getters and setters in this post, just the one I created for this.
Why does your Actag-Entity hat also a tagId field? You don't need a defined Id-Column on the Owning-Side. You have to define a OneToMany.
Many Acassettag are owned by one Actag (because of the ManyToOne-Definition in Acassettag
So every Acassettag will need the field actag_id with the Id of the owning Actag which will be autogenerated by your ManyToOne-Definition
When you create a new Acassettag Entity and want to "connect" it with a existing Actag you need Acassettag
public setActag(Actag $actag)
{
$this->tag = $actag;
return $this;
}
I need help for my problem.
When add the relationship ManyToMany to the php script this return when validate the relationship.
This is my scripts:
class Post implements ResourceInterface, TranslatableInterface
{
/**
* #var int
*/
private $id;
/**
* #var bool
*/
private $important;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Tag", inversedBy="posts")
* #ORM\JoinTable(name="posts_tags",
* joinColumns={
* #ORM\JoinColumn(name="post_id", referencedColumnName="id", onDelete="CASCADE")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="tag_id", referencedColumnName="id")
* }
* )
*/
private $tags;
}
And
class Tag implements ResourceInterface, TranslatableInterface
{
use TranslatableTrait {
__construct as private initializeTranslationsCollection;
}
/**
* #var int
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Post",
mappedBy="tags")
*/
private $posts;
}
The error is:
Mapping
[FAIL] The entity-class AppBundle\Entity\Tag mapping is invalid: *
The field AppBundle\Entity\Tag#posts is on the inverse side of a bi-
directional relationship, but the specified mappedBy association on
the target-entity AppBundle\Entity\Post#tags does not contain the
required 'inversedBy="posts"' attribute.
Hello use symfony maker
. /bin/console make:entity Post
For the field name enter 'tags' and for the type enter 'relation' . Then give the related tags entity name. Shoud be Tag. Choose the manytomany relation and enter. Like this you should never have relation issue :-). Even if the entity exist already.
maybe the mapping of the tags attribute in the post entity should be like this:
class Post implements ResourceInterface, TranslatableInterface
{
/**
* #var int
*/
private $id;
/**
* #var bool
*/
private $important;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Tag", inversedBy="posts", cascade={"persist"})
* #ORM\JoinTable(name="posts_tags",
* joinColumns={
* #ORM\JoinColumn(name="post_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="tag_id", referencedColumnName="id")
* }
* )
*/
private $tags;
}
I hope I've helped :)
I've got a problem setting up the Doctrine mapping correctly.
I have a CashRegister Entity which has a bin location and a return bin location. Both locations are from the same Type (BinLocation Entity).
Outgoing from CashRegister, CashRegister->getBinLocations() and CashRegister->getReturnBinLocations() are working fine, but how can I achieve that BinLocation->getCashRegisters() returns all CashRegister Entities that are referenced (binLocation + returnBinLocation)?
/**
* CashRegister
*
* #ORM\Table(name="cash_registers")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class CashRegister
{
...
/**
* #var BinLocation
*
* #ORM\ManyToOne(targetEntity="BinLocation", inversedBy="cashRegisters")
* #ORM\JoinColumn(name="bin_location_id", referencedColumnName="id")
*/
private $binLocation;
/**
* #var BinLocation
*
* #ORM\ManyToOne(targetEntity="BinLocation", inversedBy="cashRegisters")
* #ORM\JoinColumn(name="return_bin_location_id", referencedColumnName="id")
*/
private $returnBinLocation;
/**
* #return BinLocation
*/
public function getBinLocation()
{
return $this->binLocation;
}
/**
* #return BinLocation
*/
public function getReturnBinLocation()
{
return $this->returnBinLocation;
}
...
}
/**
* BinLocation
*
* #ORM\Table(name="bin_locations")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class BinLocation
{
...
/**
* #var CashRegister[]
*
* #ORM\OneToMany(targetEntity="CashRegister", mappedBy="binLocation") <= Here is the problem, in this case mappedBy need to be an array [binLocation, returnBinLocation]
*/
private $cashRegisters;
/**
* #return CashRegister[]
*/
public function getCashRegisters()
{
return $this->cashRegisters;
}
...
}
The simple answer is that you cannot. mappedBy accepts only one argument.
The solution to achieve what you want is however simple. Create a second property in BinLocation called: cashRegisters2 as follows:
/**
* #var CashRegister[]
*
* #ORM\OneToMany(targetEntity="CashRegister", mappedBy="binLocation")
*/
private $cashRegisters;
/**
* #var CashRegister[]
*
* #ORM\OneToMany(targetEntity="CashRegister", mappedBy="binLocation")
*/
private $cashRegisters2;
Then merge the Collections in your getCashRegisters method.
/**
* #return CashRegister[]
*/
public function getCashRegisters()
{
return new ArrayCollection(
array_merge($cashRegisters->toArray(), $cashRegisters2->toArray())
);
}
Also change your CashRegister mappings accordingly:
/**
* #var BinLocation
*
* #ORM\ManyToOne(targetEntity="BinLocation", inversedBy="cashRegisters")
* #ORM\JoinColumn(name="bin_location_id", referencedColumnName="id")
*/
private $binLocation;
/**
* #var BinLocation
*
* #ORM\ManyToOne(targetEntity="BinLocation", inversedBy="cashRegisters2")
* #ORM\JoinColumn(name="return_bin_location_id", referencedColumnName="id")
*/
private $returnBinLocation;
Note: I did not test the code. This example is to server guide only.
Note2: The ArrayCollection merge was inspired from here: https://stackoverflow.com/a/16871539/2853903
I have also searched for solutions and made a patch for Doctrine so you can have custom_attributes linked to a variety of entity types.
Doctrine 2.6: https://github.com/danielbeeke/doctrine2/commit/2d8530176b872cb490c5c88b8c8e17d8d0091388
Doctrine 2.7: https://github.com/danielbeeke/doctrine2/commit/5bde696848ea9fe7035fadc4d46baa4c0d51f3a2
/**
* #Entity
* #Table(name="product")
* #HasLifecycleCallbacks
**/
class Product {
/**
* One Product has Many Attributes.
*
* #OneToMany(
* targetEntity="CustomAttribute",
* mappedBy="EntityId",
* mappedByType={
* "field": "EntityType",
* "value": "product"
* }
* )
*
* #var $CustomAttributes ArrayCollection
*/
protected $CustomAttributes;
}
/**
* #Entity
* #Table(name="custom_attribute")
* #HasLifecycleCallbacks
**/
class CustomAttribute_entity {
/** #Id #Column(type="integer") #GeneratedValue */
protected $Id;
/**
* Many Attributes have One Entity of the EntityType provided.
* #ManyToOne(targetEntity="Product", inversedBy="CustomAttributes")
* #JoinColumn(name="EntityId", referencedColumnName="Id")
*/
protected $EntityId;
/** #Column(type="string") */
protected $EntityType;
/** #Column(type="string") */
protected $Type;
/** #Column(type="string") */
protected $Value;
}
I've been struggling for the past few days on a simple case of cascade removing using Doctrine.
Doctrine and Symfony are up to date.
I have two entities Serie and Asset that are linked to each other by two relationships OneToOne and OneToMany.
The schema is exactly like this :
A Serie has many Assets. (content).
A Serie can have an Asset. (a preview, this field is nullable).
However, no matter how I try to write and rewrite the annotations, I ALWAYS end up with this error:
An exception occurred while executing 'DELETE FROM serie WHERE id = ?' with params [1]:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or
update a parent row: a foreign key constraint fails
(galanthis.asset, CONSTRAINT FK_2AF5A5CAA3A9334 FOREIGN KEY
(serie) REFERENCES serie (id))
Of course, the problem disappear if I delete the "preview" field and its annotations in the following code:
/**
* Serie
*
* #ORM\Table(name="serie")
* #ORM\Entity(repositoryClass="Gedmo\Sortable\Entity\Repository\SortableRepository")
* #ORM\HasLifecycleCallbacks
*/
class Serie
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=96)
*/
private $title;
/**
* #var integer
*
* #Gedmo\SortablePosition
* #ORM\Column(name="position", type="integer", nullable=true)
*/
private $position;
/**
* #var \Portfolio
*
* #ORM\ManyToOne(targetEntity="Portfolio", inversedBy="series")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="portfolio", referencedColumnName="id")
* })
*/
private $portfolio;
/**
* #var \Asset
*
* #ORM\OneToOne(targetEntity="Asset")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="preview", referencedColumnName="id", nullable=true, onDelete="SET NULL")
* })
*/
private $preview;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\OneToMany(targetEntity="Asset", mappedBy="serie", cascade={"remove"})
**/
private $assets;
Here's the code for the Asset entity:
/**
* Asset
*
* #ORM\Table(name="asset")
* #ORM\Entity(repositoryClass="Gedmo\Sortable\Entity\Repository\SortableRepository")
* #ORM\HasLifecycleCallbacks
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="asset", type="string")
* #ORM\DiscriminatorMap({"asset" = "Asset", "video" = "Video","image" = "Image"})
*
*/
class Asset
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="path", type="string", length=128)
*/
protected $path;
/**
* #var string
*
* #ORM\Column(name="filename", type="string", length=64)
*/
protected $filename;
/**
* #var integer
*
* #ORM\Column(name="position", type="integer", nullable=true)
* #Gedmo\SortablePosition
*/
protected $position;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255, nullable=true)
*/
protected $description;
/**
* #var string
*
* #ORM\Column(name="mime", type="string", length=16, nullable=true)
*/
protected $mime;
/**
* #var \Serie
*
* #ORM\ManyToOne(targetEntity="Serie", inversedBy="assets")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="serie", referencedColumnName="id")
* })
*/
protected $serie;
/**
* #var UploadedFile
*/
protected $file;
/**
* #var string
*/
protected $extension;
It's driving me crazy, it's just some simple relationships... Is there a mistake I'm not seeing anymore, or do i need to use a workaround?
My guess is to set the cascade={"remove"} on the ManyToOne relationship in the Asset entity and not the other way around. That way, it tells Doctrine what to do when you delete a serie that is linked to many assets.