How to rename Entity and attribute in symfony - symfony

I just want to rename "EntityName" to something else the most easily possible, with the database entry. Also how can I rename an Attribute?
So, I have an Entity called "EntityName" (for exemple) in /appname/src/Entity/EntityName.php like this:
<?php
namespace App\Entity;
use App\Repository\EntityNameRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=EntityNameRepository::class)
*/
class EntityName
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
[...]
When I try to rename the name of the class and try php bin/console doctrine:schema:update --dump-sql or --force I get this error:
In EntityName.php line 11:
Compile Error: Cannot declare class App\Entity\NewName, because the name is already in use
(I think I cannot rename beaucause it check itself if it already exist.)

I'd advise caution, specially if it's a production environment.
doctrine:schema:update --force (or doctrine:migrations:diff or make:migration, for that matter) doesn't detect changes so it will drop your existing table (along with all your data) and create a new one.
The safest way to preserve data would be to hand-create a migration with the ALTER TABLE ... RENAME. You can also use the #Table(name="old_table_name") annotation to preserve the original name, although this might be a bit confusing when looking at the database alone.
Depending on your IDE you might need more or less elbow grease. Chances are that the following will be handled correctly:
Both the entity and repository class name and file name, making them match (even in the caseName).
The entity class name in the repository constructor.
The repository class name in the repositoryClass annotation of the entity.
targetEntity annotations in relations.
There will be the property names themselves in the related classes (and JoinTableand mappedBy / inversedBy if applicable) left to change, if you wish to keep things consistent. If so, you would have to add the needed statements to the migration as well, and you might need to disable the constraints in the process. --dump-sql might be helpful on hinting what tables need renaming, but you won't be able to use the sql straight up.
The easiest way, if you don't care about your data, would be doctrine:schema:update --force indeed.

If you want to rename the entity means you have to change both Entity and Repository Class name and file name too. Then have to change Both classes import statements properly. After that just run this comment bin/console c:c.

If you want to rename an entity, you only need to change its class name AND file name to make it match. Also make sure the namespace match file path.
If all these things are right, then make sure you don't have another file which would contain the same namespace and class name you are trying to use for your "NewName" class
If you still get the error message, then you might want to clear you cache by running php bin/console c:c
Lastly, if it still fails, you might want to dump the autoload by running composer dump-autoload (or if you are using Phpstorm: tools > composer > dump autoloader)

Related

Symfony doctrine reverse engineering and Apiplatform

Is there a way to create Apiplatform enabled entities directly from database schemas?
I successfully create the entities using php bin/console doctrine:mapping:import "App\Entity" annotation --path=src/Entity , but now i have to add manually the reference to Apiplatform resources in 120 entities like here. Is there another way?
Thanks in advance.
This feature isn’t supported out of the box (but it would be nice to add it). There is an open issue to add this feature to MakerBundle, but this hasn’t been implemented at time of writing.
However, you can easily achieve the same effect by using the "search and replace" feature of your IDE or by using sed: find every occurrences of #ORM\Entity and replace them with:
#ORM\Entity
#\ApiPlatform\Core\Annotation\ApiResource
You may want to run PHP CS Fixer after that to change the fully qualified class name by a use statement.

PHP 7 and Doctrine Group Uses

I want to use some features of PHP 7 but I'm kinda struggling with it.
I have a Symfony-Project using Doctrine to map some Entities. New in PHP 7 are the GROUP USE-Statemens, which I wanted to try. But it seems I'm doing something wrong, since Symfony / Doctrine can't resolve the Annotations in the Entity-Object.
Use-Statement:
use Doctrine\ORM\Mapping\{Entity, Id, Table, Column, GeneratedValue, JoinColumn, OneToOne, ManyToMany, JoinTable};
Entity
/**
* #Entity
* #Table(name="expansion")
*/
class Expansion {
..
}
Exception
[Semantical Error] The annotation "#Entity" in class AppBundle\Entity\Expansion was never imported. Did you maybe forget to add a "use" statement for this annotation?
If I use the single USE-Statements, the import works perfectly...
What am I doing wrong? Versions are correct. Also PHPStorm is saying that 'Alias XY' is never used.
Thanks for your support!
I'm not 100% sure but I bet that the Doctrine\Common\Annotations component cannot handle PHP7 grouped use statements yet. I could not find any written statement that confirms this assumption but Doctrine\Common\Annotations\TokenParser::parseUseStatement does not seem to handle grouped namespaces at all.

Doctrine2 bug imports 'private' variables from MappedSuperClass when generating entities

I'm using Symfony's entity classes in conjunction with Doctrine's ORM annotation to persist the values to the database. Most tables need a few standard fields, so I have created a base entity that all other entities can extend. According to the documentation this is called a MappedSuperClass: http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html
// src/Acme/Bundle/Entity/Base.php
namespace Acme\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\MappedSuperclass
* #ORM\HasLifecycleCallbacks()
*/
class Base {
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
// more values...
}
I then create multiple entities that extend this base:
// src/Acme/Bundle/Entity/View.php
namespace Acme\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
View extends Entity\Base
{
// entity definitions
}
Is this the best way to set default definitions for an entity? If you have better suggestions, let me know.
Next, when I generate entities via:
php app/console doctrine:generate:entities Acme\Bundle
It works great the first time to create the getters and setters, but if I make changes to an entity and generate again, it gives an error like this:
Fatal error: Access level to Acme\Bundle\Entity\View::$id must be protected (as in class Acme\Bundle\Entity\Base) or weaker in /src/Acme/Bundle/Entity/View.php
This is happening because doctrine:generate:entities is importing the 'protected' variables from the MappedSuperClass into the extending entity as 'private'.
Others have complained about this error in other contexts without a solution:
FOSUserBundle generate:entities does not work, Access level of fields too high
https://github.com/FriendsOfSymfony/FOSUserBundle/issues/102
QUESTION: Is doctrine supposed to be importing the protected variables? And is it supposed to be setting them as "private"? Or is this just a known Symfony bug?
It seems like it should not import the protected variables since the #ORM definitions are in the MappedSuperClass already and those are not imported (and when I delete the imported private variables it works fine). But if it does import them, it should not be setting them as private...
I literally have to do a search and replace through all my entities to delete these. Every. Single. Time.
What is the suggested course of action here? If this is a bug, has someone reported this and what is the timeline for fixing? How should I search for this issue on github and report it if it's not reported?
Question 2: As long as this bug exists, is there a way to just generate the getters/setters on a Single Entity?
e.g. php app/console doctrine:generate:entities Acme\Bundle\Entity\View (this doesn't work of course). If I could generate only one entity at a time, it would be less of a hassle deleting all the imported private variables across all my entities.
[EDIT: I have answered this question below]
The answer to #2 is, yes, you can generate entity getters/setters for just one single entity.
From the command line, if you type:
php app/console doctrine:generate:entities --help
You get a list of options. There you will see how to limit entities to bundle, single entity in a bundle, or an entire namespace:
You have to limit generation of entities:
* To a bundle:
php app/console doctrine:generate:entities MyCustomBundle
* To a single entity:
php app/console doctrine:generate:entities MyCustomBundle:User
php app/console doctrine:generate:entities MyCustomBundle/Entity/User
* To a namespace
php app/console doctrine:generate:entities MyCustomBundle/Entity
For the question 1, you need to redefine each primary key when entities are inherited.

Add a custom function in a vendor repository

I'm using CCDNForum's ForumBundle (the bundle itself is not relevant, my question isn't related to this bundle specifically but is more general) in my Symfony website, and I want to customize it, so naturally I created a AcmeForumBundle whose parent is CCDNForumForumBundle. The only thing I want to change is to add a new custom function in let say the CategoryRepository associated to the Category entity.
So I created a CategoryRepository.php in my AcmeForumBundle extending the CategoryRepository.php of CCDNForum, and this is not sufficient because the default repository of the Category entity is CCDNForum's CategoryRepository.
The next thing I did was to create a new AcmeForumBundle Category entity extending CCDNForum's Category entity, changing of course the default associated repository
namespace Acme\ForumBundle\Entity;
use CCDNForum\ForumBundle\Entity\Category as BaseCategory;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection as ArrayCollection;
/**
* #ORM\Entity
* #ORM\Entity(repositoryClass="Acme\ForumBundle\Repository\CategoryRepository")
* #ORM\Table(name="CC_Forum_Category")
*/
class Category extends BaseCategory
{
}
I added the #ORM\Table line because I had an SQL error "acme_category" table not found. The class is of course empty as I have nothing to change in the entity.
Using this code everything works fine, I added my custom function in the CategoryRepository without problem, but the problem comes when I want to update the database schema. I have the error when running php app/console doctrine:schema:update --dump-sql
[Doctrine\DBAL\Schema\SchemaException]
The table with name 'acme.cc_forum_category' already exists.
which I can understand since CCDNForum's Category entity and my Acme Category entity are using the same table (the C_Forum_Category table).
My question is: am I doing all this right ? Isn't there a simpler way to add a custom function in a vendor repository ?
Thanks!

Running "bin/vendors install" with local modifications on the "vendors" folder in Symfony2

In Symfony2, when I run the command bin/vendors install I get the following message:
?? src/Symfony/Component/Validator/Constraints/Alphanumeric.php
?? src/Symfony/Component/Validator/Constraints/AlphanumericValidator.php
?? src/Symfony/Component/Validator/Constraints/GreaterThan.php
?? src/Symfony/Component/Validator/Constraints/GreaterThanValidator.php
"symfony" has local modifications. Please revert or commit/push them before running this command again.
The files listed, are custom constraint validators created by me following the cookbook entry here.
Is there a way to update the deps files ignoring the changes I made? My goal is to install a new bundle while keeping the constraint validator files created by me.
UPDATE: Peter solution was right, the only thing left is to "use" the correct namespace inside the entity like this:
(The code has words in Spanish and I will assume again that I'm in the DemoBundle just for consistency)
namespace Acme\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Acme\DemoBundle\Component\Validator\Constraints as CustomAssert;
/**
* #ORM\Entity
*/
class Employee
{
//...
/**
* #ORM\Column(type="string", length=20)
* #Assert\NotBlank()
* #CustomAssert\Alphanumeric()
*/
protected $alfanum;
//...
}
You should never change anything contained in the vendor directory. If you have new feature to add (and you always should have to), put these features in your application specific bundles (in the src directory).
Your namespaces/classes scheme should follow the framework convention. For instance your constraint validator should go in 'src/MyNamespace/MyBundle/Validator/Constraint' (and your namespace should be 'MyNamespace\MyBundle\Validator\Constraint').
Notice that the vendor directory should be ignored by your version manager.
No, don't do this. Custom validators (or custom anything) you write should be a part of your namespace, not Symfony's. And they certainly shouldn't be vendors directory at all (unless you write your own vendor). This is the whole point of namespacing and vendor management - to avoid collisions!
So, you need to move your custom validators to your application's source. Using the AcmeDemoBundle as an example...
Create directories for the following path
src/Acme/DemoBundle/Component/Validator/Constraints
And then move your custom validators into this folder. Then update the namespace for each validator class accordingly
namespace Acme\DemoBundle\Component\Validator\Constraints
Cheers
You can put your custom validator in your own bundle and reference it in following way,
# in validation.yml
# define namespace identifier
namespaces:
namespace_name: Path\To\Your\Validator\Namespace\
# then in your entity
FQCN\Of\Entity:
constraints:
- Path\To\Your\Validator\Namespace\Alphanumeric
# or
- "namespace_name:Alphanumeric": ~

Resources