doctrine / DoctrineBundle

Symfony Bundle for Doctrine ORM and DBAL
https://www.doctrine-project.org/projects/doctrine-bundle.html
MIT License
4.69k stars 448 forks source link

Symfony Flex - Generating entity #729

Closed kironet closed 6 years ago

kironet commented 6 years ago

Hey,

Please update this bundle. I'm trying to generate new entity with this bundle, but I'm getting errors that App or AppBundle does not exist...

commands:

php bin/console doctrine:generate:entity
php bin/console doctrine:generate:entities App

My temporary fix for generating new Entities is:

Create new App class that extends Bundle in src/App.php. Register it in the bundles.php

Unfortunately not working for php bin/console doctrine:generate:entities App not generating getters and setters.

fralazar commented 6 years ago

I have the same issue when executing doctrine:mapping:import, since symfony4 is bundle-less there is no destination bundle to specify.

stof commented 6 years ago

Well, none of the Doctrine maintainers is in favor of using these generation commands (they tend to create more harm than good in most cases). So I suspect this is the reason why they were not spotted as broken in a Flex context yet (none of the Symfony or Doctrine maintainers trying Flex early were using them)

kironet commented 6 years ago

Well, thats nice(I don't see what harm can generating entity cause), at this point I don't see why I should stay with Symfony, I can just switch to Laravel, if since flex it looks like I will have to do everything manually...

Ocramius commented 6 years ago

The harm is getting a totally anemic domain model that reflects the RDBMS.

At that point, just use the RDBMS instead, as the ORM is probably a bad fit.

The fact that you use the generator means that you aren't designing any of your entities, which means that they will also be useless at runtime, if not a hindrance.

On 4 Nov 2017 11:45, "kironet" notifications@github.com wrote:

Thats nice(I don't see what harm can generating entity cause), at this point I don't see why I should stay with Symfony, I can just switch to Laravel, if since flex I have to do everything manually...

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/doctrine/DoctrineBundle/issues/729#issuecomment-341887444, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJakL9efzAHS0rwo-nMOI2OvPoweBycks5szEBTgaJpZM4QQmr3 .

weaverryan commented 6 years ago

We will support the generation commands, but in a different bundle... so stay tuned :). Remember, Symfony 4 isn't even out yet - we're still (and will continue) polish things. But, thanks for the issue!

In DoctrineBundle, I think we should deprecate any commands that you don't want to support. However, I know the doctrine:mapping:import (though imperfect by design because it's doing an impossible task) is used by a lot of developers.

gaelb80 commented 6 years ago

The problem exists in 3.4 too when using flex. Trying to generate getters and setters with command failed A way to fix it in #723

andrewtch commented 6 years ago

@stof, so you basically offer to use public properties for doctrine?

psfpro commented 6 years ago

Hi all! DisconnectedMetadataFactory not suitable for Symfony 4 also

For example, doesn't work for PSR-4:

    /**
     * Get a base path for a class
     *
     * @param string $name      class name
     * @param string $namespace class namespace
     * @param string $path      class path
     *
     * @return string
     * @throws \RuntimeException When base path not found
     */
    private function getBasePathForClass($name, $namespace, $path)
    {
        $namespace = str_replace('\\', '/', $namespace);
        $search = str_replace('\\', '/', $path);
        $destination = str_replace('/'.$namespace, '', $search, $c);

        if ($c != 1) {
            throw new \RuntimeException(sprintf('Can\'t find base path for "%s" (path: "%s", destination: "%s").', $name, $path, $destination));
        }

        return $destination;
    }
Ocramius commented 6 years ago

The generators assume a PSR-0 structure by design: that is an intentional decision.

On 25 Nov 2017 12:03, "Sergey Pantushin" notifications@github.com wrote:

Hi all! DisconnectedMetadataFactory not suitable for Symfony 4 also

For example, doesn't work for PSR-4:

/**     * Get a base path for a class     *     * @param string $name      class name     * @param string $namespace class namespace     * @param string $path      class path     *     * @return string     * @throws \RuntimeException When base path not found     */    private function getBasePathForClass($name, $namespace, $path)    {        $namespace = str_replace('\\', '/', $namespace);        $search = str_replace('\\', '/', $path);        $destination = str_replace('/'.$namespace, '', $search, $c);        if ($c != 1) {            throw new \RuntimeException(sprintf('Can\'t find base path for "%s" (path: "%s", destination: "%s").', $name, $path, $destination));        }        return $destination;    }

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/doctrine/DoctrineBundle/issues/729#issuecomment-346933693, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJakEpVG_4REUWHOIP3FC317bBPd6uIks5s5_PxgaJpZM4QQmr3 .

psfpro commented 6 years ago

Yes. I see. We can find out path from

/** @var Composer\Autoload\ClassLoader $loader */
$loader = require __DIR__.'/../vendor/autoload.php';
$loader->getPrefixesPsr4();

This is the place for a little magic))

kporras07 commented 6 years ago

Hi @weaverryan any news on this? I'm still getting the same error reported in #723 with Symfony 4

molven04 commented 6 years ago

Hi all! I have the same issue.. My way to (hope) temporary fix it:

  1. create a symfony 3.3 installation
  2. doctrine:mapping:import from existing database
  3. copy and paste Entity files in my new symfony 4 project (after change "AppBundle" with "App" in each one)
  4. doctrine:schema:update --force in new symfony 4 project
theedov commented 6 years ago

@molven04, @kporras07 You can use Symfony Maker: https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html

seydu commented 6 years ago

@Ocramius I would agree with you on doctrine:mapping:import. Four to 5 years ago I used it when migrating existing applications to Symfony 2. I stopped using it because it required so much work to fix the generated mappings that writing the mappings from scratch was more efficient.

But doctrine:generate:entities is very useful and does not lead to anemic data model. I use it to generate entity classes from YAML or XML mapping and it does not cause any harm. It really shines in this use case as it handles all the boring, repetitive and error prone process of converting XML or YAML mapping into entity classes.

Symfony is used by a wide range of shops, we cannot assume that the author of the mapping is the developer and suggest they just write the mapping in annotations to begin with (you did not say that but that argument is frequently raised).

Ocramius commented 6 years ago

In 5 years of answering ORM questions, I can assume that.

Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/

On Sun, Dec 3, 2017 at 7:38 AM, Saidou GUEYE notifications@github.com wrote:

@Ocramius https://github.com/ocramius I would agree with you on doctrine:mapping:import. Four to 5 years ago I used it when migrating existing applications to Symfony 2. I stopped using it because it required so much work to fix the generated mappings that writing the mappings from scratch was more efficient.

But `doctrine:generate:entities' is very useful and does not lead to anemic data model. I use it to generate entity classes from YAML or XML mapping and it does not cause any harm. It really shines in this use case as it handles all the boring, repetitive and error prone process of converting XML or YAML mapping into entity classes.

Symfony is used by a wide range of shops, we cannot assume that the author of the mapping is the developer and suggest they just write the mapping in annotations to begin with (you did not say that but that argument is frequently raised).

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/doctrine/DoctrineBundle/issues/729#issuecomment-348744137, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJakOlllLj3bjjwKJmwDPbZbUo-Jy6Iks5s8kH2gaJpZM4QQmr3 .

gabiudrescu commented 6 years ago

I know that using pre-Symfony 4 doctrine:generate:entity + doctrine:generate:entities + doctrine:schema:update made prototyping very fast.

as a developer, you answered a few basic questions that were prompted on the screen and everything was created on your behalf. no more of similar code written by hand over and over again...

and coupled with an EasyAdmin with low customization, it provided out of the box functionality by using basically only config files.

you could have an up and running PoC application in 30 minutes, having the rest of the time for doing the real coding for the more relevant business layer.

andrewtch commented 6 years ago

My 5 cents:

gabiudrescu commented 6 years ago

@andrewtch I haven't been able to make PHPStorm generate methods for collections properties (addElement, removeElement + constructor initialization). hence, relied on the generator to do this instead of me.

martinezvictor84 commented 6 years ago

to generate entities of tables in symfony 4, try it:

php bin/console doctrine:mapping:convert --from-database annotation ./src/Entity

kironet commented 6 years ago

Yeah, I was using command doctrine:generate:entities only because of relationships. It was easy and fast.

martinezvictor84 commented 6 years ago

you can use a text editor plugin to generate the setters and getters for exmaple https://github.com/francodacosta/atom-php-getters-setters

molven04 commented 6 years ago

Thanx @martinezvictor84

https://github.com/francodacosta/atom-php-getters-setters https://atom.io/packages/php-getters-setters

kironet commented 6 years ago

@martinezvictor84 For simple getters and setters you can just use phpstorm CMD + N on MacOS CTRL + N on Windows(I guess).

GrandNin-portequoi commented 6 years ago

@martinezvictor84 With Phpstorm, when you are in an inversed entity, Generate Getters & Setters doesn't work properly, cause it does'nt generate the 'add'/'remove' methods

zorn-v commented 6 years ago

https://github.com/symfony/maker-bundle/pull/95

Majkl578 commented 6 years ago

Just a heads-up here: support for codegen tools, including EntityGenerator, EntityRepositoryGenerator, orm:generate:entities, orm:generate-repositories and doctrine:convert-mapping, has been dropped and they will not be part of Doctrine 3.0 (ref doctrine/doctrine2#6870). It'd be awesome if Symfony started phasing them out, the sooner the better, and teach its users good manners - i.e. how to write entities properly, not by generating anemic 1:1 table copy.

kironet commented 6 years ago

Woohoo let's spend weeks just by writing entities from scratch. 👍

Ocramius commented 6 years ago

Not much of a joke: if you generate anemic entities, enjoy maintaining the stateful spaghetti mess for years.

alcaeus commented 6 years ago

Last but not least, if someone really wants this functionality, feel free to extract these commands to a separate bundle or create a pull-request to add them to the Symfony MakerBundle if you want to maintain them. Doctrine is not breaking code generation - we're just no longer maintaining/providing the tools to do so.

kironet commented 6 years ago

If you don't want people to use anemic entities, maybe it's good idea to update docs?

zorn-v commented 6 years ago

Lets collect experience. I use gen:entities for generating getters/setters and "new ArrayCollection"

Majkl578 commented 6 years ago

Good documentation about design/modelling is indeed needed apart from just removing generator-related chapters. Keep in mind that entity generator has not yet been officially deprecated or removed so there is still time to improve documentation. I've opened an issue on symfony-docs repo.

Woohoo let's spend weeks just by writing entities from scratch.

Actually, why not? If you put enough time in designing your domain model, you won't regret. Entity with bunch of getters and setters is not a good example, but entity with some getters, (almost no/zero) setters and business methods is. For example, $article->release($reviewer, $date) will definitely be better than $article->setReleaseDate($date) + $article->setReviewer($reviewer) + $article->setState($article::RELEASED).

Lets collect experience. I use gen:entities for generating getters/setters and "new ArrayCollection"

Then please stop. Please read some articles about anemic domain model. https://www.martinfowler.com/bliki/AnemicDomainModel.html


As already stated in the PR doctrine/doctrine2#6870, if anyone wants to take over, that PR is a good reference of all the needed code if you read it inversely.

sarcher commented 6 years ago

I ran into this issue today in Symfony 4 while trying to generate the usual getters/setters on a class. For anybody looking to actually make the current software work, you do need to make changes to both the DoctrineBundle and the ORM itself as outlined in #723 (and below).

Regardless of the long term solution, this should be fixed in what is out there today so as to behave as documented. When the entity generator is deprecated in the new Doctrine and eventually removed in 3.0, new documentation should exist somewhere in the Symfony ecosystem describing the proper best practice (the Martin Fowler article is nice at a conceptual level, but is rather vague from a "what to do next when these commands stop existing" perspective). In my case, I wouldn't call my models anemic, but generating these on a large model is a good starting point and easy to do, and my IDE doesn't generate what I need without spending a good bit of time playing with the recipe.

The root cause of the problem at hand is that the new Symfony structure removes the "App" directory (or whatever you call your project), so for example if your company is "Example" then your entities are probably namespaced to "Example\Entity" but your directory structure is likely just "src/Entity". The same is true if you use the default "App\Entity" and so on.

I solved this by making the following change to Mapping\DisconnectedMetadataFactory.php in DoctrineBundle on line 124 (1.8.1):

        if (class_exists($all[0]->name)) {
            $r = new \ReflectionClass($all[0]->name);
            $ns = substr($r->getNamespaceName(), strpos($r->getNamespaceName(), '\\') + 1);
            $path = $this->getBasePathForClass($r->getName(), $ns, dirname($r->getFilename()));
        } elseif ($path) {

And in Doctrine\ORM\Tools\EntityGenerator.php in the ORM on line 363 (2.5.13):

        $namespace = substr($metadata->name, strpos($metadata->name, '\\') + 1);
        $path = $outputDirectory . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . $this->extension;

These changes just strip the leading namespace element out of the path since it is no longer present in the new structure.

Is it worth putting out PRs for these to get them merged, or is another solution favored?

For anybody looking to follow the new entity generation for Symfony Flex, it seems to be here (also referenced above): https://github.com/symfony/maker-bundle/issues/83

zorn-v commented 6 years ago

@sarcher https://github.com/symfony/maker-bundle/pull/95

pawellen commented 6 years ago

I completely disagree with @Ocramius. I exactly know how my domain-model must be designed! I used to copy necessary methods from generated entities, remove some methods and redesign some of them. Writing all this from scratch (because beginners users abuse it) is insane idea.

pawellen commented 6 years ago

@Majkl578 You said: "It'd be awesome if Symfony started phasing them out, the sooner the better, and teach its users good manners - i.e. how to write entities properly, not by generating anemic 1:1 table copy." So lets consider simple example to prove you are wrong:

Now I am struggling with import of several GB of data to more than 100 tables. All data must be imported with little reorganization of relation names etc... I created my new database scheme with MysqlWorkbench - fastest way. Please tell me who is going to pay for time I will be wasting on writing everything from scratch? It will take me about one 10 days to do all the job. I think that you forget that writing applications isn't always a hobby when you have infinite time and you can spent to concerning good manners only.

After my import will be done I am going use DDD to write my target application where persistent layer will be complete decoupled from domain. But for now my client wont allow me to just skip import of some data because lack of time or because you don't like it. You can't put all people to one bag and say that they need to be more educated.

If you don't like generation entities inside doctrine3 project just move it and maintain it in separate branch or project but don't kill feature that my be really helpful for many people. If you're unable understand it I hope there will people that will do and will have 10000 of stars on github with new generator project!

Ocramius commented 6 years ago

Now I am struggling with import of several GB of data to more than 100 tables. All data must be imported with little reorganization of relation names etc... I created my new database scheme with MysqlWorkbench - fastest way.

You are importing an entire schema without changing anything, yet you had to do design the new schema manually in MySQL Workbench? I cannot see where this could possibly go wrong!

Jokes apart, you will likely incur in:

Importing the entire schema into a "new" application without inspecting manually each scenario and each business rule that couldn't be coded into a DB-level constraint is gonna be more trouble.

You will hit issues, you will corrupt the data and the migration will just lead to misunderstanding by consumers of the generated model.

I've gone through the same scenario you described above multiple times, and it is generally a waste of money to abstract away existing data models, since you do not know everything that the existing data model is supposed to do.

After my import will be done I am going use DDD to write my target application where persistent layer will be complete decoupled from domain. But for now my client wont allow me to just skip import of some data because lack of time or because you don't like it. You can't put all people to one bag and say that they need to be more educated.

Then you likely don't need Doctrine ORM: you probably want a Table-Data-Gateway or an Active-Record implementation, or even something more lightweight than that if applicable. You'd just end up writing something quite complex that:

This train has left the station over 2 years ago, and it is just going to happen now.

We're not in a popularity contest here: if people like shooting themselves in the foot, so be it, but we'll provide as little assistance (before AND after) as possible to focus on more relevant problems.

To recap:

kironet commented 6 years ago

http://docs.doctrine-project.org/en/latest/tutorials/getting-started.html

When creating entity classes, all of the fields should be protected or private (not public), with getter and setter methods for each one (except $id).

pawellen commented 6 years ago

1) "You are importing an entire schema without changing anything, yet you had to do design the new schema manually in MySQL Workbench? I cannot see where this could possibly go wrong!"

I disagree. I am importing data from different source types (not just doing copy of existing schema):

2) "Then you likely don't need Doctrine ORM: you probably want a Table-Data-Gateway or an Active-Record implementation, or even something more lightweight than that if applicable. You'd just end up writing something quite complex that (...)"

3) "We're not in a popularity contest here: if people like shooting themselves in the foot, so be it, but we'll provide as little assistance (before AND after) as possible to focus on more relevant problems."

4) "we did it exactly to prevent people from doing exactly what you are doing: designing anemic domains with a "database-first" approach. That's a bad fit for this ORM and it will hurt you down the line."

Ok, You may say that Doctrine is not tool designed as a some kind of tool/helper to import data from junk sources like those i have ..and I agree with that, I also agree and understand why removing generators will prevent people of saying "ORM sucks" because they put whole database to it. But you must admit that there are scenarios when generator can be useful. Maybe there is some approach to kill to birds with one stone and save generators for cases like mine and also save people from abusing it. It is up to you.

Thanks for answer Best Regards.

Ocramius commented 6 years ago

It is up to you.

Precisely the opposite, which is why they are being removed here.

pawellen commented 6 years ago

Just want to say this that for me this is "Volstead Act" approach like in USA in 1919. Instead of educating people you just want to put all people to the same bag and ban all generators, its exactly like prohibition did with alkohol in United States. Maybe better way is to change documentation, try to educate people (see what happen and after that decide should we remove generators or not). Like @kironet mention Doctrine documentation is teaching developers to create anemic domains in the first place not generators itself.

Ocramius commented 6 years ago

No prohibition: make your own generator.

Prohibition is when I lock the thread, which is really close.

As for the docs: https://github.com/doctrine/doctrine2/pull/6902

ciaranmcnulty commented 6 years ago

@pawellen

who is going to pay for time I will be wasting on writing everything from scratch?

Perhaps consider who's paying the maintainers of this project to do your job for you?

Pierstoval commented 6 years ago

Guys, I've experienced generate:entity and mapping:import a dozen times since 2013, as I also wanted to migrate an old data source to Symfony & Doctrine.

First I was like:

Neat! I can use my old db structure again!

Then I was:

Damn, it's been 3 weeks and I'm still handling errors in my entities

And after the first year:

I think my structure's not OK

And today, it's more than four years after the birth of this "V2" project. Still not on production (it's a personal project so I don't mind, in the beginning it was just for fun), and by the way it's the same for all other non-personal projects on which I used these features:

Hell, how could the v1 possibly work with such structure? My objects are now thousands, and I cannot manage to handle importing the old data in the new structure. I shouldn't have used import at all in the first place.

The same goes for generate:entity but @Ocramius said enough about anemic models. If you like anemic models, it's up to you, but just don't ask Doctrine maintainers to support an idea that themselves would've never used because it's bad design in the first glance. It's like saying Hey, Symfony devs, I need the sfContext class like in Symfony1 because I design my whole project using this class, it's so cool and shiny and furry, but it's hell of a bad practice so it's been removed.

Even though my entities are still a mix between anemic and rich, I tend to think every model should be rich, so no setters, but getters are fine.

That's why I created doctrine/doctrine2#6902 and will take time in the next weeks to update it, unless someone more clever than me wants to participate.

And that's also why I agree on the fact that generate:entity and mapping:import were removed and are not coming back.

That's my 2 cents

Baachi commented 6 years ago

So here are my 2 cents to this discussion. Is it really doctrine or symfony task to teach people DDD, i think so. Doctrine is only one tool to practice DDD. You can also use eloquent, propelorm or just dbal to do it. Should each of this project do document DDD?

And for all people who want to have this feature: I see many comments here, but no one extract this feature into his own library bundle. You can also create a PR and say "Hey i want to maintain this feature". Then this is how open source should work.

The guys form doctrine do a great job and instead of blame this people they do bad work, think about this: How many time (and money) do you save with doctrine and you pay nothing for it.

See this as a chance to give them something back and be constructive.

javiereguiluz commented 6 years ago

There's no need to discuss about this :) Doctrine maintainers have removed all the generator tools because they think it's the best for their project ... and we're working on adding new and modern generator tools to Symfony's Maker bundle because we think it's the best for Symfony.

So we both get what we want, nobody is "doing it wrong", everybody should be happy ... and there's no need to discuss about this. Cheers!

pawellen commented 6 years ago

"Perhaps consider who's paying the maintainers of this project to do your job for you?" @ciaranmcnulty good point!

@javiereguiluz You right!

@Ocramius After reading whole discussion I admit that generators inside doctrine project are bad idea and their are causing to many problems and most of my arguments I wrote earlier sucks! :)

liverbool commented 6 years ago

I never used this tool after pass 2-3 months in Doctrine, try to go RDBMS and some IDE like Phpstorm so now about 5+ years life is easy.

tvogt commented 6 years ago

Half of you are insane, right? Don't tell me how to write my code. If I want all my entities to have getters and setters for all their variables, and access to the very convenient relation add, remove, etc. methods then I want it and it's not your place to tell me what I want.

Symfony used to be perfect for banging out a quick prototype exactly because of this. Especially if you use XML or Yaml for entity mapping, the getter/setter code generation is a gift from heaven.

I just started a new project on Flex, after using Symfony 2 and 3 for older ones, and the missing entity generator is the reason I'm shelving it for the weekend until I figure out how to proceed without wasting hours on writing extremely repetitive code.

Ocramius commented 6 years ago

Just make properties public and you have the same behaviour: no need for generators or "extremely repetitive code" (which is quite the code smell again, and leads to extremely repetitive maintenance work).

We're not telling you how to write your code, we just stop writing code for you.