Symfony Doctrine Mapping - Different entity and property names in database - php

I have issue with updating entities with console command bin/console doctrine:mapping:import. Project requirements forces different names for class names and properties in code and in database, for example:
/**
*
* #ORM\Table(name="user_db")
*/
class User
{
/**
* #var int
*
* #ORM\Column(name="id_user", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #ORM\SequenceGenerator(sequenceName="user_id_user_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="mail", type="string", length=128, nullable=false)
*/
private $email;
}
Database schema will be updated many times during project development. After running doctrine:mapping:import again instead of mapping user_db table to User entity (because annotation points to this table) this command creates new entity UserDB. After every database change I'm forced to manually compare changes and add them to code. Is there any way to update mapping for those entities (change column details, add new columns, remove removed)?
I'm using Symfony 5.4 as it is LTS version currently.

Related

Doctrine migrations wont recognise changes to annotations (in production)

The original problem
The reasons, notes and members fields bellow where #ORM\Column(type="string", length=20000) which did not work because that is too long for a VARCHAR so I changed them all to #ORM\Column(type="text")
And Now
It is possible that I have misunderstood the correct way to handle migrations in productions but I can't get my database to match my entity. Running php bin/console doctrine:migrations:diff or php bin/console doctrine:schema:update --dump-sql doctrine tries to update the database to an old version of Request.php like it has been cached but even after running clear-metadata the migrations all say VARCHAR(20000) like in this sql dump after I manually changed the database:
ALTER TABLE request CHANGE reasons reasons VARCHAR(20000) NOT NULL, CHANGE notes notes VARCHAR(20000) DEFAULT NULL, CHANGE members members VARCHAR(20000) NOT NULL;
Current Request.php
namespace App\Entity;
use App\Repository\RequestRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass=RequestRepository::class)
*/
class Request
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="time")
* #Assert\LessThan(propertyPath="endTime", message="The booking must start before it ends")
*/
private $startTime;
/**
* #ORM\Column(type="time")
*/
private $endTime;
/**
* #ORM\Column(type="date")
*/
private $date;
/**
* #ORM\Column(type="text")
*/
private $reasons;
/**
* #ORM\Column(type="text", nullable=true)
*/
private $notes;
/**
* #ORM\Column(type="text")
*/
private $status;
/**
* #ORM\ManyToOne(targetEntity=User::class, inversedBy="requests")
* #ORM\JoinColumn(nullable=true)
*/
private $user;
/**
* #ORM\Column(type="text")
*/
private $members;
I have tried removing the Request.php entity but then doctrine gets upset that it is gone. (I do have a relational link to the user table here but it is one to many).
Changing the names of members reasons and notes worked but when I changed the names back it wanted to set them back to VARCHAR(20000). Where is it holding this info. How do I get rid of it?
Doctrine Metadata is cached. When you clear the cache (and warming it back up), symfony runs "compiler passes" that among other things read annotations to build the metadata, proxy objects, registers repositories, all this kind of stuff (obviously other doctrine-unrelated stuff as well).
Running bin/console cache:clear should solve your problems. (It also should be part of your deployment process. And unless you copy over the vendor dir as well, composer install too).

How to update entities and database

I'm working to fix some bugs and add new features to a project already in production.
What I need to do I think is very simple for who knows Symfony2 and Doctrine but I'm newbie and I don't know how to achive what i need:
I've got an existing entity on PHP side that is associated with a table in the database.
What I need is to create another entity that has some foreign key with other table.
I've tried to create the table into database first, but I don't know how to create the associated entity in PHP ( with correct annotation pointing to the foreign keys) and how to edit the other entities that need new attribute in class.
What I've also tried is to create an annotated PHP class as this:
<?php
namespace MyProject\MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\VirtualProperty;
use MyProject\MyBundle\Model\ItemThumb;
/**
* #ORM\Entity
* #ORM\Table(name="wall_message_comment_answer")
*/
class WallMessageCommentAnswer {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #Groups({"user_details", "search_around"})
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="wall_message_comments")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
* #Groups({})
*/
public $user;
/**
* #var WallMessage
* #ORM\ManyToOne(targetEntity="WallMessage", inversedBy="users_comments")
* #ORM\JoinColumn(name="wall_message_id", referencedColumnName="id", onDelete="CASCADE")
*/
public $wall_message;
/**
* #var WallMessage
* #ORM\OneToMany(targetEntity="WallMessageComment", mappedBy="comment_answers")
* #ORM\JoinColumn(name="wall_message_comment_id", referencedColumnName="id", onDelete="CASCADE")
*/
public $wall_message_comment;
/**
* #var string
* #ORM\Column(type="string")
* #Groups({"user_details", "search_around"})
*/
public $content;
/**
* #var int
* #ORM\Column(type="integer")
* #Groups({"user_details", "search_around"})
*/
public $timestamp;
}
and then, trying to create getter and setter, launch the command:
php app/console doctrine:generate:entities MyProjectMyBundle/Entity/WallMessageCommentAnswer
But it gives me that error:
[Symfony\Component\Debug\Exception\FatalErrorException]
Compile Error: Cannot redeclare MyProject\MyBundle\Entity\User::setDocumentNumber()
as it tries to create again other entities.
Could anyone help me?
Thanks!
Why don't you try creating Entity using php app/console doctrine:generate:entity command. This will ask you for Bundle name, Entity name and columns.
After this you'll have .php file created in specified bundle. Following this URL to manually add relationship between your current and new entity.
http://symfony.com/doc/current/book/doctrine.html#relationship-mapping-metadata
This is how you can give manyToOne relationship in Symfony usng annotations, you can switch your way to assigning this relationship. (YML or any other supported by Symfony)
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="products")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
And specify oneToMany in target entity like this
/**
* #ORM\OneToMany(targetEntity="Product", mappedBy="category")
*/
After you're done with this run the following command to get the SQL queries of the changes.
php pap/console doctrine:schema:update --dump-sql
You'll have SQL queries output which you need to copy and run on the production environment. If your production and testing environment are same run following command.
php pap/console doctrine:schema:update --force
For above procedure you don't have the table to be created in database. Doctrine does that for you.
If you already have table created you can remove that as it's going to be created automatically when you force the schema.

Doctrine Is not a valid entity or mapped super class

i have a problem with doctrine and i getting this error from auto generated entity file "Class "Users" is not a valid entity or mapped super class.". File and comments inside looks like fine i dont understund why or i something miss?
Some piece of code
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* Users
*
* #ORM\Table(name="users", uniqueConstraints={#ORM\UniqueConstraint(name="username", columns={"username"})})
* #ORM\Entity
*/
class Users
{
/**
* #var integer
*
* #ORM\Column(name="userid", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $userid;
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=100, nullable=false)
*/
private $username;
Doctrine 2 annotation mapping might have been configured to negate the need for the #ORM prefix.
I would try replacing #ORM\ with #. For example #Entity
As far as i recall, these errors happen when doctrine cant find the entity, double check the namespace, by default the entity folder in symfony is "Entity" (Uppercase!). Also check the config files if auto_mapping is set to true.
for me this problem was solved after adding following namespace
use Doctrine\Common\Annotations\AnnotationReader;
in my doctrine.php

Doctrine 2 OneToOne Identity through foreign Entities Error while persisting

We had to refactor many entities in our application because we share database and tables with another app and there was an update that changed the data structure and we must follow up to the new structure.
This meant that some entities were split in 2 or 3 tables so we followed the tutorial for setting up OneToOne relations but ended up with an issue on every attempt to persist both main and related entities.
Whenever we try to flush changes through the entity manager (after persisting both main and related entity either with or without cascade persist) we get 500 error status response, no response data (even using app_dev.php) and we get this message in the log:
request.CRITICAL:
Uncaught PHP Exception Symfony\Component\Debug\Exception\ContextErrorException:
"Notice: Undefined index: 000000003440ddf300000000391d8640" at
vendor\doctrine\orm\lib\Doctrine\ORM\UnitOfWork.php line 2905
{"exception":"[object]
(Symfony\\Component\\Debug\\Exception\\ContextErrorException(code: 0):
Notice: Undefined index: 000000003440ddf300000000391d8640 at
vendor\\doctrine\\orm\\lib\\Doctrine\\ORM\\UnitOfWork.php:2905)"} []
We are creating new entities so there is not an issue with cached entities.
Here is some sample code on how we defined the entities and the relations. (we tried both with and without id property but we ended up with the same issue)
/**
* #ORM\Table(name="contacts_accounts_1_c")
* #ORM\Entity
*/
class ContactsAccounts1C
{
/**
* #var string
* #ORM\Column(name="id", type="string", length=36, nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var ContactsAccounts1CExtradata
* #ORM\OneToOne(targetEntity="ContactsAccounts1CExtradata", mappedBy="principal", cascade={"ALL"})
*/
private $extradata;
...
}
/**
* #ORM\Table(name="contacts_accounts_1_c_extradata")
* #ORM\Entity()
*/
class ContactsAccounts1CExtradata {
/**
* #var string
* #ORM\Column(name="id", type="string", length=36, nullable=false)
*/
private $id;
/**
* #var ContactsAccounts1C
* #ORM\Id
* #ORM\OneToOne(targetEntity="ContactsAccounts1C", inversedBy="extradata")
* #ORM\JoinColumn(name="id")
*/
private $principal;
...
}
If we avoid setting/creating the extradata entity the principal entity ends up being successfully persisted.
I found this question that seems to be related but still not solved.
Thanks in advance for your help.
At a quick glance, this annotation looks out of place on principal:
* #ORM\JoinColumn(name="id")
Given that your relation is principal -> extradata it seems to have no place there.
Found the issue: GeneratedValue was being wrongly defined and overrided for the main entity.
And the solution: Use #GeneratedValue(strategy="UUID") for principal entity (owning side) and #GeneratedValue(strategy="NONE") for related entities (owned side).

Create a new table with a relation in the Database, with Doctrine in Symfony

I'm struggling with this, in my project in symfony. I have a entity content, with doctrine i have a table in my db content, that saves contents. Every content has an id. If anyone wants to see a specific content they have to request it by submitting an email, I need to associate all the emails to the specific id content. I dont want to create a new entity just to save the request emails. Is there a way to create/associate a new table with doctrine annotations. They have to be in a relation many-to-one. Or is there another simple way to save the email requests. This is the code I have, but is not working.
/**
* #ORM\Table(name="content")
* #ORM\Entity(repositoryClass="myBundle\Repository\ContentRepository")
*/
class Content{
/**
* #var integer
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $nome
* #ORM\ManyToOne(targetEntity="Content")
* #ORM\Column(name="email_request", type="string", length=255, unique=false, nullable=false )
*/
private $emailRequest;
Thanks for your time.
Your $emailRequest wouldn't be defined as Column if you want it to map entity. You need to define #ORM\JoinColumn instead.

Categories