Phinx config for Symfony2

As you may know, you can also use a php file for your phinx config. Just replace the phinx.yml with phinx.php and it should work fine. I like to use phinx in my Symfony2 bundles, because it’s better to use in a vcs like GIT. Also you can do rollbacks, and add the migration scripts to your build script like ant.

Anyways, when using different environments, you probably have different database credentials. I put this little preg_match in the php file to parse the database config from parameters.yml. This phinx.php is located in the bundle, so for example /src/Acme/DemoBundle/phinx.php .. the migrations would then be placed in /src/Acme/DemoBundle/Migrations/ .. Just make sure the location to the parameters.yml is correct at the top of the script. You probably want to use relative paths because otherwise the path is still different in your environments. Your development VM may have different paths than your production server.

 

Use Sublime Text to help you create doctrine Entities part two

In my previous post I wrote about a regexp search and replace to create Doctrine entities easily from a phpmyadmin CSV export. After that post I found myself checking my own website to copy and paste the regexp. Then I tried recording a macro in Sublime, but it turns out sublime doesn’t record search and replace actions.

Then I learnt about the feature to install packages to your sublime install, which has a really cool RegReplace package. Just follow the instructions on that page. I was a bit confused at point three, but turns out I had to go to Package Control: install package. You can go there by pressing cmd+shift+p and then type Package Control. It should appear in the list.

Then this superuser post helped me configuring the RegReplace package. It took me a while to figure out how to use extended back references. But I got it all working now. I use Sublime Text 2, so go to Preferences → Package Settings → Reg Replace → Settings – Default.

Sublime_Reg_Replace

At the replacements section I added this:

Don’t forget to enable “extended_back_reference” at the end of this file.

Then I went to Preferences → Package Settings → Reg Replace → Commands – Default and added this at the end:

Now when I am in my editor and press cmd+shift+p I can just type “Doctrine” and my command shows up. Then it’ll convert the cvs formatted table heads to a nice doctrine entity.

 

Use Sublime Text to help you create doctrine Entities

I don’t know about you, but when working in a projects that already exists, I am afraid to let Symfony extract the entities for my project. I’d rather just define a new entity myself. To get started, Sublime Text is very useful in creating the entity with annotations. Here’s what I do.

First, in phpmyadmin I go to the table I want to create an entity for. I use browse, select the first record, and then export this to CSV. Export to screen, and make sure the headers are in the first row.

Copy the headers to your clipboard, and then paste them in sublime text. Then first replace the comma’d with newlines, which is easy .. just search for , and repalce with \n. Make sure you have the regex function enabled (that’s the .* button).

Now the magic trick so convert the rows with column names to an almost complete entity. Again use the search and replace.

Find What: ^\"(.*)\"$
Replace With: \/\*\*\n \* \@ORM\\Column\(name\=\"$1\", type\=\"\", nullable\=false\)\n \*/\nprivate \$\l\1\;\n

SublimeText

Now you should have something like this:

If course you can alter this any way you like.

Now copy this to your IDE of choice (PhpStorm probably, right?) and finish the details.

Forms in Symfony2: dependent selectboxes

My wish was simple: I wanted to have an extra dropdown box, to be able to filter a table, so the second dropdown box would have less items. So the second dropdown box depends on the first. I found two nice articles about this, but I missed a few things before I got it to work. This post tries to describe what my pitfalls were.

The great articles I found were: Symfony2.4: Dependent Forms and Symfony2 – Dynamic forms, an event-driven approach

The difference with my approach is: building the lists of the selectboxes should be inside the form builder. This way I think it’s more reusable and code is in one place. I don’t want to write extra methods in my controller to fill the selectboxes with javascript. My idea was just to submit the form, and let the form figure out what it should do: save the object, or fill the second list with options.

To describe my pitfall’s, I better first describe my situation. I changed the use case for the sake of this article, but it’s the same with my problem. Suppose you have a Person who can own several cars. On the person edit page, where you can edit his name and other properties, I wanted to add a table with the cars he owns. Under this table I have action buttons for New, Edit and Delete. When you use new, the div on that page is reloaded with the form, so the page isn’t reloaded, you are still on the edit Person page.

This would be my database model:

Forms in Symfony2: model used in this example

The list of cars with all their types would be huge, so I wanted to select the Brand (Opel, Mercedes, BMW) first. This wasn’t a value that I should save to my Person_has_Car model, so I set mapped to false. This was my main problem, because now this value wouldn’t be mapped to the entity, so how should I read it?

Initially I wanted to post the BrandId to the form, and based on this BrandId I wanted to build the select. I found that the PRE_SUBMIT and POST_SUBMIT weren’t called when you don’t submit the entire form. Probably because of CSFR that doesn’t match.

Then after a long search I found that at the PRE_SUBMIT Form Event, the data was just an array instead of an object.

Well, after a few days of frustration, googling, trying, googling and trying, this is what I came up with. Maybe it’s not the best approach, but it seems to work.

So Image that you are on a “User edit” page, and you want to add a car to his account.

Form

My form class PersonHasCarType would be something like this:

Twig template

The (simplified) twig form would look something like this:

The $.parseHtmlBlock is just a little code snippet that replaces HTML based on a json response. It also does some initialisation. The snippet looks like this:

Note the clearOnChange in the javascript that clears the second selectbox (if it exists) with empty values. If I don’t do this, the form has validation errors the second time you change the brand of the car. This was an easy hack to prevent this, and also I think it’s actually not that bad to reset invalid fields.

Controller

Now my controller is something like this:

So basically we now have a form that submits itself whenever the first selectbox changes. The controller checks if the form is fully entered by checking if the car object is set. This approach will probably conflict if you use validation. But for me this seems to work in my application.

Active menu determination in Metronic theme

So we bought the Metronic theme from keenthemes. It’s fully featured and packed, but I was wondering how the theme determines what the active link is. Browsing through the comments I found out that we’re supposed to handle this ourselves, server sided. No fancy javascript that handles this from itself.

Fortunately I found a way to determine the route in Symfony. This returns the name of the route, not the result form path. So now it’s easy to compare your current page. All I had to do is put this in Twig:

But if I use submenu’s, how would I know what parent menu should have the active class as well? Easy: just check for the first part of the route (if you set your routes smart enough though). So if you have a menu called “promotion” where you have sub menu’s like “create, list”, you might want to name your routes like _promotion_new and _promotion_list. At the parent menu item promotion you could easily check if the route starts with _promotion_. The substr equivalent is slice. So the HTML for the parent menu item would have something like this:

If you named your router less ‘smart’, you could use a larger OR compare in the if statement.

Easy does it.

Symfony translations using PoEdit

For my Symfony project, that has to support two languages, I started with created a xliff file manually. This was really annoying. Not only the creation of the xml, but also the inability to see if you didn’t already translate this string. So, I wanted to use Poedit. But this wasn’t so easy.

I needed to create .po files, which are the uncompiled language files that contain all translations. Actually, a .pot file would even be better. I didn’t know how to extract the strings.

The LeaseWeb gettext bundle looked great, but I already had used normal translation strings in twig, like {% trans %} and {% endtrans %}. I didn’t want to refactor my whole project, just to be able to use gettext (with a third party bundle anyways). It might be a good option if you start your project from scratch though.

So then I found the Twig Gettext Extractor. This seemed rather complicated, as I never worked with Poedit before too. I am working on a Mac, and my code is on a virtual machine. This project seems to be about a tool that extracts the language strings from Twig. I decided to give it a try, and installed the project standalone.

When I tried to run through the project in Poedit, it came up with an error. I copy and pasted the commands in my terminal, and found out that it couldn’t render the Twig template, because I was using KnpPaginatorBundle. It didn’t understand a twig function that it was using.

Ok, fair enough, so I decided to add the bundle to my Symfony project. It didn’t help much: it was still throwing php errors, so it couldn’t extract anything.

Then I tried the JMSTranslationBundle for a second time. I had already tried this, but when I ran

as stated in the docs, it would output to xliff again. I don’t exactly remember why, but I installed the bundle again, and ran this extract again. This time, a .mo en .po file were present in my /Resource/translations bundle. To my great surprise, it now updated this .po file!

I was also surprised, because the website says the bundle doesn’t support .mo files.

 

Anyways, it turns out it is supported. At least on Symfony 2.3.6. The command you need to issue on an empty translations directory is this:

After that you can update your translations with this command:

Still, I think I am missing something in the workflow. When I add new strings to be translated to my project, the strings are added to the .po file, but they are not marked as “new” in Poedit. So it’s difficult to see what strings still need to be translated.

But, it’s much better than creating those language files by hand.

Created entities are all wrong

So I was performing a console doctrine:generate:entities for my bundle. The first thing I noticed is that it did’t create the appropriate getters and setters, especially for my OneToMany relations. The add and remove methods weren’t there.

So I started deleting all the methods, recreating them, and weird stuff kept happening. It even created some private properties that I didn’t define in my entity at all.

Eventually I found out that there was old ORM data in my project. Although I deleted the cache, this ORM data was still there. So, go to your bundle directory, and then to Resources/config/doctrine. Delete all the files in here. Then recreate your entities.

Raw mysql in Doctrine

To perform a raw mysql statement in symfony through Doctrine:

This example was being used in a controller.

Pass array of options to form builder

This post is just to archive a solution I used to pass an option list, to create a selectbox. The code I used to create the form type:

The setDefaultOptions method makes sure you pass the array of options. If you don’t, it will throw an exception.

Force Doctrine to close mysql connections

So I wrote a nice shell within app/console, which also used pcntl_fork(). Of course there was a very old archive somewhere in my mind that knew that this would mean trouble when you use mysql connections. But since I don’t explicitly use mysql_connect anymore, because Doctrine does this for me, I didn’t realise I faced the same problem as years ago.

When you fork a process with pcntl_fork(), it will copy the current process. This also contains the handles to your mysql connection. When the first child process dies, it will clean up these handles, and therefore close the connection.

Simple solution: make sure all connections are closed before you fork a child. That way, the child is forced to create a new connection.

I solved this using the following piece of code in the script.