use generated entities as "base class" in sf2/doctrine2 - symfony

How can I tell Doctrine2 Entity Manager to use an inherited class by default, instead of the generated one?
In my new sf2 app, I generated all entities from the existing database to /src/Package/Bundle/DataBundle/Entity - of course I'd like to have generated forms as well, so I need for my foreign-key relations __toString() methods, which I don't want to put into those generated files because they get overwritten (yes they also get backuped in an extra file, so my changes aren't lost, but manually merging files is not what I want).
So I added new classes to /src/Package/Bundle/DataBundle/Model inheriting all from the entities, but with a __toString() method and surely some other tweaks in the future as well. But now, when I call $entity = $em->getRepository('PackageDataBundle:Customer')->find($id); - I get an instance of /src/Package/Bundle/DataBundle/Entity/Customer instead of /src/Package/Bundle/DataBundle/Model/Customer ..
I'd like to have the behaviour from sf1, where all custom work is done in the inherited classes and the generated ones are the "base" Classes, which can be updated any time on a schema update and aren't touched otherwise..
I hope there is some configuration for this..
Maybe as a bonus, I'd like to have my naming convention turned around: to have Model as the "abstract" generated one and Entity as the actual used one
Thanks.

I'd like to have the behaviour from sf1, where all custom work is done in the inherited classes and the generated ones are the "base" Classes, which can be updated any time on a schema update and aren't touched otherwise..
For purposes you described you should use Propel ORM - it was so in Symfony-1.4, and became even more flexible for Symfony-2.0 with Propel 1.6. It is well documented, easily installed and naturally used within Symfony-2.0

Perhaps I misunderstood your problem, but going from Propel to Doctrine i was also disappointed that there is no way to keep that "dirty" auto-generated code out of my logic.
I do not know how much it is now important to you, but I currently writing a simple bundle that implements such generation style.
$ app/console doctrine:generate:entities СompanySomeBundle --propel-style=true
Generating entities for bundle "СompanySomeBundle"
> backing up User.php to User.php~
> generating Сompany\SomeBundle\Entity\Base\User
> generating Сompany\SomeBundle\Entity\User
https://github.com/madesst/MadesstDoctrineGenerationBundle
PS: Sorry for my english =/

Related

Symfony2 getters, setters, add and remove

I'm getting really confused by entity properties and what they mean. I understand that get and set allow the application to interact with protected and private properties, but what about add and remove?
When running the command
php app/console doctrine:generate:entities bundle:entity
Sometimes it will generate getters and setters and other times it will generate add and remove properties (and usually a get method as well). I've noticed that it also sometimes depends on the relationship with other entities (i.e. OnetoMany), but not always :-S
Nowhere in the Symfony documentation that I can find is this addressed, and it's causing me to see the message "Neither the property "x" nor one of the methods exist and have public access" way too often. Can anybody provide a succinct explanation of this?
add and remove are used to deal with collections. If for example your Entity (Let's say A) contains a collection of B elements, then the command will provide an addB() and a removeB() public methods to help you add and remove elements from your collection. It'll also provide a getter which returns the whole collection.
The command generates methods based on the type of attributes you're working with (ArrayCollection, string, ...)
For xxxToMany associations, Doctrine will generate a "adder" and a "remover" instead of a plain setter. The idea is to easily add and/or remove a single object from the collection without needing to pass around the entire collection everytime to the setter.
Note though that these generated methods are an implementation detail you are free to revise. If you prefer a single setter method for example, feel free to implement that one yourself.
I personally don't rely on the accessor generation of Doctrine anymore. Doing it manually allows greater control of your entity's API, and is also quite easy in an IDE like Netbeans or PHPStorm.

Doctrine 2 base entities like those in doctrine 1?

I'm starting a new project with Symfony2/Doctrine2 and I generated my entities from the DB with the mapping:convert and mapping:import commands.
My entities are fine, but I only have the generated entities. Back in Doctrine1/Symfony1, you had your entities generated twice : once in the doctrine folder, an almost empty class just extending the second one in doctrine/base folder where all the doctrine internals were (getters/setters, fields...)
This way, you could add your own methods in the first file where they remained untouched even if you generated again the entities (only the doctrine/base files were modified by the generator).
Am I missing something ?
Well the generate command only generates getters and setters that are undefined and appends them to the (entity) file. This means that your custom getters/setters will never be overwritten. Does that answer your question?

Use FOSUserBundle in relation with yml-based Entities

I've started a Symfony2 project from scratch where I then installed FOSUserBundle.
Then, I have written (actually, generated with ORM Designer) some entities that need to have relations between them, and with the User entity.
I have Items belonging to Users, Collections belonging to Users that group Items, and so on.
Since I used FOSUserBundle I only have a basic User class (https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md , step 3a) defined using annotations, no config/doctrine folder and no User.yml file in it.
I then created the MyBundle/Resources/config/doctrine folder and added the yml files mentioned above.
When I try to generate the entities with the command-line tool everything works fine: it will create the Entities from my yml files.
However, at this point, trying to load up in browsers the url where the login previously worked (when I only had the FOSUserBundle installed) will throw this error:
MappingException: No mapping file found named
'/var/www/concert/src/X/MyBundle/Resources/config/doctrine/User.orm.yml'
for class 'X\MyBundle\Entity\User'.
Following actions, such as generating the CRUD logic, will not work as long as I have an *.orm.yml file in the config/doctrine folder. If I remove those, CRUD generation will work, but generation of actual mysql tables won't.
Juggling with these gets me to a point where I can also get the tables, but then the actual app doesn't work if I try to use any of the url's where the newly generated CRUD is involved because since the entities are based on yml (which I remove to get things "working") it won't have any mapping knowledge.
Is this inherently wrong? To have yml-based entities in relationship with an User entity based on the FOSUserBundle and still be able to get the nice command-line generation tools?
The problem you describe stems from mixing configuration formats (yaml and I assume annotations). You can easily fix this by ditching the annotations in your models and replacing them with yaml-files like you would do in your own models.
Unfortunately the FOSUserBundle-docs only show you how to use annotations, so here is a quick transformation into yaml format when your X\MyBundle\Entity\User extends FOSUSerBundle's UserEntity:
X\MyBundle\Entity\User:
type: entity
table: fos_user
id:
id:
type: integer
strategy: { generator: "AUTO" }
The remaining stuff is taken care of by FOSUserBundle, as the BaseModel is a mapped-superclass and already describes the stuff in the User.orm.xml, but you could just as well replace the existing values or add additional values just like you would do with your own models.
If you don't use annotations throughout your app, you might also want to disable them in your app/config/config.yml to prevent side effects.

Generic comment system in Symfony2

I have in my Symfony 2.1 RC app a simple Comment model (using Doctrine 2). Every comment has a user and a message.
Currently, the CommentBundle manages comments on articles. I'd like it to be more generic to be able to comment any kind of entity without copying code across different bundles dedicated to comments...
For this to work, I also need a way to reference any entity from the comment one. I think having two fields entity_type and entity_id can be a nice solution. However, I can't get the object from these without mapping entity_type to classes manually and using the find method.
So how do I reference an entity from a comment ? And how can I create generic behavior working on several entities ?
You can create a abstract base class entity called Commentable and create entities that inherit Commentable such as Document or Post.
Since Document and Post are derived from Commentable, you can create a one to many relationship between the entities Commentable and Comment respectively.
Make sure to include in your base class ORM annotations for inheritance:
#InheritanceType
#DiscriminatorColumn
#DiscriminatorMap
Examples can be found on Doctrine Project Inheritance Documentation

How to override record table naming to access existing data in Orchard CMS

I need to access data from pre-existing tables. I've started working my way through creating a module to display the data etc. However, Orchard is prefixing the table commands with the 'Table_Prefix' and 'Module Name'.
Is there any way I can specify what table to bind the model, so that I can use the existing IRepository
I'm trying to steer clear of modifying the core code, or implement my own IRepository ( which I've got a feeling is what I'm going to have to do.)
Thanks in advance.
You can create custom table naming convention (so that it would fit your current naming) by altering the core code, in three ways:
Record name mapping is created in BuildRecord method of
CompositionStrategy class
(Orchard.Framework/Environment/ShellBuilders/CompositionStrategy), so you can simply modify the code here.
By altering the Apply method of Orchard.Data.Conventions.RecordTableNameConvention class. This is where the record table name mappings (built in point 1.) get pushed to NHibernate.
Create your own implementation of FluentNHibernate.Conventions.IClassConvention (similar to RecordTableNameConvention mentioned above and replace the default one used by AutoMap in Orchard.Data.Providers.AbstractDataServicesProvider's CreatePersistenceModel(...) method with it.
You could also create your own IDataServicesProvider implementation, but that would surely be an overkill if you only need to change the table naming convention.
I was modifying CompositionStrategy and discovered that you have to modify the following
1. SetupService.cs (Modules\Orchard.Setup\Services):
Tables hardcoded in the Setup method are
"Orchard_Framework_DataMigrationRecord" and
"Settings_ShellDescriptorRecord"
2. InfosetController.cs (Modules\Upgrade\Controllers):
Multiple tables were hardcoded in this class which need to be updated.
3. DataMigrationManager.cs (Data\Migration):
Replace the SchemaBuilder parameters to the contructor.

Resources