We encounter an issue with inheritance on Symfony 5.
We created a UserBundle bundle which includes a simple User entity (id, email, password): the purpose of this bundle is to be able to easily reimport it into our various projects.
In some projets, we want to extend this entity to add some specific fields (phone, address, ...), but that's not always the case.
Here is the code we had set up:
UserBundle > User class:
<?php
namespace MyCompany\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* #ORM\MappedSuperclass()
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
...
User entity inherited:
<?php
namespace App\Entity;
use MyCompany\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* #ORM\Entity
* #UniqueEntity(fields={"email"})
*/
class User extends BaseUser
{
/**
* #ORM\Column(type="string", length=50)
*/
private $phone;
...
The inheritance works fine: the problem comes from projects for which the User entity of the bundle is sufficient for us.
=> The User class of the bundle is defined as Mapped superclass in order to be able to extend it but Doctrine can't create an associated table if there is no class which inherits from it...
We could systematically create an empty User class in src/ which inherits from the User class of the bundle, but that doesn't seem super clean to me...
I went on this post but that doesn't seem to work: Doctrine Inheritance replacement
Could anyone help us on this problem? I imagine that a solution must exist...
Thank you in advance!
The idea below does not work.
As #Cerad already pointed out, the best approach probably really is to define the concrete User in each app. Thats also what FOSUserBundle does.
I'd go with the following approach: Declare the mapped superclass abstract.
/**
* #ORM\MappedSuperclass()
*/
abstract class AbstractBaseUser implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
...
And implement a concrete empty child class User inside your bundle.
/**
* #ORM\Entity
*/
class User extends AbstractBaseUser
{
}
That way each app can either use the User of your library or inherit from it.
Related
I'm just making a new Entity as usual, but something goes wrong and console report this error and I couldn't generate the entity setter/getter:
[Doctrine\ORM\Mapping\MappingException]
Class "AppBundle\Entity\Admin_Actions" is not a valid entity or mapped super class.
Here is my Entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="admin_actions")
*/
class Admin_Actions
{
/**
* #ORM\Column(name="id",type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="uid",type="string",length=100)
*/
private $uid;
/**
* #ORM\Column(name="type",type="integer")
*/
private $type;
/**
* #ORM\Column(name="linedate",type="datetime")
*/
private $linedate;
}
If I do doctrine:mapping:info:
[Exception]
You do not have any mapped Doctrine ORM entities according to the current configuration. If you have
entities or mapping files you should check your mapping configuration for errors.
I've just waste an hour trying to investigate the problem and I've already tried to rewrite it from new but I'm missing something. What's wrong with this?
May be datetime field has same name as function/implementation in doctrine, I have got same mistake by naming a table "condition" which may be condition function in MySql query
I created a BaseBundle with a SuperUser MappedSuperClass who extends FOSUserBundle User
use FOS\UserBundle\Model\User as FOSUser;
/*
* #ORM\MappedSuperclass
*/
class SuperUser extends FOSUser
{
/**
* #var string
* #ORM\Column(name="locale", type="string", nullable=true)
*/
protected $locale;
}
In my Project I installed my BaseBundle. I created a User entity who extends my SuperUser class.
/*
* User class
*/
class User extends SuperUser
{
/**
* #var string
*/
private $fullName;
}
The problem is that when I create the table, Doctrine see only FOSUser properties and User properties but not my SuperUser properties. I can see only fullName and FOSUser properties.
My SuperUser class is bypassed..
I noticed that User class is with YAML notation, SuperUser is with PHP Annotation while FOSUser Class is with XML notation. I don't know if this create problems.
From the documentation:
A bundle can accept only one metadata definition format. For example, it's not possible to mix YAML metadata definitions with annotated PHP entity class definitions.
Try to add the YML mapping of your MappedSuperClass
I am building an application using Zend Framework and Doctrine 2.
My code looks like this:
namespace Entities;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity (repositoryClass="Repositories\Person")
* #Table(name="persons")
* #InheritanceType("SINGLE_TABLE")
* #DiscriminatorColumn(name="type", type="string")
* #DiscriminatorMap({"2"="User"})
*/
class Person
{
/**
* #Id #Column(type="integer")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
}
And my class User
namespace Entities;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity (repositoryClass="Repositories\User")
*/
class User extends Person
{
}
Now, I get this error:
Fatal error: Class 'Entities\Person' not found in C:\xamp\htdocs\Persons\application\m
odels\Entities\User.php on line 13
I have no idea why I get that error. I have tried calling the "Person" class in many different ways but the its not working. Any idea? Thanks!
When running in Zend Framework, you have an autoloader setup that handles the loading of classes for you dynamically.
When you run just the Doctrine tool from the command line, you don't have an autoloader at your disposal. Doctrine is trying to load the User class, which requires Person, and yet it doesn't (apparently) know how to load Person.
I think the simple solution would be to have require_once('Person.php'); at the top of your User entity. This is probably unnecessary for ZF, but will be helpful for Doctrine command line tools.
I have abstract entity (App - base core):
namespace App\Bundles\AppBundle\Entity;
abstract class App extends ContainerAware implements AppInterface
{
// .....
}
and self entity:
namespace AppRus\Bundles\AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM,
App\Bundles\AppBundle\Entity\App as BaseApp;
/**
* App
*
* #ORM\Table(name="apps")
* #ORM\Entity(repositoryClass="AppRus\Bundles\AppBundle\Entity\AppRepository")
*/
class App extends BaseApp
{
// ....
}
and entity for control revisions:
namespace App\Bundles\AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* AppHistory
*
* #ORM\Table(name="apps_history")
* #ORM\Entity(repositoryClass="App\Bundles\AppBundle\Entity\AppHistoryRepository")
*/
class AppHistory
{
/**
* #var integer
*
* #ORM\ManyToOne(targetEntity="App\Bundles\AppBundle\Entity\App")
* #ORM\JoinColumn(name="app_apple_id", referencedColumnName="apple_id")
*/
private $app;
}
I can't create relation AppHistory#app to App#apple_id
When I set entity to abstract class App, then doctrine create a new table "App"
When I set MappedSuperClass to abstract class App, I have error: http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html#mapped-superclasses
How can I create relation from AppHistory to abstract core App?
My understanding is that that's not possible. I think you're doing things the wrong way, at least for Doctrine2.
First of all, from the Doctrine2 docs you mention:
A mapped superclass is an abstract or concrete class that provides persistent entity state and mapping information for its subclasses, but which is not itself an entity.
You can't create a relation to something that's not an entity!
To solve your immediate problem (~version control~ in doctrine), check out EntityAudit on Github instead.
I'm searching for a solution for the following problem with a database inheritance using Doctrine 2 built in Symfony 2 framework. This is what I want to do...
I want to create two tables (UredniHodiny, KonzultacniHodiny) with the same interface as the abstract class Hodiny. This is how I'm trying to do it
<?php
// src/CvutPWT/ImportBundle/Entity/Hodiny.php
namespace CvutPWT\ImportBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\MappedSuperclass
*/
abstract class Hodiny
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Osoba")
*/
protected $osoba;
/**
* #ORM\ManyToOne(targetEntity="Mistnost")
*/
protected $mistnost;
/**
* #ORM\Column(type="datetime")
*/
protected $zacatek;
/**
* #ORM\Column(type="datetime")
*/
protected $konec;
}
<?php
// src/CvutPWT/ImportBundle/Entity/KonzultacniHodiny.php
namespace CvutPWT\ImportBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="konzultacnihodiny")
*/
class KonzultacniHodiny extends Hodiny
{
}
<?php
// src/CvutPWT/ImportBundle/Entity/UredniHodiny.php
namespace CvutPWT\ImportBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="urednihodiny")
*/
class UredniHodiny extends Hodiny
{
}
Now when I run php app/console doctrine:generate:entities CvutPWTImportBundle Symfony generates all variables (more precisely columns) from class Hodiny as private variables to both child classes. Now when I'm trying to create those tables with app/console doctrine:schema:update --force I'm getting errors that $id must be protected or weaker. When I change this protection manually I am able to create tables but there is only one column (id). But this is not what I was hoping for. Can somebody give me any advice what I'm doing wrong?
This is not table inheritance. Mapped super classes are just mapping inheritance.
The tables corresponding to your final entities will not be relied together in any way.
If you want real table inheritance (single table or joined table), use this: http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/inheritance-mapping.html#single-table-inheritance
If you still want to use mapped super classes, then you will have to put the #ORM\Id definition in both final classes. You can not put ids in mapped super classes.