Categories
Web Development

How to add placeholder text to a Symfony 5+ form row

If you are using the Symfony forms system, which I assume you are if you are here, then this post is for you. Otherwise you figure it out. LOL

you need to figure it out meme
This is only for symfony forms otherwise…

There is more than one way to do this. However, I am going to show the way I prefer and that is right in the form type definition class.

When you build a form by way of creating a form type class, then it is easy to set all of the options and values you need in one location..

By looking at the documentation one would think the following would work for the HTML placeholder attribute


->add('userAlias', TextType::class, [
            'mapped' => false,
            'constraints' => new Length([
                'min' => 2,
                // max length allowed by Symfony for security reasons
                'max' => $userAliasObj->getColumnLength(UserAliasTable::ALIAS)
            ]),
            'row_attr' => ['placeholder' => $this->aliasPlaceholder]
        ])

BUT …. SURPRISE IT DOESN’T WORK. Why? Who knows? Docs need updating, something changed? We might never know.

It even says the following in the docs for row_attr

An associative array of the HTML attributes added to the element which is used to render the form type row:

The pain of using Symfony is in the docs

I am guessing all of the other HTML attributes will work with row_attr? Maybe they do not consider the placeholder attribute as an attribute? The docs are as clear as mud on this one. And I am not the only one who has discovered this.

This is at least a 3 year old issue. I appreciate all the hard work, but in so many places the docs are out of sync with the base code. This makes it so hard to use the code, it takes the fun out of using it and wastes peoples time.

However, I did discover that plain attr works with the placeholder attribute like so.


->add('userAlias', TextType::class, [
            'mapped' => false,
            'constraints' => new Length([
                'min' => 2,
                // max length allowed by Symfony for security reasons
                'max' => $userAliasObj->getColumnLength(UserAliasTable::ALIAS)
            ]),
            'attr' => ['placeholder' => $this->aliasPlaceholder]
        ])

The docs say the following about attr

If you want to add extra attributes to an HTML field representation you can use the attr option. It’s an associative array with HTML attributes as keys. This can be useful when you need to set a custom class for some widget:

Dear Symfony, placeholder is not an extra attribute it is a valid html attribute.

symfony meme
Say what?

Keeping things together

better together meme
Keeping your form pieces together is better later.

Keeping all of the form related stuff in one location makes it easier to find and make changes. Some people may argue that you should do this in the template so that non programmers can make changes. I argue if you can learn HTML you can learn to read the docs and articles like this and figure it out. LOL

The interesting thing is the field definitions in your FormType class do not have to be in the order you want them displayed in the browser. This is actually done in the template. This makes it easy to move the small pieces around by copy and paste and it means you get much fewer html bugs. That is another reason I argue if you hire someone who knows only html they should learn this simple system.

My FormType definition for the registration form, for my app contains quite a few fields. However, I can quickly redesign it with confidence by moving a line or two of code instead of hundreds of lines.


{{ form_row(registrationForm.userAlias) }}
        {{ form_start(registrationForm) }}
        {{ form_errors(registrationForm) }}
        {{ form_row(registrationForm.email) }}
        {{ form_row(registrationForm.emailMatch) }}
        {{ form_row(registrationForm.plainPassword) }}
        {{ form_row(registrationForm.passwordMatch) }}
        {{ form_row(registrationForm.agreeTerms) }}

See how making changes to the forms layout is super easy this way.

symfony forms meme
Symfony forms made easy.
Categories
Web Development

How to access Doctrine in Symfony 5+ services

Scroll down to the answer part if you just want the answer.

From what I can tell the Symfony documentation only shows how to access doctrine in your controllers. But what if you need to access it in a service?

Services are any class within a folder inside the src folder, Repository folder for example. In Symfony 5+ every folder within src directory is considered a service folder, meaning the classes inside are services.

My current app has a very complex registration system. Not all of the fields are saved, and some go to different tables after processes are applied. For example the user alias is turned into a URL safe string to be used as their profile page.

So I started with all of the code I needed directly in the controller method, but that was a few hundred lines. Usually when I have a complex form that needs specific processing I create a processing class and save it in a folder called FormProcessors.

Inside the form processors I have public and private methods. I call the public methods from the controller methods to process the forms. You could split the code up within your controller class using private methods. I do that sometimes as I am building the form, I then move it to the form processors.

One added benefit of using the form processors is the logic can be copied over to new classes used with something like RabbitMQ when I move to an Event based system or microservices etc.

So I needed to figure out how to get to the dang doctrine orm inside my form processors.

The answer

The answer is to type hint your Service class constructors with EntityManagerInterface like this

class RegistrationProcessor
{
    private Form $form;
    private array $errors;
    private array $filtered;
    private EntityManagerInterface $entityManager;
    private MysqlConnection $mysqlConnection;
    private UserPasswordEncoderInterface $passwordEncoder;

    public function __construct( EntityManagerInterface $entityManager,
                                 MysqlConnection $mysqlConnection,
                                 UserPasswordEncoderInterface $passwordEncoder,
                                 Form $form)
    {
        $this->entityManager = $entityManager;
        $this->form = $form;
        $this->filtered = array();
        $this->errors = array();
        $this->mysqlConnection = $mysqlConnection;
        $this->passwordEncoder = $passwordEncoder;
    }

Then to use it, you do this where you need it.

public function saveUserAlias( User $user, string $alias, DateTimeInterface $dateTimeObject){
       $userAlias = new UserAlias();
       $userAlias->setUser($user);
       $userAlias->setAlias($alias);
       $userAlias->setDatetimeAdded($dateTimeObject);
       $this->entityManager->persist($userAlias);
       $this->entityManager->flush();
   }

Notice it is as simple as two calls to entityManager. You don’t have to even get the Repository. However you may get an error if you do not have your Repositories defined in your entities.

 

Categories
Software Development

Ubuntu desktop getting slower each release

I’ve used ubuntu desktop since 2008. You wouldn’t believe how fast it used to be. It used to be fast even on small resource limited devices.

But then version 20 came out and WOW IS THIS POS SLOW. Slower than molasses in the winter in Siberia. Startup time is about 5 minutes. You literally turn this POS on and walk away and do something for 5 minutes while it screws around in blackscreen mode.

 

Then you come back and open each app you want to use and wait another couple minutes.

Every app is slow to start and runs slow.

I just want to know WTF have you people done? If you are trying to make a slow POS. CONGRATULATIONS YOU WIN.

GOOD GOD UBUNTU DESKTOP IS SLOW

I am sure there are like 10 cryptic commands I could pop into the terminal and fix it. But that requires googling and wasting time. That is a repeating issue with Linux Desktop WASTED TIME. SO MUCH DOES NOT WORK. Linux desktop is for people that program or people that love to waste their time learning about useless BS. I use it because I program. But if it gets any slower I’ll be forced back to Windows 10

Typing cryptic commands into the Terminal makes stupid people feel smart
Categories
medicine Software Development

A proposed system to help Physicians quickly detect Illness via x-ray

I’ll be referring to this research document in this paper. Comparison of Chest Radiograph Interpretations by Artificial Intelligence Algorithm vs Radiology Residents + Supplemental content click the link to view it or
https://www.researchgate.net/publication/344604144_Comparison_of_Chest_Radiograph_Interpretations_by_Artificial_Intelligence_Algorithm_vs_Radiology_Residents_Supplemental_content

In this research paper they describe a system they created to test whether the concept of detecting illnesses of the chest with x-ray and Artificial intelligence was a viable solution. Their findings seem to determine that it is in fact viable and useful. Their research showed the AI was slightly less accurate than radiologists. I believe better training techniques would improve this situation.

The main issue the researchers seemed to have is getting enough good data to train the AI as well as possible. This can be improved by having the largest pool of data you can to start with to help train your AI program. Their experiment only had 2 sources. To improve the accuracy of the AI, I would suggest continually feeding new data into the system by having Radiologists interact with it via special user interfaces.

One way this could be done is by having the system send the x-ray from the machine into your software. Then have your software run it’s predictive analysis Algorithms and save the result. Then the radiologist can review result and the x-rays on their touch screen monitor. Your program can give them the tools they need in the user interface to confirm or change the systems analysis and record this data. Each time a doctor does this your AI software becomes better at predicting illness.

Another improvement I can suggest in this user interface for the radiologists, give them a way to circle over the x-ray, the location of the illness and label it. This over time would allow your Software to build a better understanding of the exact issues you want it to find and diagnose. This could also help your software run more efficiently. For example if one specific part of a lung gets cancer more often then other parts, you can have your AI start by scanning those sections first, then others after.

In the same line of thinking another improvement I would suggest is having the software highlight or circle locations in the x-ray where it thinks it has discovered something. This will further help the radiologists and other doctors by drawing their eyes to the immediate issue. Circling, highlighting etc. is all very easy to do without harming the original image.

I believe better ongoing collection of Data via user interfaces will add more value to your product by giving the users of your product the confidence that your system is designed to continually improve itself. Talk about smart software. Some of the ideas I list above would sound great in marketing materials.

 

Don’t run the AI on your machines. Create a “new age” system. Don’t spend millions a year on hosting servers for people to run your AI software on. Amazon AWS now offers GPU’s specifically for running AI algorithms.

This means you create a system where your software is hosted on a server like a website. The operator/radiologist logs into your system. Their x-ray machine can connect to your system or they have a way to feed the x-ray in. Through the user interface they choose to run your program. Your program fires up an AWS compute instance of their choice and runs the AI software. Their hospital pays for this instance not your company. These instances can run from 5 minutes to 5 years. If it only runs each time an x-ray needs analysis it may be like 10 minutes, which is a few pennies. After it runs it feeds the data back into your Server.

In the above server design you are storing your AI software and a database of past x-ray results which can be used to further train and calibrate your AI to make it more effective. All of the actual computing and running of your software is done on AWS servers. Your companies programmers can write scripts with something like Terraform and Packer, which takes the request from the User interface and fires up an AWS compute instance.

Each of your customers(hospitals) is responsible for paying their AWS bills. The last thing you want is to have them running your AI on your Servers. Not only will that cost you much more due to owning the servers. It will also cost you more to maintain those servers and pay more employees. The last thing you want is to get a reputation for having a slow piece of software. If you get too many people trying to run your AI at once your system crashes or you get a huge $$$ Bill.

Creating a user interface to allow the doctors to choose what AWS instance to run your software on gives them more feeling of control. Do they want to spend $.10 or $1.00? Or let the hospital dictate? All that matters then is that your software runs properly.

After the radiologist runs your AI software on an AWS instance the data is then saved back to your sever and the radiologist can be sent a notification right to their phone. This flexibility in interfaces means they could use your app right from their phone if they are really busy. Or they could sit down at a desk or laptop. Or they could use a touch screen smart TV with internet access. Designed like this your system is beautiful and you can gather precious data much more easily all while giving doctors conveniences they will crave.

Imagine for a second this scenario. A person comes into the emergency room complaining of chest pain and trouble breathing. The emergency room nurse sets them up for an x-ray. That machine feeds into your system. Your system alerts a radiologist of the results of the AI software processing. The radiologist short on time whips out their tablet or phone, taps a few times, circles something and hits submit. Your system gets instant confirmation of whether it was correct or not and can improve.

Another added benefit of a system like this is more than one radiologist can have a look quickly and easily… right from their phones.

Having your system scripted to run the AI on AWS sounds complicate but it actually isn’t that hard. Basically what happens is your server takes the request from the user interface when the doctor choose which AWS instance they want it to run on. It then sends a request to a script that fires up a matching AWS compute instance and runs your code. When it completes it shuts down the AWS instance and returns the results to your system. Your customers/hospitals have an AWS account and your system has an interface for them to enter their information.

Building your system like this can help you gain more customers, more quickly by being able to offer a lower price for acquisition due to you not needing to charge for server resources.

AI algorithms have to change and they have to change often in a new system until you work out all of the minor details. Algorithms look like fancy math hieroglyphs… until they have to become code. I’d propose creating a user interface for your head AI algorithm person to be able to easily enter and change the algorithms.

The way this would work is your user interface gives the person a way to enter their algorithm. The system then takes those symbols and maps them to the matching character codes. It then needs to map those character codes to the underlying code. I am a really huge fan of writing code that writes code so I don’t have to write code. LOL https://akashicseer.com/web-development/how-to-create-100-symfony-5-doctrine-2-or-3-repositories/

I’ve written all kinds of mapping code. I’ve spent a lot of time writing code that writes SQL queries. I think many other things would be easier, honestly.

Such code would mean you have your programmer write the mapping code one time and your AI person doesn’t have to know anything about programming to watch their algorithms work.

You don’t have to stop at just software to help doctors quickly diagnose illnesses. You could use the precious data your server collects to create a training system for radiologists. Imagine you can create a game where a radiologist is shown an x-ray and has to guess the illness. When they submit they find out if they are correct or not and why or why not. You wouldn’t use this data to train your AI but it is what is known as value added.

Your system could also spot radiologists that are not so good at their job and help better train them.

Another thing I would suggest is to have your team brainstorm all the features they can think of. But do not plan on adding these to your product immediately. Add them over time. This will allow you to get your product to market faster. It will also make your customers feel like they are getting something for their money as they see constant changes and improvements. And the final reason is to use it as a weapon against your competitors. If you make a superior product you will be copied. But the survivor of this kind of competition war will be the constant innovator. If you have planned future innovations but do not speak of them. Then all your competition can do is copy you. When you are one step behind you get mud in your eyes on wet days as your competitor runs ahead of you. LOLOLOLOL

About my app

The app I am currently working on right now works with the technology you would need to achieve the interfaces I describe. Basically I use javascript with a canvas element to create an interactive drawing tool. This technology can run on all devices running newer browsers. This means you do not have to create a web user interface, then another for an apple app, and another for a windows app and another for google play etc. These days I build it once and that is all. I am a lazy programmer. LOL

The app I am building contains a drawing/image editing user interface which lets users edit images or create drawings on any device. They can start it on a tablet, save, and start working on it from their desktop/laptop. I’ve spent a good bit of time learning about image processing, video processing, audio processing etc.

My app has a user reputation system because it has 0 administrators. The users of the social platform are the controllers. User A reports an item. The system asks x amount of user admins ( actual users not employees) to judge the content. Once they do, the system weighs their judgments and makes a decision. Admins have admin reputation. Users have users reputation. These reputations are built based on users actions and interactions with the system.

Starting out the system doesn’t really use an AI. It uses mostly basic machine learning algorithms and very basic math. In the future it will be moved up to using more AI. There are several reasons for this. First off, AI needs data and it takes time to gather that data. One enough data is collected I can finally start running AI on it. AI is only as effective as the data you give it. In Software engineering we have a saying for this “Garbage in equals garbage out”. So for a long while my system will use user judgments to gather data. Once it has enough data it can start guessing on it’s own what may or may not be bad content. It can then flag what it thinks is bad and have the user admins confirm it. This is the exact cycle I was describing above.

Categories
Software Development Web Development

How to create 100+ Symfony 5+ Doctrine 2 or 3 Repositories

Scroll to the bottom to view a video of this Repository maker in action. I make about 100 Repositories in less than 2 minutes.

So you need to make a lot of basic Doctrine repositories for your Symfony 5 app? I needed to do the same thing. That is why I created a Doctrine Repository maker for Symfony 5+ or any version that contains the Maker Bundle and uses the src/Repository and src/Entity directory structure.

What happened is I was not very familiar with Doctrine and EXACTLY how it wants entities to be structured.

I knew exactly how to design a database. But I didn’t feel like wasting time to learn everything about Doctrine ORM just to be able to make queries and use migrations.

Honestly I am not a big fan or ORMs because all of them are specific and take time to learn. I’ve spent over a decade with SQL thank you very much. Plus I code in so many languages, I don’t have time to learn everything about every ORM… and that is why SQL was invented.

too many words meme
Not enough time to read it all.

So I have this seriously complex app I am building. It needs several hundred tables. I had well over 100 tables already created via MySQL Workbench. I love workbench because it is a nice UI that makes creating tables and making changes super fast and easy. Much faster than typing all of that mess into an Entity directly.

So what I did is I used Doctrine to reverse engineer my database and create the mapping to the Entity Annotations. That was a pain, but still faster than learning EVERYTHING about Doctrine and typing all that stuff in.

too fast meme
As a lazy programmer I like to go fast. LOL

The main problems with reverse engineering with  Doctrine is it doesn’t create the repositories for the entities. And in order to use Doctrine with Symfony you need a Repository for each Entity, especially if you need custom queries/methods.

Another issue I had is if you do reverse engineer your database like this and you do create the repositories, you must then go into each Entity and add the Repository imports.

In order to create the Repositories for my new Entities, I created a maker. The maker gets a list of all of the Entities and existing Repositories. It then loops through each of the Entities that does not have a Repository and asks you if you would like to create one.

If you go with the naming path of the Repository maker it can overwrite files so be careful.

I also created an Entity clone maker, which I’ll talk about and share soon. Many of my Database tables were very similar, so I created an Entity cloner which can be used with Doctrine migrations and the Repository Maker to quickly finish building my app.

The Entity cloner also loops through entities and asks if you want to clone it. Very helpful.

wow dog meme
Entity Cloner is very helpful too…

Repository Maker in action

Categories
Web Development

how to fix doctrine symfony entity has a repositoryClass set to “entity name”, but this is not a valid class. Check your class naming

So you got this error while trying to access a repository from a Service or somewhere else. So what went wrong and what does this mean?

baby what does that even mean meme
What does this even mean?

Well it probably means that you did not use a fully qualified name for the repositoryClass statement or you do not have one at all.

Basically Doctrine needs to know where the repository for an Entity is located. It can be anywhere. If you define the repository like this

/**
 * User
 *
 * @ORM\Table(name="user", uniqueConstraints={@ORM\UniqueConstraint(name="email_UNIQUE", columns={"email"})}, indexes={@ORM\Index(name="email", columns={"email"})})
 * @ORM\Entity(repositoryClass=UserRepository::class)
 */

Then Doctrine looks in the same directory as your Entity aka the entity folder and since it can’t find it you get this error. I found that adding a simple use statement to the top of the Entity file like so works well.

use App\Repository\UserRepository;

You can also just add the fully qualified Repository name like this.

@ORM\Entity(repositoryClass="App\Repository\UserRepository")

It is a personal choice thing. I like the use statements because I am using PHP storm and it does use statements better than it does suggesting Repository names in the Entity annotations. Actually it doesn’t suggest the fully qualified path name so that is why I personally use “use” LOL

Links

You can find more about this error here.

Categories
Web Development Web Security

How to add CSRF protection to Symfony 5+ forms

How CSRF works

What you are basically doing with CSRF is trying to make sure a hacker has not created a fake form to gather private information from your user.

You want your app to create a unique string and save it on the server in a session cookie or database, redis etc. Then you add that string to a form in a hidden field. When the form is submitted by the user you fetch the CSRF string you created server side and compare it to the value in the form.

If the values match there was no hacking attempt and you can trust it. If the values do not match then a hacker has probably done something and you should not trust the form submission.

My interweb searches on this subject were not very helpful the other day. So, today I dig into the docs.

on the case detective meme
Time to be a Symfony detective

The first place to look is in the documentation for the security component. That article doesn’t say much about CSRF, but it has lots of links to how the Security system works in Symfony.

In the article above is a link of gold, How to implement CSRF protection.  I didn’t even find this in my  searches for “Symfony CSRF” protection yesterday. I am not sure why, maybe it was further down the list. This article contains some very helpful information though.

You may want to check your current configuration to see if you have enabled CSRF.

So it appears here that just adding to the configuration adds CSRF protection to all forms? Which I find confusing. Like this is truly the only change we need to make?

no way meme
Is it really that easy?

But that is only with forms created using Symfony form tools. If you create a custom form, not using Symfony form system, say REACT, you will need to implement your own CSRF more here.

Here is a good video about Symfony form security and shows how to quickly build an entire app with Symfony

Links

If you need to use PUT with CSRF protection see this SymfonyCast.

Here is a nice SymfonyCast about CSRF with a REST API.

SymfonyCast about CSRF with ReactJs.

Samesite cookie configuration in Symfony docs

Here is a nice Symfony bundle for 2 factor identification with CSRF

This awesome SymfonyCast covers security in  Symfony version 4 but most of it still applies to Symfony 5. It talks more about how using the Symfony form bundle automatically adds CSRF protection when enabled.

Categories
Software Development Web Development

How to install Redis with Docker for local testing

In another article I suggest installing Redis with docker but do not tell how. In this article I cover how to get a Redis Image up and running with Docker locally.

First you need to install Docker for your system.  After you have Docker installed, next you need to download a Redis image. Here is a list of official redis images.

To get the image you can use the pull method.
To view all of the current images you have on your system type

docker image ls -a

You should see something like this if you have any redis downloaded.

docker image ls outpu
output of docker image ls -a

Next create and run a new container with this command:

docker run --name redis-5 -dp 127.0.0.1:6379:6379 redis

–name is how you tell it the name you want for the container mine is redis-3
-dp the -d starts in detached mode, the p is for port and mine maps 6379 to 6379 127.0.0.1:6379:6379 tells docker to start the container with an ipv4 of 127.0.0.1 and network the systems port 6379 to the containers port 6379 without the ipv4 part Docker starts with an ipv4 of 0.0.0.0 127.0.0.1 is localhost some systems may map 0.0.0.0 to localhost in the hosts file too. You an add almost any conforming IP you want here and that will be the IP for the container docker run creates.
Here is a link to the docker docs about networking. Here is a link to Learning Ocean about docker networking.
redis is the name of the image I want to use to create the container.

That command will output something like this.

output of docker run
docker run output

Notice in the image, I did not specify an IP so it starts with an ipv4 of 0.0.0.0 not very helpful.

Once you have created the container you can start and stop it with the docker stop and start commands.

You will need to install the redis-cli if you want to quickly test your redis docker container is working. I am using ubuntu so I just install the redis-tools package. If you are using something else you are in for a world of hurt, see this stack question.  Ubuntu makes programming easier for most things.

Now to test if your docker redis is working just type the following into your command line to interact with redis via cli

redis-cli

You should see the following output, just the ip and port means your redis is working

your redis is working if you see this

To learn more about how to configure your symfony app to use this redis connection read this article.

Links

Here is a nice article about how to remove old images and containers and clean docker up.

Remove multiple docker images at once. This is good for when you have a bunch of unused images. Use this command to view all images currently on your system

Learning Ocean Docker tutorials – some of the best information you can find on Docker



		
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.

Categories
Software Development Web Development

How to fix Unknown database type enum requested, Doctrine\DBAL\Platforms\MySQL80Platform may not support it.

So you got this lovely error when trying to reverse engineer a database with doctrine. This error means that your database uses ENUM and is probably running on MySQL.

MySQL also contains SET which is about the same as ENUM except enum allows only 1 value from the list( or empty string or NULL) and set allows multiple values from the list. Doctrine doesn’t barf when it sees a SET but it sure does when it sees an ENUM.

baby threw up meme
Doctrine no ENUMs very well

Enums are ok when you know in advance that your will only ever require a small number of options and you will allow empty strings or NULL. I usually go with a table when the number of options will be like 10+ , or I don’t know for sure how many items there could be.

However working with Enums is a little difficult with Doctrine. Especially if you are trying to reverse engineer an existing database, you will get the following error :

doctrine enum barf
Doctrine barfs when it encounters an ENUM

The only way to reverse engineer a database that exists already is to redesign it the Doctrine way. You must remove all Enums and TinyInts. And if those tinyints were used in foreign key ids then, you must hunt down each one and remove it then you can add it again.

Then after you reverse engineer the database you can go into each and every single Entity that should be using an Enum and add the Enum to the Entity like so. Then you can rerun migrations:diff and update the database.

are you kidding me
So do you really want those Enums that bad?

Do you really need enums that bad?

Here is an article about tips and tricks to reverse engineer your existing database.