Сначала короткая версия:
Я хочу, чтобы команда doctrine:database:create создала базу данных с правильной / определенной кодировкой и сопоставлением. Как этого добиться? (В лучшем случае без изменения каких-либо глобальных настроек на сервере.)
Подробная версия:
Контекст - это приложение Symfony 4 и Doctrine 2. СУБД: MySQL, ОС: Ubuntu 14.04. Я хочу создать базу данных с помощью Doctrine:
$ bin/console doctrine:database:create
Оператор SQL, выполняемый Doctrine в фоновом режиме:
CREATE DATABASE `mydb`
Значит: он не использует настройки charset и collate из .../config/packages/doctrine.yaml, а также игнорируется DATABASE_URL в .../.env.
.../config/packages/doctrine.yaml
parameters:
env(DATABASE_URL): ''
doctrine:
dbal:
# configure these for your database server
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
# With Symfony 3.3, remove the `resolve:` prefix
url: '%env(resolve:DATABASE_URL)%'
mapping_types:
enum: string
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Base/Entity'
prefix: 'App\Base\Entity'
alias: App
.../.env
###> doctrine/doctrine-bundle ###
DATABASE_URL=mysql://root:[email protected]:3306/mydb?charset=utf8mb4
###< doctrine/doctrine-bundle ###
База данных DEFAULT_CHARACTER_SET_NAME - это latin1, а DEFAULT_COLLATION_NAME - это latin1_swedish_ci:
SELECT
`DEFAULT_CHARACTER_SET_NAME`, `DEFAULT_COLLATION_NAME`
FROM
information_schema.SCHEMATA
WHERE
schema_name = 'mydb'
;
+----------------------------+------------------------+
| DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME |
+----------------------------+------------------------+
| latin1 | latin1_swedish_ci |
+----------------------------+------------------------+




Вот еще несколько ответов: Doctrine2: как настроить сопоставление всех таблиц с UTF8
Они рекомендуют использовать сопоставление в самом объекте, но вам нужно указать все такие объекты, и если у вас их много, это проблема
@ORM\Table(options = {"collate" = "utf8mb4_unicode_ci"})
Второй подход - использовать опции в doctrine.yml.
doctrine:
dbal:
options:
1002: "SET NAMES 'utf8mb4_unicode_ci'"
И третье решение - отредактировать файл конфигурации mysql и добавить туда кодировку по умолчанию.
my.cnf
[mysqld]
character-set-server=utf8mb4_unicode_ci
collation-server=utf8mb4_unicode_ci
ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ MySQL (для текущего сеанса)
SET GLOBAL `character_set_server` = 'utf8mb4';
SET GLOBAL `collation_server` = 'utf8mb4_unicode_ci';
@automatix как это? 1002: «УСТАНОВИТЬ ГЛОБАЛЬНЫЙ 'utf8mb4_unicode_ci'»? Отправьте наш ответ, как вы это сделали :)
Только что обновил свой ответ. Но на самом деле это то, чего я хотел избежать - изменений на сервере.
Похоже, текущая версия доктрины (doctrine / dbal v2.10.0) не поддерживает создание баз данных mysql с кодировкой и сопоставлением, отличными от по умолчанию. Команда Symfony php bin/console doctrine:database:create вызывает Doctrine\DBAL\Platforms\MySqlPlatform::getCreateDatabaseSQL() в фоновом режиме.
public function getCreateDatabaseSQL($name)
{
return 'CREATE DATABASE ' . $name;
}
Из дерева конфигурации Symfony не добавляется кодировка или сопоставление :-( Почему бы и нет? ^^
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
driver: 'mysql'
server_version: '5.7'
# Only needed for MySQL (ignored otherwise)
charset: utf8mb4
default_table_options:
collate: utf8mb4_unicode_ci
Так что в настоящее время это не поддерживается.
Спасибо за ваш ответ! К решениям: 1. Я бы хотел избежать явной установки кодировки для каждой отдельной таблицы. Я хочу иметь это на уровне базы данных. 2. Опция
1002у меня не работает.1002: "SET NAMES 'utf8mb4_unicode_ci'"вызывает ошибку БД (An exception occurred in driver: SQLSTATE[42000] [1115] Unknown character set: 'utf8mb4_unicode_ci'). Поэтому я поменял его наutf8mb4. Без ошибок, но и без эффекта - база данных создается с кодировкойlatin1и сопоставлениемlatin1_swedish_ci. 3. Кажется, что эти настройки вmy.cnfигнорируются. Что работает, так этоSET GLOBAL.