Doctrine2 what is the best way to update entities? ( Database => Doctrine ) - symfony

Let's say I have all my entities set and I have my repositories linked in annotations like this:
/**
* User
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
* #ORM\Table(name="user")
*/
class User
{....}
now I go to my sql database and add a new column or any other change. I need to update doctrine model and at the moment I do it like this :
1 ) php bin/console doctrine:mapping:import App\\Entity annotation --path=src/Entity
2) php bin/console make:entity --regenerate App
these commands are purging my entities annotations and I get:
/**
* User
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User
{....}
3) I have to relink all my repositories manually in each entities (I have 12)
QUESTION:
Is there a way to update from database to entity while keeping all repository links at the top of my entities? How do you do it ?
I could not find anything in the doctrine manual; I was hoping for a doctrine:mapping:import setting ?

Instead of going from database to entity, go by another way: from entity to database
add needed property to the entity. like
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
protected $name;
run php bin/console doctrine:migrations:diff you will get migration with changes like $this->addSql('ALTER TABLE user ADD name VARCHAR(255) DEFAULT NULL');
run migration
EDIT
If you still want to go by your way, at least you could narrow down changes only to one entity by adding --filter="user" to both your commands

Related

Doctrine throw error: "A new entity was found through the relationship" after removing entity

Let's say I have two entities, Project and User with relation.
Project.php
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="User")
* #ORM\JoinColumn(onDelete="SET NULL")
*/
private $creator;
When I remove the User entity, the doctrine leaves the User object(without ID) in the Project entity. In a normal situation, this is fine but I am using DomainEvents. In this scenario, after removing the User entity, DomainEvent triggers saving some data in the DB and secondary saving data(after removing) throw this error. This happens because of now in the Project entity we have the detached(from the EM) User object without ID.
I thought about a listener, that will remove empty objects in the entity after removing, but I am not sure that is a good variant
What is the best variant for solving this error?
The onDelete option doesn't apply a cascade removing.
If you want to do so I think you should have to add the cascade={"remove"} option to the ManyToOne.
Try as following :
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="User", cascade={"remove"})
* #ORM\JoinColumn(onDelete="SET NULL")
*/
private $creator;
Removing entity in doctrine

Proper migration path to add a unique token column in existing entity for symfony2/doctrine

I would like to add a new unique token column to an existing customer entity.
I know I need to change the customer class, update the schema, create unique token for each customer.
This is easy in dev as I just wipe the data from the database and start new. But I can't do this on the production database.
So, What is the proper or appropriate method to make this change?
Here are my changes to Customer.php:
/**
* Customer
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppBundle\Entity\CustomerRepository")
* #UniqueEntity("urlToken")
*/
class Customer
{
...
/**
* #var string
*
* #ORM\Column(name="urlToken", type="string", unique=true)
*/
private $urlToken;
The proper way to deploy schema changes on production is to use Doctrine Migrations.
1) Modify the entity class
2) Generate doctrine migrations:
$ ./doctrine migrations:diff
3) Update doctrine proxy classes if necessary:
$ ./doctrine orm:generate:proxies
4) Execute migrations on production:
$ ./doctrine migrations:migrate

Symfony - Doctrine not generating entity

i have a quite primitve problem:
I created an Entity in my Symfony App:
src/AppBundle/Model/Article/Article.php:
<?php
namespace AppBundle\Model\Article;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="articles")
*/
class Article {
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length="255", nullable=false)
*/
private $name;
}
When i type in console:
php app/console doctrine:generate:entities AppBundle
it prints:
Bundle "AppBundle" does not contain any mapped entities.
And when i type:
php app/console doctrine:generate:entities AppBundle/Model/Article/Article
it prints:
Class "AppBundle\Model\Article\Article" is not a valid entity or mapped super class.
Anybody has some idea how to solve this?
I already followed some solutions on stackoverflow like changing or turning off cache/clearing cache/ etc.. but none works.
Thanks and Greetings!
Probably Doctrine doesn't know about these mappings.
Have you created this bundle with a generator?
Check your config.yml in app/config, you should have an entry under following keys structure:
doctrine:
orm:
mappings:
AppBundle: ~
Edit:
Ok, you use custom structure.
Default namespace should look like that:
AppBundle\Entity
So full class name should be AppBundle\Entity\Article
If you want to stick with custom mappings, check configuration docs.
You should add all your Entities in the Entity Folder, remember Entity and Model are different concepts. You can create others folders like Model, Handlers, Managers. Another important thing is not to confuse Data Base with Object-oriented programming.
You need to make sure that you do not use Doctrine\Common\Annotations\SimpleAnnotationReader class. Instead Doctrine\Common\Annotations\AnnotationReader should be used.
Simple reader doesn't support #ORM\Annotation, only #Annotation.

Doctrine Associations Mapping

I'm trying Doctrine Associations with Symfony2 for the first time and it's giving me headache.
I have an Admin interface that can, among other things, upload images. I want to know which administrator uploaded what image so i've putted a foreign key administrator to my images table. To gather data, a simple JOIN is necessary to collect the data but with Doctrine, I'm stuck, altough it seems simple.
So, I have an Administrator object that reflects the table. In that object, I have this statement...
#ORM\OneToMany(targetEntity="ImageBundleNamespace\ImageEntity", mappedBy="administrator")
It's simple. In my ImageEntity object (that reflects Images table) is a foreigh key column administrator.
In the ImageEntity object, I use this statement...
#ORM\ManyToOne(targetEntity="AdministratorNamespace\Administrator", inversedBy="imageEntity")
#ORM\JoinColumn(name="administrator", referencedColumnName="id")
There is a administrator field in ImageEntity and a imageEntity field in Administrator that the formentioned statements are mapping.
It doesn't work.
I've run the SchemaValidator on the EntityManger and it says the the administrator field on the ImageEntity object is not defined as an association. The second message says that the administrator field does not exist.
If it helps, this is my DQL for all of it...
'SELECT i.id,
i.imeSlike,
i.velicina,
i.ekstenzija,
i.paths,
a.username,
a.ime,
a.prezime FROM ImageBundle:ImageEntity i
JOIN a.administrator a'
Thank you in advance for all the help.
EDIT
I had a mistake in DQL. Corrected it.
EDIT
I forgot to add the source code.
Association part of the Administrator...
**
* #ORM\OneToMany(targetEntity="Icoo\Administracija\GalerijaBundle\Entity\ImageEntity", mappedBy="administrator")
*/
protected $imageEntity;
public function __construct() {
$this->imageEntity = new ArrayCollection();
}
Association part of the ImageEntity
/**
* #ORM\Column(type="smallint")
*
* #ORM\ManyToOne(targetEntity="Icoo\LoginBundle\Entity\Administrator", inversedBy="imageEntity")
* #ORM\JoinColumn(name="administrator", referencedColumnName="id")
*
*/
protected $administrator;
In the administrator class, you have:
/**
* #ORM\Column(type="smallint")
*
* #ORM\ManyToOne(targetEntity="Icoo\LoginBundle\Entity\Administrator", inversedBy="imageEntity")
* #ORM\JoinColumn(name="administrator", referencedColumnName="id")
*
*/
you need to remove the #ORM\Column(type="smallint")
This must be all. Let me know.
You can separate field mapping from association mapping:
/**
* #ORM\Column(name="administrator", type="smallint", nullable=false, options={"unsigned"=true})
*/
protected $administratorId;
/**
* #ORM\ManyToOne(targetEntity="Icoo\LoginBundle\Entity\Administrator", inversedBy="imageEntity")
* #ORM\JoinColumn(name="administrator", referencedColumnName="id")
**/
protected $administrator;
If you go further you can put exception into $administratorId getter/setter to avoid usage of it.
As i have tested, doctrine ignores value into $administratorId property when you persist/flush your entity (For confirmation you can look at prepareUpdateData() in Doctrine\ORM\Persisters\BasicEntityPersister)
EDIT
I think, my previous variant is possible but wrong. Because, doctrine gets field mapping from definitions in referencedColumn, you can add some more definitions using
* #ORM\JoinColumn(name="administrator", referencedColumnName="id", unique, nullable, onDelete, columnDefinition, fieldName)
This means that your image_entity.administrator field in db will be the same as your administrator.id field in db (except of additional definitions)

Symfony: How do I annotate entity properties that are objects to get Doctrine to store a foreign key?

I'm still getting to grips with Symfony and Doctine and I appreciate this might sound overly simple.
I have at present two basic entities: WebSite (having id and canonicalUrl properties) and Job which has, as one property, a WebSite.
A Job has one WebSite; a WebSite can be referenced by many Jobs. Both are under the same namespace.
Relevant here is the Job entity:
/**
*
* #ORM\Entity
*/
class Job
{
/**
*
* #var integer
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
*
* #var WebSite
*/
protected $website;
}
In database terms, a persisted Job should be storing the id of the relevant WebSite.
Without any changes to the above, calling php app/console doctrine:migrations:diff generates a new migration for a table named Job with a single id field.
How do I annotate Job::website such that Doctrine knows to create an integer field and to get the value as the id of the Website object?
You must explicitly define the relationship. The shortest would be
/**
* #ORM\Entity
*/
class Job
{
/**
* #var WebSite
*
* #ORM\ManyToOne(targetEntity="Website")
*/
protected $website;
}
However, should you find yourself wanting to tweak the relationship to better suit your needs, have a look at the annotation reference (ManyToOne and JoinColumn for this particular case). There's also quite a comprehensive article about association mapping, which you might find interesting.

Resources