Doctrine wont generate columns for properites inherited from mapped super class - symfony

I have a mapped super class and two entities that extend that base class. I followed this docs, but when I run bin/console doctrine:schema:update both of my entities are generated only with the properties declared on the entity itself but not the ones declared in the mapped super class. What am I missing or doing wrong?
mapped super class:
<?php
namespace AppBundle\Model;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\User;
/**
* #ORM\MappedSuperclass(repositoryClass="Doctrine\ORM\EntityRepository")
*/
class Comment {
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="comments")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $author;
/**
* #ORM\Column(name="content", type="text", length=500)
*/
private $content;
/**
* #ORM\Column(name="date", type="datetime")
*/
private $date;
// setters and getters...
}
extending entities:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Model\Comment;
/**
* #ORM\Entity
* #ORM\Table(name="component_comment")
*/
class ComponentComment extends Comment {
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="ComponentComment", inversedBy="replies")
* #ORM\JoinColumn(name="reply_to", referencedColumnName="id")
*/
private $replyTo;
/**
* #ORM\OneToMany(targetEntity="ComponentComment", mappedBy="replyTo")
*/
private $replies;
/**
* #ORM\ManyToOne(targetEntity="Component", inversedBy="comments")
* #ORM\JoinColumn(name="component", referencedColumnName="id")
*/
private $targetComponent;
// setters and getters...
}
and
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Model\Comment;
/**
* #ORM\Entity
* #ORM\Table(name="food_comment")
*/
class FoodComment extends Comment {
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="FoodComment", inversedBy="replies")
* #ORM\JoinColumn(name="reply_to", referencedColumnName="id")
*/
private $replyTo;
/**
* #ORM\OneToMany(targetEntity="FoodComment", mappedBy="replyTo")
*/
private $replies;
/**
* #ORM\ManyToOne(targetEntity="Food", inversedBy="comments")
* #ORM\JoinColumn(name="food", referencedColumnName="id")
*/
private $targetFood;
// setters and getters...
}
And my corresponding database tables look like:
CREATE TABLE `component_comment` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`reply_to` int(11) DEFAULT NULL,
`component` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_2478D345E2B0FBEB` (`reply_to`),
KEY `IDX_2478D34549FEA157` (`component`),
CONSTRAINT `FK_2478D34549FEA157` FOREIGN KEY (`component`) REFERENCES `component` (`id`),
CONSTRAINT `FK_2478D345E2B0FBEB` FOREIGN KEY (`reply_to`) REFERENCES `component_comment` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `food_comment` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`reply_to` int(11) DEFAULT NULL,
`food` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_DBEB8E54E2B0FBEB` (`reply_to`),
KEY `IDX_DBEB8E54D43829F7` (`food`),
CONSTRAINT `FK_DBEB8E54D43829F7` FOREIGN KEY (`food`) REFERENCES `food` (`id`),
CONSTRAINT `FK_DBEB8E54E2B0FBEB` FOREIGN KEY (`reply_to`) REFERENCES `food_comment` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
The columns from common properties inherited from the Comment parent class are missing. Why is wrong with my code?

I've fond an other solution that fits better my requirements, but I think I've figured out. I haven't tested it but very likely the problem is that the mapped super class has private properties instead of protected ones. So although they were mapped properly, the sub classes didn't inherit neither the properties nor the mappings belonging to them.

I think you should place the mapped superclass under AppBundle/Entity

Related

How to modify Symfony ORM insert\update query

I have project that is migrate to Symfony, that project have multiple tables,and also some tables are migrated to ORM, but now i need to incert/update from Symfony to table that have Entity but not managed by ORM. Problem consist in not null columns that require some value and in Entity I cannot define that value because of table relations.
It posible to edit MySql query before they submited to Database.
For example i have Entity:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* User
*
* #ORM\Table(name="p_user")
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
*/
class User
{
/**
* #var int
*
* #ORM\Column(name="user_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string|null
*
* #ORM\Column(name="name", type="string", length=55, nullable=true)
*/
private $name;
/**
* #var Permission
*
* #ORM\ManyToOne(targetEntity="Permission", inversedBy="user", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="permission_id", referencedColumnName="permission_id", onDelete="CASCADE")
*/
private $permission;
}
permission_id can be null but in database is not null with default value 0, same for name but with default value ''.
That mean when I make flush, ORM execute INSERT INTO p_user (name, permission_id) VALUES ('name', null), but I want also to execute INSERT INTO p_user (name) VALUES ('name').
It's possible to do that I wanted.
To achieve this you can provide default values.
private $permission = 0;
private $name = '';

Doctrine keeps updating DATETIME on update CURRENT_TIMESTAMP

I have parent entity class:
namespace App\Model\Entities;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\MappedSuperclass
*/
abstract class ParentEntity
{
/**
* #var int|null
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/**
* #ORM\Column(type="datetime", columnDefinition="DATETIME on update CURRENT_TIMESTAMP")
*/
protected $modifiedOn;
}
and everytime I run php bin/console o:s:u --dump-sql or --force the console prints out that X queries will be executed and every query is for modified_on column.
ALTER TABLE contact CHANGE modified_on modified_on DATETIME on update CURRENT_TIMESTAMP;
ALTER TABLE about_us CHANGE modified_on modified_on DATETIME on update CURRENT_TIMESTAMP;
ALTER TABLE image CHANGE modified_on modified_on DATETIME on update CURRENT_TIMESTAMP;
...
In MySQL database everything is setup correctly:
CREATE TABLE `about_us` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`modified_on` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
So my question is why is this happening? Did I miss some configuration/annotation for Doctrine? Or do you have to specify this attribute in some other way?
You are probably after Lifecycle Callbacks. if so this is the way to go:
namespace App\Model\Entities;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\MappedSuperclass
* #ORM\HasLifecycleCallbacks
*/
abstract class ParentEntity
{
/**
* #var int|null
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/**
* #ORM\Column(type="datetime")
*/
protected $modifiedOn;
/**
* #ORM\PreUpdate
*/
public function setModifiedOn()
{
$this->modifiedOn = new \DateTime();
}
}

Doctrine Composite primary key foreign key

I realize a web application with Symfony 2 from an existing database.
I have set up an entity with a primary key consisting of two foreign keys.
example:
Entity1 with a composite primary key: property1 (PK), property2 (PK)
Entity2 primary key consists of two foreign keys: property1 (PK FK), property2 (PK FK), propriete3 (PK)
I don't how to implement this association:
In the entity2 i do :
/**
* #ORM\ManyToOne (targetEntity = "Entity1")
* #ORM\JoinColumns ({
* #ORM\JoinColumn (name = "property1" referencedColumnName = "property1")
* #ORM\JoinColumn (name = "property2" referencedColumnName = "property2")
* #ORM\Id
* #})
*/
private $entity1;
But I get an error:
It is not possible to map entity 'ExempleBundle\Entity\Entite1' with a composite primary key as part of the primary key of another entity 'ExempleBundle\Entity\Entite2#entite1'.
How to properly handle this kind of association with Doctrine
I tried to follow this example but I do not understand : http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html#use-case-1-dynamic-attributes
Can you give an example of two entities with a similar case and especially on how to make a joint in this case.
I found a work-around that gets around the issue, by defining a separate foreign key, using the original foreign key columns as the join columns.
/** #Id #Column(...) */
protected $property1;
/** #Id #Column(...) */
protected $property2;
/** #Id #Column(...) */
protected $property3;
/**
* #ManyToOne(targetEntity="Entity1")
* #JoinColumns({
* #JoinColumn(name="property1", referencedColumnName="property1"),
* #JoinColumn(name="property2", referencedColumnName="property2")
* })
**/
protected $foreignObject;
It is a example that works:
<?php
namespace Project\WorkflowBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="opinion")
*/
class Opinion
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="\Project\WorkflowBundle\Entity\Comision_Proyecto", inversedBy="opiniones")
*/
protected $comision;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="\Project\WorkflowBundle\Entity\Persona", inversedBy="opiniones")
*/
protected $persona;
/**
* #ORM\OneToMany(targetEntity="\Project\WorkflowBundle\Entity\Comentario", mappedBy="opinion")
*/
protected $comentarios;
}
the other class:
<?php
namespace Project\WorkflowBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="comentario")
*/
class Comentario
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/**
* #ORM\Column(type="boolean")
*/
protected $privado;
/**
* #ORM\ManyToOne(targetEntity="\Project\WorkflowBundle\Entity\Opinion")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="comision_id", referencedColumnName="comision_id"),
* #ORM\JoinColumn(name="persona_id", referencedColumnName="persona_id")
* })
*/
protected $opinion;
}
Doctrine2 do not manage foreign composite keys to reference an entity with its composite primary keys
The cases where Doctrine2 manage correctly composite primary keys are mainly :
OneToMany: The associated entity (ArticleAttributes) uses as primary key, the primary key of the referenced entity (Artile) and an other self field (attribute)
Article (id, title, ...),
ArticleAttributes (#article_id, #attribute, value, ...)
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html#use-case-1-dynamic-attributes
ManyToMany: Join-Table with Metadata
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html#use-case-3-join-table-with-metadata
In your case, you want to reference an entity which hasn't got a unqiue identifier but a composite keys, Doctrine do not manage this case. You can only have composite key for association entity type.
Generally, I avoid to use composite keys for the main models. I reserved composite keys for model of association type.
So a solution is to use a primary key for your main model Entity1
Hope this helps.

symfony2 and doctrine: in one to many relationship, unique key for foreign keys are assigned

I have this entity:
class Partido
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Project\Bundle\AdminBundle\Entity\Jornada", inversedBy="partidos")
* #ORM\JoinColumn(name="temporada_id", referencedColumnName="id")
**/
private $jornada;
/**
* #ORM\OneToOne(targetEntity="Project\Bundle\AdminBundle\Entity\Equipo")
* #ORM\JoinColumn(name="equipo1_id", referencedColumnName="id")
*/
private $equipo1;
/**
* #ORM\OneToOne(targetEntity="Project\Bundle\AdminBundle\Entity\Equipo")
* #ORM\JoinColumn(name="equipo2_id", referencedColumnName="id")
*/
private $equipo2;
When I generate the database, equipo1 and equipo2 are uniquey keys, why?
CREATE TABLE IF NOT EXISTS `partido` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`temporada_id` int(11) DEFAULT NULL,
`equipo1_id` int(11) DEFAULT NULL,
`equipo2_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_4E79750B8D588AD` (`equipo1_id`),
UNIQUE KEY `UNIQ_4E79750B1A602743` (`equipo2_id`),
KEY `IDX_4E79750B6E1CF8A8` (`temporada_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=8 ;
I dont want them to be unique keys..
your columns join with Equipo entity "ManyToOne":
/**
* #ORM\ManyToOne(targetEntity="Project\Bundle\AdminBundle\Entity\Equipo")
* #ORM\JoinColumn(name="equipo1_id", referencedColumnName="id")
*/
private $equipo1;
/**
* #ORM\ManyToOne(targetEntity="Project\Bundle\AdminBundle\Entity\Equipo")
* #ORM\JoinColumn(name="equipo2_id", referencedColumnName="id")
*/
private $equipo2;

Not Null field with SonataAdmin Bundle

Hi I have a problem with SonataAdminBundle.
I've created "Job" table in DB and I use in backend of my website.
When I insert data, I have an error with "not null" fields in my table Job.
For example I have "nb_comment" that is the number of comments of each job,so when I insert in backend all information about Job I don't use a NOT NULL field "nb_comment",and I have the following error :
PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'nb_comment' cannot be null
add in #ORM annotation nullable=true
use Doctrine\ORM\Mapping as ORM;
...
/**
* #var integer $nb_comment
* #ORM\Column(name="nb_comment", type="integer", nullable=true)
*/
private $nb_comment;
or add Constraint validator with #Assert declaration and initialize in construct
use Symfony\Component\Validator\Constraints as Assert;
/**
* #var integer $nb_comment
* #ORM\Column(name="nb_comment", type="integer")
* #Assert\NotNull()
*/
private $nb_comment;
public function __construct()
{
$this->nb_comment = 0;
}
I had the same problem I think and it works for me. You have to initialize the variable nb_comment in the model with null, like this:
/**
* #var integer $nb_comment
*/
private $nb_comment = null;

Resources