Слой доступа к базе данных CakePHP предоставляет слой абстракции и доступ к большинству аспектов взаимодействия с реляционными базами данных, включая поддержку соединений с сервером, построение запросов, предотвращение SQL инъекций, проверка и изменение схемы БД, отладку и создание профилей запросов, направляемых базе данных.
Функции, описанные в даннйо главе дают представление о возможностях взаимодействия с API базы данных на низком уровне. Если вместо этого вы хотите узнать больше о нолных возможностях ORM, обратитесь к разделам Query Builder и Табличные объекты.
Самый простой способ создать соединение с базой данных - использовать DSN
строку:
use Cake\Datasource\ConnectionManager;
$dsn = 'mysql://root:password@localhost/my_database';
ConnectionManager::config('default', ['url' => $dsn]);
После создания, появится возможность получить доступ к объекту соединения и начать его использовать:
$connection = ConnectionManager::get('default');
CakePHP поддерживаем следующие редяционные базы данных:
MySQL 5.5+
SQLite 3
PostgreSQL 8.3+
SQLServer 2008+
Oracle (с использованием плагина)
Вам понадобится соответствующее расширение PDO, установленное для каждой вышеуказанной базы данных. Процедурные API не поддерживаются.
База данных Oracle поддерживается с использованием плагина: Драйвер для базы данных Oracle
Выполнение сырых SQL запросов осуществляется очень просто:
use Cake\Datasource\ConnectionManager;
$connection = ConnectionManager::get('default');
$results = $connection->execute('SELECT * FROM articles')->fetchAll('assoc');
Используйте подготовленные выражения для добавления параметров:
$results = $connection
->execute('SELECT * FROM articles WHERE id = :id', ['id' => 1])
->fetchAll('assoc');
Также можно использовать сложные типы данных в качестве аргументов:
use Cake\Datasource\ConnectionManager;
use DateTime;
$connection = ConnectionManager::get('default');
$results = $connection
->execute(
'SELECT * FROM articles WHERE created >= :created',
['created' => new DateTime('1 day ago')],
['created' => 'datetime']
)
->fetchAll('assoc');
Вместо написания SQL запросов вручную, используйте конструктор:
$results = $connection
->newQuery()
->select('*')
->from('articles')
->where(['created >' => new DateTime('1 day ago')], ['created' => 'datetime'])
->order(['title' => 'DESC'])
->execute()
->fetchAll('assoc');
Вставка строк в базу данных обычно состоит всего из нескольких строк кода:
use Cake\Datasource\ConnectionManager;
use DateTime;
$connection = ConnectionManager::get('default');
$connection->insert('articles', [
'title' => 'A New Article',
'created' => new DateTime('now')
], ['created' => 'datetime']);
Обновление строк в базе данных также интуитивно понятно, следующий пример обновляет элемент article с id 10:
use Cake\Datasource\ConnectionManager;
$connection = ConnectionManager::get('default');
$connection->update('articles', ['title' => 'New title'], ['id' => 10]);
Точно так же метод delete()
используется для удаления строк из базы данных.
В следующем примере удаляется элемент article с id 10:
use Cake\Datasource\ConnectionManager;
$connection = ConnectionManager::get('default');
$connection->delete('articles', ['id' => 10]);
Согласно правилу, соединение с базой данных настраивается в config/app.php.
Информация о соединении в этом файле используется в классе
Cake\Datasource\ConnectionManager
, создавая настройку соединения,
которая будет использоваться вашим приложением. Пример настройки соединения находится
в файле config/app.default.php. Пример конфигурации выглядит следующим образом:
'Datasources' => [
'default' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
'username' => 'my_app',
'password' => 'sekret',
'database' => 'my_app',
'encoding' => 'utf8mb4',
'timezone' => 'UTC',
'cacheMetadata' => true,
]
],
Вышеуказанный код создаст соединение „default“ с предоставленными параметрами.
Вы можете определить столько соединений, сколько нужно в конфигурационном файле.
Вы можете также определить дополнительные соединения во время выполнения, используя
Cake\Datasource\ConnectionManager::config()
. Пример:
use Cake\Datasource\ConnectionManager;
ConnectionManager::config('default', [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
'username' => 'my_app',
'password' => 'sekret',
'database' => 'my_app',
'encoding' => 'utf8mb4',
'timezone' => 'UTC',
'cacheMetadata' => true,
]);
Параметры конфигурации также могут быть представлены в виде строки DSN. Это полезно при работе с переменными окружения или провайдерами PaaS:
ConnectionManager::config('default', [
'url' => 'mysql://my_app:sekret@localhost/my_app?encoding=utf8&timezone=UTC&cacheMetadata=true',
]);
При использовании DSN строки, вы можете определеить любые дополнительные параметры/настройки в качестве аргументов строки запроса.
По умолчанию, все объекты Таблицы используют default
соединение. Для использования
соединения не по умолчанию, смотрите Настройка соединений.
При конфинурации базы данных используется ряд ключей. Полный список приведен ниже:
Полное имя класса с указанием пространства имён, предоставляющее соединение с сервером базы данных. Этот класс несет отвечает за загрузку драйвера базы данных, обеспечивая механизм транзакций и подготавливая выражения SQL среди прочего.
Имя класса драйвера, используемого для реализации всех особенностей механизма базы данных. Это может быть как короткое имя класса с использованием синтаксиса плагина, полное имя класса или созданный экземпляр драйвера. Примеры сокращенных наименований класса: Mysql, Sqlite, Postgres, и Sqlserver
Следует ли использовать постоянное соединение с базой данных. Эта опция
не поддерживается SqlServer. Начиная с версии 3.4.13 CakePHP,
исключение выбрасывается, если вы пытаетесь установить
persistent
в true
с помощью SqlServer.
Имя хоста сервера базы данных (или IP-адрес).
Имя пользователя учетной записи.
Пароль учетной записи.
Имя базы данных для этого соединения. Избегайте использования .
названии вашей базы данных.
Из-за того, что экранирование символов осложнено, CakePHP не поддерживает .
в имени базы данных.
Путь к базе данных SQLite должен быть абсолютным (например, ROOT. DS. 'My_app.db'
),
чтобы избежать неправильного указания пути из-за использования относительного пути.
Порт TCP или сокет Unix, используемый для подключения к серверу.
Определяет кодировку, используемую при отправке SQL выражений на сервер. Этот параметр определяет кодировку по умолчнию для всех баз данных кроме DB2.
Часовой пояс, установленный на сервере.
Настройка в базе данных, используемая в PostgreSQL для указания используемой схемы.
Используется драйверами для подключения через файлы Unix сокетов. Если вы используете PostgreSQL и хотите использовать Unix сокеты, оставьте значение хоста пустым.
Путь до файла SSL ключа. (Поддерживается только MySQL).
Путь до файла SSL сертификата. (Поддерживается только MySQL).
Путь до файла издателя SSL сертификата. (Поддерживается только MySQL).
Список запросов, которые должны быть отправлены серверу базы данных, когда создается соединение.
Установите значение на true
для включения логирования запросов. При включеннои режиме
запросы будут логироваться на уровне debug
с областью действий queriesLog
.
Установите значение на true
, если используются зарезервированные слова или специальные
символы в названиях таблиц или столбцов. Включение этого параметра приведёт к тому, что в запросах,
сформированных с использованием Query Builder, будут использоваться идентификаторы,
заключенные в кавычки при создании SQL. Необходимо отметить, что это снизит производительность
так как каждый запрос должен быть отслежен и обработан до выполнения.
Ассоциативный массив констант PDO, которые должны быть переданы в базовый экземпляр PDO. Смотрите документацию PDO для флагов, поддерживаемых драйвером, который вы используете.
Либо логическое true
, либо строка, содержащая конфигурацию кэша для хранения метаданных.
Отключение кэширования метаданных не рекомендуется и может привести к
очень низкой производительности. Смотрите раздел: ref: database-metadata-cache
для получения дополнительной информации.
Установите разрешения для сгенерированного файла базы данных. (Поддерживается только SQLite)
На данном этапе будет полезно обратить внимание на Соглашения CakePHP. Правильное наименование для таблиц (и добавление некоторых столбцов) может дать некоторые дополнительные функции и избежать настройки. Например, если назвать таблицу базы данных big_boxes, таблицу BigBoxesTable и контроллер BigBoxesController, то все вместе будет работать автоматически. Согласно правилам, необходимо использовать знак нижнего подчеркивания, нижний регистр и множественное число в наименованиях таблиц баз данных - например: bakers, pastry_stores и savory_cakes.
Класс ConnectionManager
действует как реестр для доступа к соединениям базы данных,
которые существуют в приложении. Это место, где другие объекты могут получить ссылки на
существующие соединения.
Настроенные один раз, соединения могут быть получены с использованием
Cake\Datasource\ConnectionManager::get()
. Данный метод создаст и загрузит соединение,
если оно не было создано до этого или возвратит существующее известное соединение:
use Cake\Datasource\ConnectionManager;
$conn = ConnectionManager::get('default');
Попытка загрузить соединения, которые не существуют, приведет к вызову исключения.
Используя config()
и get()
можно создавать новые соединения, которые не определены в
файлах конфигурации, во время выполнения приложения:
ConnectionManager::config('my_connection', $config);
$conn = ConnectionManager::get('my_connection');
Смотрите раздел Настройка для получения дополительной информации по конфигурационным данным, используемым при создании соединений.
Так как каждая база данных включает в себя разный набор типов данных или одинаковые имена, используются для схожих типов данных, CakePHP предоставляет набор абстрактных типов данных для использования со слоем базы данных. Типы, которые поддерживает CakePHP:
Обычно поддерживается столбцами типа CHAR
или VARCHAR
. Использование опции
fixed
преобразует столбец в тип CHAR. Для SQL Server используются типы
NCHAR
и NVARCHAR
.
Соответствует типам TEXT
.
Соответствует типу UUID, если база данных имеет таковой, в противном случае
генерируется поле CHAR(36)
.
Соответствует типу UUID, если база данных имеет таковой, в противном случае
генерируется столбец BINARY(16)
.
Соответствует типу INTEGER
, предоставляемому базой данных. BIT на данный момент
не поддерживается.
Соответствует типу SMALLINT
, предоставляемому базой данных.
Соответствует типу TINYINT
или SMALLINT
, предоставляемому базой данных. Для MySQL
TINYINT(1)
является логическим типом.
Соответствует типу BIGINT
, предоставляемому базой данных.
Соответствует либо DOUBLE
, либо FLOAT
в зависимости от базы данных. Опция precision
используется для определения кол-ва знаков после запятой.
Соответствует типу DECIMAL
. Поддерживаются опции length
и precision
.
Соответствует BOOLEAN
, кроме MySQL, где TINYINT(1)
используется для представления
булевых значений. BIT(1)
на данный момент не поддерживается.
Соответствует типу BLOB
или BYTEA
, в зависимости от базы данных.
Соответствует простому типу часового пояса столбца DATE
. Возвращаемое значение столбца
этого типа - Cake\I18n\Date
, которое расширяет основной класс DateTime
.
Соответствует простому типу часового пояса столбца DATETIME
. В PostgreSQL и SQL Server
преобразуется в тип TIMESTAMP
. Возвращаемое значение по умолчанию столбца этого типа -
Cake\I18n\Time
, которое расширяет встроенный класс DateTime
и
Chronos.
Соответствует типу TIMESTAMP
.
Соответствует типу TIME
во всех базах данных.
Соответствует типу JSON
, если он доступен, иначе преобразуется в TEXT
.
Тип JSON
был добавлен в версии 3.3.0
Эти типы используются как для функций отражения схемы, которые предоставляет CakePHP, так и для функций создания схемы, которые CakePHP использует при проведении тестов.
Каждый тип предоставляет функции преобразования между представлениями PHP и SQL.
Эти методы вызываются на основе подсказок для типов данных при выполнении запросов.
Например, столбец, помеченный как „datetime“ будет автоматически конвертировать входные параметры
из экземпляров DateTime
во временные метки или форматированные строки представляющие даты.
Аналогично, столбцы с „двоичными“ данными принимают файловые дескрипторы и генерируют
файловые дескрипторы при чтении данных.
Изменено в версии 3.3.0: Был добавлен тип json
.
Изменено в версии 3.5.0: Были добавлены типы smallinteger
и tinyinteger
.
Изменено в версии 3.6.0: Был добавлен тип binaryuuid
.
Если необходимо использовать особые типы, которые не встроены в CakePHP, можно добавить новые дополнительные типы в систему типов CakePHP. Классы типов имплементируют следующие методы:
toPHP
: Преобразует данное значение из типа базы данных в эквивалент PHP.
toDatabase
: Преобразует данное значение из типа PHP в один из подходящих базе данных.
toStatement
: Преобразует данное значение в эквивалент выражения.
marshal
: Сериализирует необработанные данные в объекты PHP.
Простой способ реализовать базовый интерфейс - расширить класс Cake\Database\Type
.
Например, если необходимо добавить тип JSON, нужно написать следуюий класс для типа:
// в src/Database/Type/JsonType.php
namespace App\Database\Type;
use Cake\Database\Driver;
use Cake\Database\Type;
use PDO;
class JsonType extends Type
{
public function toPHP($value, Driver $driver)
{
if ($value === null) {
return null;
}
return json_decode($value, true);
}
public function marshal($value)
{
if (is_array($value) || $value === null) {
return $value;
}
return json_decode($value, true);
}
public function toDatabase($value, Driver $driver)
{
return json_encode($value);
}
public function toStatement($value, Driver $driver)
{
if ($value === null) {
return PDO::PARAM_NULL;
}
return PDO::PARAM_STR;
}
}
По умолчанию метод toStatement ()
обрабатывает значения как строки, которые предназначены
для нового типа. Как только новый тип создан, необходимо добавить его в отображение типа.
Во время начальной загрузки приложения необходимо сделать следующее:
use Cake\Database\Type;
Type::map('json', 'App\Database\Type\JsonType');
Добавлено в версии 3.3.0: Тип Json, описанный в этом примере был добавлен в ядро фреймворка.
Затем мы можем перезагрузить данные отраженной схемы для использования нового типа, и слой базы данных CakePHP автоматически конвертирует JSON данные при создании запросов. Пользовательские типы можно использовать в вашей Таблице с помощью метода _initializeSchema():
use Cake\Database\Schema\TableSchema;
class WidgetsTable extends Table
{
protected function _initializeSchema(TableSchema $schema)
{
$schema->columnType('widget_prefs', 'json');
return $schema;
}
}
Добавлено в версии 3.3.0: Поддержка сопоставления пользовательских типов данных к выражениям SQL была добавлена в версии 3.3.0.
Предыдущий пример сопоставляет пользовательский тип данных для столбца типа „json“, который легко выразить
в виде строеи в выражении SQL. Сложные типы данных SQL не могут быть выражены строками/числами в SQL запросах.
При работе с этими типами данных класс Типа должен имплементировать интерфейс
Cake\Database\Type\ExpressionTypeInterface
. Этот интерфейс даёт возможность пользовательскому типу представлять
значение в виде SQL выражения. Например, построим простой класс Типа для обработки типа данных POINT
из MySQL. Сначала определим объект „value“, который используется для представления данных POINT
в PHP:
// в src/Database/Point.php
namespace App\Database;
// Наш объект-значение не изменяем.
class Point
{
protected $_lat;
protected $_long;
// Factory метод.
public static function parse($value)
{
// Парсинг данных из MySQL.
return new static($value[0], $value[1]);
}
public function __construct($lat, $long)
{
$this->_lat = $lat;
$this->_long = $long;
}
public function lat()
{
return $this->_lat;
}
public function long()
{
return $this->_long;
}
}
После создания объекта-значения понадобится класс Типа для сопоставления данных в этот объект-значение и в выражение SQL:
namespace App\Database\Type;
use App\Database\Point;
use Cake\Database\Expression\FunctionExpression;
use Cake\Database\Type as BaseType;
use Cake\Database\Type\ExpressionTypeInterface;
class PointType extends BaseType implements ExpressionTypeInterface
{
public function toPHP($value, Driver $d)
{
return Point::parse($value);
}
public function marshal($value)
{
if (is_string($value)) {
$value = explode(',', $value);
}
if (is_array($value)) {
return new Point($value[0], $value[1]);
}
return null;
}
public function toExpression($value)
{
if ($value instanceof Point) {
return new FunctionExpression(
'POINT',
[
$value->lat(),
$value->long()
]
);
}
if (is_array($value)) {
return new FunctionExpression('POINT', [$value[0], $value[1]]);
}
// Обработка других случаев.
}
}
Вышеуказанный класс выполняет несколько интересных вещей:
Метод toPHP
парсит результаты SQL запроса в объект-значение.
Метод marshal
преобразовывает данные запроса в объект-значение.
Здесь принимаются такие строковые значения, как '10.24,12.34
и массивы.
Метод toExpression
обрабатывает преобразование объект-значения в эквивалент выражения SQL. В этом примере
полученный в результате SQL будет выглядеть как POINT(10.24, 12.34)
.
Как только будет создан пользовательский тип, понадобится подключить тип к таблице классов.
Добавлено в версии 3.2: Неизменяемые объекты date/time были добавлены в версии 3.2.
Так как объекты Date/Time легко изменить, CakePHP дает возможность использовать неизменяемые объект-значения. Наилучшим образом это можно сделать в файле config/bootstrap.php:
Type::build('datetime')->useImmutable();
Type::build('date')->useImmutable();
Type::build('time')->useImmutable();
Type::build('timestamp')->useImmutable();
Примечание
В новых приложениях неизменяемые объекты используются по умолчанию.
Классы подключений предоставляют простой интерфейс для согласованного взаимодействия с соединениями базы данных. Они предназначены для более абстрактного интерфейса для слоя драйвера и предоставляют функции выполнения запросов, логирования запросов и выполнения транзакционных операций.
Получив объект подключения, вы вероятно захотите выполнить с ним несколько запросов.
Слой абстракции базы данных CakePHP предоставляет функции обёртки поверх PDO и
собственных драйверов. Данные обертки предоставляют схожий интерфейс аналогичный PDO.
Существует несколько различных способов выполнения запросов в зависимости от его типа,
который необходимо выполнить и того какие результаты нужны в ответ.
Наиболее простой метод - query()
, который позволяет запускать уже выполненные SQL запросы:
$stmt = $conn->query('UPDATE articles SET published = 1 WHERE id = 2');
Метод query()
не допускает применение дополнительных параметров. Если нужны дополнительные параметры,
необходимо использовать метод execute()
, который дает возможность использовать шаблон для подстановки:
$stmt = $conn->execute(
'UPDATE articles SET published = ? WHERE id = ?',
[1, 2]
);
Без явного указания типов, execute
предположит, что все подстановочные значения имеют строковый тип.
Если необходимо привязать определенные типы данных, можно использовать абстрактные имена типов при
создании запроса:
$stmt = $conn->execute(
'UPDATE articles SET published_date = ? WHERE id = ?',
[new DateTime('now'), 2],
['date', 'integer']
);
Это позволяет использовать расширенные типы данных в ваших приложениях и правильно конвертировать их в SQL выражения. Последний и наиболее гибкий способ создания запросов - использование Query Builder. Данный подход позволяет сконструировать сложные и выразительные запросы без использования платформенно-ориентированного SQL:
$query = $conn->newQuery();
$query->update('articles')
->set(['published' => true])
->where(['id' => 2]);
$stmt = $query->execute();
При использовании конструктора запросов, ни один SQL запрос не будет послан на сервер
базы данных до вызова метода execute()
или пока запрос не будет повторён.
При итерации запроса, сначала он выполняется, а затем его результатирующий набор данных будет проитерирован:
$query = $conn->newQuery();
$query->select('*')
->from('articles')
->where(['published' => true]);
foreach ($query as $row) {
// Сделать что-нибудь со строкой.
}
Примечание
Если есть экземпляр Cake\ORM\Query
, можно использовать all()
для получения результатирующего набора SELECT запросов.
Объекты соединения предоставляют несколько простых способов выполнения транзакций
базы данных. Наиболее простой способ выполнения - используя методы begin()
,
commit()
и rollback()
, которые преобразуются в их SQL эквиваленты:
$conn->begin();
$conn->execute('UPDATE articles SET published = ? WHERE id = ?', [true, 2]);
$conn->execute('UPDATE articles SET published = ? WHERE id = ?', [false, 4]);
$conn->commit();
В дополнение к этим экземплярам интерфейсов соединений в том числе предоставляется
метод transactional()
, который делает обработку вызовов begin/commit/rollback
еще проще:
$conn->transactional(function ($conn) {
$conn->execute('UPDATE articles SET published = ? WHERE id = ?', [true, 2]);
$conn->execute('UPDATE articles SET published = ? WHERE id = ?', [false, 4]);
});
В дополнение к базовым запросам, вы можете выполнить более сложные запросы, используя Query Builder или Табличные объекты. Транзакционный метод сделает следующее:
Вызов begin
.
Вызов замыкания.
Если замыкание выбрасывает исключение, то вызывается откат изменений. Будет выброшено первоначальное исключение.
Если замыкание возвращает false
, будет вызван откат изменений.
Если замыкание выполняется успешно, транзакция будет завершена.
При использовании нижнего уровня API базы данных, вы будете часто сталкиваться с
объектами выражения. Эти объекты позволяют манипулировать подготовленными выражениями
из драйвера. После создания и выполнения объекта запроса или использования execute()
,
у вас появится экземпляр StatementDecorator
. Он оборачивает основной объект выражения
и предоставляет несколько дополнительных функций.
Вы можете создать объект выражения, используя execute()
или prepare()
.
Метод execute()
возвращает выражение с привязанными к нему значениями.
При использовании prepare()
возвращается неполное выражение:
// Выражения execute уже имеют связанные значения.
$stmt = $conn->execute(
'SELECT * FROM articles WHERE published = ?',
[true]
);
// Выражения из метода prepare будут параметрами полей для подстановки.
// Необходимо привязать параметры до того как их использовать.
$stmt = $conn->prepare('SELECT * FROM articles WHERE published = ?');
После того как выражение подготовлено, вы можете привязать дополнительные данные и выполнить его.
После того как подготовленное выражение создано, можно привязть дополнительные ланные.
Можно привязать множество значений сразу, используя метод bind()
или привязать
отдельные элементы, используя bindValue
:
$stmt = $conn->prepare(
'SELECT * FROM articles WHERE published = ? AND created > ?'
);
// Привязка множества значений
$stmt->bind(
[true, new DateTime('2013-01-01')],
['boolean', 'date']
);
// Привязка одного значения
$stmt->bindValue(1, true, 'boolean');
$stmt->bindValue(2, new DateTime('2013-01-01'), 'date');
При создании выражений, можно использовать именованные ключи массива вместо индексных:
$stmt = $conn->prepare(
'SELECT * FROM articles WHERE published = :published AND created > :created'
);
// Привязка множества значений
$stmt->bind(
['published' => true, 'created' => new DateTime('2013-01-01')],
['published' => 'boolean', 'created' => 'date']
);
// Привязка одного значения
$stmt->bindValue('published', true, 'boolean');
$stmt->bindValue('created', new DateTime('2013-01-01'), 'date');
Предупреждение
Нельзя смешивать индексные и именованные ключи массива в одном и том же выражении.
После подготовки выражения и привязки к нему данных, можно выполнить его и получить строки.
Выражения должны быть выполнены с использованием метода execute()
. После выполнения, результаты
можно получить, используя fetch()
, fetchAll()
или проитерировать выражение:
$stmt->execute();
// Прочитать одну строку.
$row = $stmt->fetch('assoc');
// Прочитать все строки.
$rows = $stmt->fetchAll('assoc');
// Прочитать строки путем итерации.
foreach ($stmt as $row) {
// Выполнить задачу
}
Примечание
Считывание строк итерированием подтягивает строки в „обеих“ режимах. Это означает, что можно получить как нумерованные индексные и ассоциированные индексные результаты.
После выполнения выражения, можно получить количество затронутых строк:
$rowCount = count($stmt);
$rowCount = $stmt->rowCount();
Если запрос не был выполнен успешно, можно получить соответствующую информацию об ошибке,
используя методы errorCode()
и errorInfo()
. Эти методы работают также, как те, что
предоставляются PDO:
$code = $stmt->errorCode();
$info = $stmt->errorInfo();
Логирование запросов может быть включено при настройке соединения, установив параметр
log
на значение true
. Также можно включить логирование запросов во время выполнения,
используя enableQueryLogging
:
// До 3.7.0 используйте logQueries()
// Включить логирование.
$conn->enableQueryLogging(true);
// Отключить логирование
$conn->enableQueryLogging(false);
Когда логирование запросов включено, запросы логируются в Cake\Log\Log
,
используя уровень „debug“ и область действия „queriesLog“.
Необхоимо, чтобы логгер был настроен на этот уровень и область действия. Логирование
с опцией stderr
может быть полезно при работе с юнит тестами и логирование в
files/syslog может быть полезно при работе с веб-запросами:
use Cake\Log\Log;
// Консольное логирование
Log::config('queries', [
'className' => 'Console',
'stream' => 'php://stderr',
'scopes' => ['queriesLog']
]);
// Логирование в файле
Log::config('queries', [
'className' => 'File',
'path' => LOGS,
'file' => 'queries.log',
'scopes' => ['queriesLog']
]);
Примечание
Логирование запросов предназначено только для процесса отладки/разработки. Никогда не оставляйте логирование запросов включенным в рабочем режиме, так как это может негативно сказаться на производительности приложения.
По умолчанию CakePHP не использует кавычки идентификаторов в сгенерированных SQL запросах. Причина этого заключается в том, что использование кавычек в идентификаторах имеет несколько недостатков:
Снижение производительности - использование кавычек в идентификаторах намного медленнее и сложнее чем их неиспользование.
Не нужно в большинстве случаев - в неунаследованных базах данных, которые соответствуют правилам CakePHP, нет причины использовать кавычки в идентификаторах.
Для унаследованной схемы, в которой требуются кавычки в идентификаторах, можно включить настройку quoteIdentifiers
в Настройка. Эта функция включается в том числе и при выполении:
$conn->getDriver()->enableAutoQuoting();
При включенном режиме, использование кавычек в идентификаторах
Когда использование кавычек в идентификаторах включено, вызывается дополнительный проход запроса, который
ковертирует все идентификаторы в объекты IdentifierExpression
.
Примечание
SQL фрагменты, содержащиеся в объектах QueryExpression не изменяются.
Функция объектно-реляционного отображения данных CakePHP использует отражение базы данных для
определения схемы, индексов и внешних ключей, которые содержит приложение. Так как эти
метаданные изменяются нечасто и требуют много ресурсов при доступе, они обычно кэшируются.
По умолчанию, метаданные хранятся в конфигурации кэша _cake_model_
. Можно определить
пользовательскую конфигурацию кэша, используя опцию cacheMetatdata
в конфигурации
источника данных:
'Datasources' => [
'default' => [
// Other keys go here.
// Use the 'orm_metadata' cache config for metadata.
'cacheMetadata' => 'orm_metadata',
]
],
В том числе можно определить конфигурацию кэширования метаданных во время выполенния
с помощью метода cacheMetadata()
:
// Отключить кэширование
$connection->cacheMetadata(false);
// Включить кэширование
$connection->cacheMetadata(true);
// Использование пользовательской конфигурации кэширования
$connection->cacheMetadata('orm_metadata');
CakePHP вклчюает инструмент CLI для управления кэшированием метаданных. Обратитесь к разделу /console-and-shells/schema-cache для получения дополнительной информации.
Если необходимо создать соединение без выбора базы даных, можно опустить название базы данных:
$dsn = 'mysql://root:password@localhost/';
Теперь можно использовать объект соединения для выполнения запросов, которые создают/изменяют базы данных. Например, для создания базы данных:
$connection->query("CREATE DATABASE IF NOT EXISTS my_database");
Примечание
При создании базы данных, рекомендуется установить параметры кодировки и сортирующей последовательности. Если не указать эти данные, база данных установит системные значения, которые используются по умолчанию.