Immediately I want to say that I am new to Symfony and Doctrine and faced this kind of problem for the first time when using Symfony, but I also think that my experience can be useful to someone when solving similar or similar problems.
Background:
I had the opportunity not so long ago to upload a project on Symfony2 to the host site, but, as is often the case, the application refused to work on a live server, and having enabled debug, I saw a notification similar to the following:
Twig_Error_Runtime: An exception has been thrown during the rendering of a template.
("Warning: htmlspecialchars () [function.htmlspecialchars]: Invalid multibyte sequence in argument in
/.../app/cache/prod/classes.php line ... ") in" ... "at line ...
The reason for this error lies in the fact that Twig, by default, escapes any output, including using the
htmlspecialchars () function, which in this case stumbles over some kind of
Invalid multibyte sequence . And having decided that it would be nice to see this very
Invalid multibyte sequence , I missed the output of the corresponding variables through the raw filter in the template, like this:
{{ sometext|raw }}
It turned out that the Cyrillic text data from the database for some reason comes in the cp1251 encoding, although the encoding of the imported database, tables and acc. The fields from which the values ​​were taken were utf8. In phpMyAdmin, which was provided to me by the hoster, on the “Variables” tab, my attention was attracted by the following values ​​of the mysql server configuration parameters:
init connect SET NAMES cp1251
collation database cp1251_general_ci
collation servercp1251_general_ci
...
Problem:
Obviously, the reason was exactly in init connect, which when connected performed SET NAMES cp1251, because all values ​​were transferred to the application as cp1251.
SET NAMESLet me remind you that SET NAMES defines the encoding in which the client sends data to the server and also the encoding in which the server sends the return response to the client.
')
Problems of this kind are usually solved quite simply - immediately after connecting to the database in our application, we execute a query or a group of queries of the type:
SET CHARACTER SET UTF8;
SET NAMES UTF8;
But, as for me, any extra query to the database is not comme il faut at all, and the crutches in the framework code too. Therefore, at first I tried to resolve the issue through technical support.
The guys from technical support of the host company told me that they cannot transfer the base to the server configured under utf8, since all the servers they work with the same configuration on cp1251, and no one will change the server settings due to one project, because
changes affect all databases on this server (I understand them perfectly). But the problem had to be solved somehow ...
Decision:
However, the Symfony solution turned out to be quite elegant, which was the reason for writing this article.
I came to the aid of a tiny EventListener, which I hung on the postConnect event.
To create it, you need to make an entry in the app / config / config.yml file (if you use YAML) in the “services” section:
services:
onconnect.listener:
class: Dev \ SomeBundle \ EventListener \ OnConnect
tags:
- {name: doctrine.event_listener, event: postConnect}
Now in our Bundle, you need to create a listener file that corresponds to the namespace specified in the configuration above (
Dev \ SomeBundle \ EventListener \ OnConnect ).
those. We
put the OnConnect.php file in the
Dev / SomeBundle / EventListener folder as follows:
<?php
In my case, the problem with the encoding was completely eliminated, and besides, I did not have to insert any “hacks” into the doctrine or framework code. The event listening mechanism is widely used in symfony for solving various tasks. In the example described above,
Symfony 2.2.0 (Standard Edition) was used .
Findings:
- Pay attention to the settings of the MySQL server settings, some servers by default can work with a different encoding.
- If you do not have the ability to configure MySQL server properly, you can use the technique described above.