Categories
Software Development Web Development

Tips and tricks to reverse engineer your existing database with Doctrine for Symfony

So in the Symfony documentation there is a page that describes how to reverse engineer an existing database using Doctrine.

borat not meme
Symfony doctrine NOT Joke with Borat

Rule #1 No DB Vendor custom types

The only problem is this technique will only work with databases that are  generically designed. Meaning you can’t use most of the DB vendor specific types etc.

This means if your database uses tinyint or enum for example you should undo that before trying to reverse engineer it with the link above. And god bless you if you have used tiny ints as foreign keys. You must delete all foreign keys first, then recreate them.

Seriously trying to figure out how to work around TinyInts and Enums is a real pain in the ass, I’d advise against it. This documentation page is written poorly it leaves lots of questions to be asked.

symfony documentation meme
Doctrine is all like WTF do you need docs for?

Like WTF does this line even mean?

In this case however Schema-Tool update will have a hard time not to request changes for this column on each call.

Anyone want to have a stab at translating what that means?

details meme
I need more details than that please. LOL

Use a backup

the office meme
Step 1 use a backup

Don’t just backup your database. Start by dumping your current database structure, no data. Next import that into a new Schema. You can do that with one of the doctrine migration commands see this article.

Once you have the database structure imported. Open a terminal and do a quick doctrine migration diff as talked about here. Once you have the diff look over the migration to see what doctrine is wanting to change in your database schema. For me, It is easier to make those changes in something like MySQL Workbench with the added bonus that it can create an Entity Relationship diagram as part of my documentation.

Working with a backup of the data-structure lets you see what needs to be changed in your real database first. Follow the techniques in this article about reverse engineering the database.

Do the doctrine orm mapping import after you do the first diff. The purpose of the first diff is just to see the changes. You will see stuff like problems with TinyInts, Enums etc. Any vendor specific column type will generally be more trouble than it is worth.

Delete Migrations

system32 meme
Delete time

In the process of doing the diff and creating the mapping and doing the diff again and again, you end up with lots of migrations. Delete all of the migrations except for the very last diff migration.

You do the final diff after making final changes to the entity, mapping annotations. This way Doctrine can view your entities and compare them to your actual Schema. When you run this migration it will sync your database to the Entities.

No TinyInts

Sorry database designers you are not allowed to have these in your database design as they are mostly MySQL specific the Doctrine code does not allow them.

angry cat not going to happen
Doctrine is all like… NOPE
The Answer

Convert your tinyint columns to smallint. Doctrine understands those. Sure you are using like, a little more space each row now, but you really need Doctrine. LOL You can create a custom tinyint type, but wiring it in and using it is more of a pain than it is worth unless you really need it.

NO ENUMS

no enums meme
Remove Enums from your database design first

And the docs are wrong on this one and need updating. MySQL no longer requires an entire table rebuild costing hours.However Enums are not very useful because NULL and an empty string can be acceptable values under normal MySql configuration. Also with enums users can choose multiple values, so Doctrine uses php array type. You can use Enums, but it is more of a pain. See the doctrine docs here. You have to create a custom type and wire it in.

The Answer

Just use varchar or string as doctrine calls it. Make a check in your code (entity methods) to restrict values that are able to be accepted or make a table that holds the values. I personally use a table when there will be 10 or more values or I don’t know for certain how many there will be. If you use a table use a foreign link id to it in your main tables.

Forget your foreign key names

There is no solution for this. I have no idea why but Doctrine will absolutely rename,or suggest to rename every foreign key.

why can't i have my foreign key names?
Why can’t I have my foreign key names?

I think it tries to make sure each is unique or maybe it needs it in a specific format. I usually like to put the table name in it to be a hint in error output. But it also seems to rename keys it has previously renamed too.

The Answer

Like the leg humping dog in National Lampoon… “it’s best to  let it finish”

I’ll post more as I find it.

Your Entities have no repositories

It is awesome that doctrine can reverse engineer a database and even create the repositories too. What I don’t understand is why it does not link the damn repository  to the Entity. When you use the Entity maker it does this. When you reverse engineer with Doctrine it only creates the Entity mappings.

Answer

Use this Doctrine/Symfony maker I created. It can loop through your Entities and create Repositories for them.

There is still one catch though. You will have much fun like I did, opening 100+ Entity files and adding the proper annotations for the matching Repository to it.

This part is so tedious and fun

For example my app has a PageUrls Entity and it uses… PageUrlsRepository so to fix PageUrls so that I can use custom Repository methods I must now add this in the annotations.

/**
 * PageUrls
 *
 * @ORM\Table(name="page_urls", indexes={@ORM\Index(name="userOwnerId", columns={"owner_user_id"})})
 * @ORM\Entity(repositoryClass=PageUrlsRepository::class)
 */

So I must do this 100+ times now. I hope you have less tables in your database schema

hide the pain meme
Repetitive stuff is fun

I could add more code to the RepositoryMaker to update the Entities with the proper Repository tag. But then it is doing more than one thing. Maybe I should make a maker that updates the Entities Repository definition line to match. I wonder how long that would take compared to opening 100+ files and trying to type it properly etc.? Looks like I need to create a new maker.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.