01 Уровень абстракции базы данных
Уровень абстракции базы данных
Phalcon\Db является компонентом, располагающимся под Phalcon\Mvc\Model, который управляет слоем моделей в фреймворке. Он состоит из независимых абстракций высокого уровня для баз данных, полностью написанных на C.
Этот компонент позволяет производить манипуляции с базой данных на более низком уровне, чем при использовании традиционных моделей.
Адаптеры баз данных
Этот компонент использует адаптеры для инкапсуляции определенных сведений о системе базы данных. Phalcon использует PDO для подключения к базам данных. Следующие СУБД поддерживаются:
Класс | Описание |
---|---|
Phalcon\Db\Adapter\Pdo\Mysql | Наиболее часто используемая реляционная система управления базами данных (RDBMS), которая работает как сервер, обеспечивающий многопользовательский доступ к некоторому набору баз данных. |
Phalcon\Db\Adapter\Pdo\Postgresql | PostgreSQL- мощная реляционная система баз данных с открытым исходным кодом. Это более чем 15 лет активного развития и проверенная архитектура, которая завоевала прочную репутацию за надежность, целостность данных и точность. |
Phalcon\Db\Adapter\Pdo\Sqlite | Библиотека SQLite реализует автономную, бессерверную, не требующую конфигурации и при этом поддерживающую транзакции базу данных на основе языка SQL. |
Константы
Класс Phalcon\Db\Enum предоставляет ряд констант,которые можно использовать на уровне DB.
FETCH_ASSOC
=\Pdo::FETCH_ASSOC
FETCH_BOTH
=\Pdo::FETCH_BOTH
FETCH_BOUND
=\Pdo::FETCH_BOUND
FETCH_CLASS
=\Pdo::FETCH_CLASS
FETCH_CLASSTYPE
=\Pdo::FETCH_CLASSTYPE
FETCH_COLUMN
=\Pdo::FETCH_COLUMN
FETCH_FUNC
=\Pdo::FETCH_FUNC
FETCH_GROUP
=\Pdo::FETCH_GROUP
FETCH_INTO
=\Pdo::FETCH_INTO
FETCH_KEY_PAIR
=\Pdo::FETCH_KEY_PAIR
FETCH_LAZY
=\Pdo::FETCH_LAZY
FETCH_NAMED
=\Pdo::FETCH_NAMED
FETCH_NUM
=\Pdo::FETCH_NUM
FETCH_OBJ
=\Pdo::FETCH_OBJ
FETCH_PROPS_LATE
=\Pdo::FETCH_PROPS_LATE
FETCH_SERIALIZE
=\Pdo::FETCH_SERIALIZE
FETCH_UNIQUE
=\Pdo::FETCH_UNIQUE
Дополнительные константы доступны в объекте Phalcon\Db\Column. Этот объект используется для описания столбца (или поля) в таблице базы данных. Эти константы также определяют, какие типы поддерживаются ORM.
Типы Привязки
BIND_PARAM_BLOB
- BlobBIND_PARAM_BOOL
- ЛогическийBIND_PARAM_DECIMAL
- ДесятичныйBIND_PARAM_INT
- Целое числоBIND_PARAM_NULL
- NullBIND_PARAM_STR
- СтрокаBIND_SKIP
- Пропускать обязательные
Тип столбца
TYPE_BIGINTEGER
- Большое целое числоTYPE_BIT
- BitTYPE_BLOB
- BlobTYPE_BOOLEAN
- ЛогическийTYPE_CHAR
- СимволTYPE_DATE
- ДатаTYPE_DATETIME
- Дата-времяTYPE_DECIMAL
- ДесятичныйTYPE_DOUBLE
- ДвойнойTYPE_ENUM
- ПеречислениеTYPE_FLOAT
- ПлавающийTYPE_INTEGER
- Целое числоTYPE_JSON
- JSONTYPE_JSONB
- JSONBTYPE_LONGBLOB
- Длинный BlobTYPE_LONGTEXT
- Длинный текстTYPE_MEDIUMBLOB
- Средний BlobTYPE_MEDIUMINTEGER
- Среднее Целое ЧислоTYPE_MEDIUMTEXT
- Средний ТекстTYPE_SMALLINTEGER
- Малое Целое ЧислоTYPE_TEXT
- ТекстTYPE_TIME
- ВремяTYPE_TIMESTAMP
- Отметка времениTYPE_TINYBLOB
- Крошечный BlobTYPE_TINYINTEGER
- Крошечное Целое ЧислоTYPE_TINYTEXT
- Крошечный ТекстTYPE_VARCHAR
- Тип varchar
Примечание: В зависимости от вашей СУБД, некоторые типы будут недоступны (например,
JSON
не поддерживается для Sqlite).
Методы
public function addColumn( string $tableName, string $schemaName, ColumnInterface $column ): bool
Добавляет столбец в таблицу
public function addIndex( string $tableName, string $schemaName, IndexInterface $index ): bool
Добавляет индекс к таблице
public function addForeignKey( string $tableName, string $schemaName, ReferenceInterface $reference ): bool
Добавляет внешний ключ к таблице
public function addPrimaryKey( string $tableName, string $schemaName, IndexInterface $index ): bool
Добавляет первичный ключ к таблице
public function affectedRows(): int
Возвращает количество затронутых строк по последней INSERT
/UPDATE
/DELETE
, сообщенное системой базы данных
public function begin( bool $nesting = true ): bool
Запуск транзакции в соединении
public function close(): bool
Закрывает активное соединение, возвращая успех. Phalcon автоматически закрывает и уничтожает активные соединения
public function commit( bool $nesting = true ): bool
Фиксирует активную транзакцию в соединении
public function connect( array $descriptor = null ): bool
Этот метод автоматически вызывается в конструкторе Phalcon\Db\Adapter\Pdo\AbstractPdo. Вызовите его, когда вам нужно восстановить соединение с базой данных
public function createSavepoint( string $name ): bool
Создает новую точку сохранения
public function createTable( string $tableName, string $schemaName, array $definition ): bool
Создаёт новую таблицу.
Creates a table ```php public function createView( string $viewName, array $definition, string $schemaName = null ): bool
Создает новый вид.
public function delete( mixed $table, mixed $whereCondition = null, mixed $placeholders = null, mixed $dataTypes = null ): bool
Удаляет данные из таблицы с помощью пользовательского синтаксиса SQL СУБД
public function describeColumns( string $table, string $schema = null ): ColumnInterface[]
Возвращает массив объектов Phalcon\Db\Column, описывающих таблицу
public function describeIndexes( string $table, string $schema = null ): IndexInterface[]
Возвращает список индексов таблицы
public function describeReferences( string $table, string $schema = null ): ReferenceInterface[]
Возвращает список ссылок на таблицу
public function dropColumn( string $tableName, string $schemaName, string $columnName ): bool
Удаляет столбец из таблицы
public function dropForeignKey( string $tableName, string $schemaName, string $referenceName ): bool
Удаление внешнего ключа из таблицы
public function dropIndex( string $tableName, string $schemaName, string $indexName ): bool
Удаление индекса из таблицы
public function dropPrimaryKey( string $tableName, string $schemaName ): bool
Удаление первичного ключа из таблицы
public function dropTable( string $tableName, string $schemaName = null, bool $ifExists = true ): bool
Удаление таблицы из схемы / базы данных
public function dropView( string $viewName, string $schemaName = null, bool $ifExists = true ): bool
Удаление представления.
public function escapeIdentifier( mixed identifier ): string
Экранирует имя столбца/таблицы/схемы.
public function escapeString(string $str): string
Экранирует строку, чтобы избежать SQL-инъекции.
public function execute( string $sqlStatement, mixed $placeholders = null, mixed $dataTypes = null ): bool
Отправляет SQL-инструкции на сервер базы данных, возвращающий состояние успеха. Использовать этот метод только в том случае, если инструкция SQL, отправленная на сервер, не возвращает строки
public function fetchAll( string $sqlQuery, int $fetchMode = 2, mixed $placeholders = null ): array
Выводит полный результат запроса в массив
public function fetchColumn( string $sqlQuery, array $placeholders = [], mixed $column = 0 ): string | bool
Возвращает n '-е поле первой строки в результате запроса SQL
// Получение количества роботов $robotsCount = $connection->fetchColumn("SELECT count(*) FROM robots"); print_r($robotsCount); // Получение имени последнего отредактированного робота $robot = $connection->fetchColumn( "SELECT id, name FROM robots order by modified desc", 1 ); print_r($robot);
public function fetchOne( string $sqlQuery, int $fetchMode = 2, mixed $placeholders = null ): array
Возвращает первую строку в результате запроса SQL
public function forUpdate( string $sqlQuery ): string
Возвращает SQL, измененный с параметром FOR UPDATE
public function getColumnDefinition( ColumnInterface $column ): string
Возвращает определение столбца SQL из столбца
public function getColumnList( mixed $columnList ): string
Получение списка столбцов
public function getConnectionId(): string
Получение уникального идентификатора активного подключения
public function getDescriptor(): array
Возвращает дескриптор, используемый для подключения к активной базе данных
public function getDialect(): DialectInterface
Возвращает экземпляр внутреннего диалекта
public function getDialectType(): string
Возвращает название используемого диалекта
public function getDefaultIdValue(): RawValue
Возвращает значение идентификатора по умолчанию для вставки в столбец идентификаторов
public function getInternalHandler(): \PDO
Возвращает внутренний обработчик PDO
public function getNestedTransactionSavepointName(): string
Возвращает имя точки сохранения, используемое для вложенных транзакций
public function getRealSQLStatement(): string
Активный оператор SQL в объекте без привязки параметров replace
public function getSQLStatement(): string
Активный оператор SQL в объекте
public function getSQLBindTypes(): array
Активный оператор SQL в объекте
public function getSQLVariables(): array
Активный оператор SQL в объекте
public function getType(): string
Возвращает тип системы баз данных, для которой используется адаптер.
public function insert( string $table, array $values, mixed $fields = null, mixed $dataTypes = null ): bool
Вставка данных в таблицу с использованием пользовательского синтаксиса SQL СУБД
public function insertAsDict( string $table, mixed $data, mixed $dataTypes = null ): bool
Вставка данных в таблицу с использованием пользовательского синтаксиса RBDM SQL
// Вводить новый счет $success = $connection->insertAsDict( 'co_invoices', [ 'inv_cst_id' => 1, 'inv_title' => 'Invoice for ACME Inc.', ] ) // Следующее предложение SQL отправляется в систему базы данных INSERT INTO `co_invoices` ( `inv_cst_id`, `inv_title` ) VALUES ( 1, 'Invoice for ACME Inc.' )
public function isNestedTransactionsWithSavepoints(): bool
Возвращает, если вложенные транзакции должны использовать точки сохранения
public function isUnderTransaction(): bool
Проверяет, находится ли соединение в транзакции
public function lastInsertId( mixed $sequenceName = null )
Возвращает идентификатор вставки для столбца auto_increment, вставленного в последнюю инструкцию SQL
public function limit( string $sqlQuery, int $number ): string
Добавляет предложение LIMIT к аргументу sqlQuery
public function listTables( string $schemaName = null ): array
Список всех таблиц в базе данных
public function listViews( string $schemaName = null ): array
Список всех представлений в базе данных
public function modifyColumn( string $tableName, string $schemaName, ColumnInterface $column, ColumnInterface $currentColumn = null ): bool
Изменяет столбец таблицы на основе определения
public function query( string $sqlStatement, mixed $placeholders = null, mixed $dataTypes = null ): ResultInterface | bool
Отправляет инструкции SQL на сервер базы данных, возвращая состояние успешного выполнения. Используйте этот метод только тогда, когда инструкция SQL, отправленная на сервер, возвращает строки
public function releaseSavepoint( string $name ): bool
Релизы с заданной точкой сохранения
public function rollback( bool $nesting = true ): bool
Откаты активной транзакции в соединении
public function rollbackSavepoint( string $name ): bool
Возвращает SQL, измененный предложением LOCK IN SHARE MODE
public function setNestedTransactionsWithSavepoints( bool $nestedTransactionsWithSavepoints ): AdapterInterface
Установить, должны ли вложенные транзакции использовать точки сохранения
public function supportSequences(): bool
Проверяет, требуется ли системе базы данных последовательность для получения автоматических числовых значений
public function tableExists( string $tableName, string $schemaName = null ): bool
Генерирует SQL-проверку на наличие схемы.стол
public function tableOptions( string $tableName, string $schemaName = null ): array
Получает параметры создания из таблицы
public function update( string $table, mixed $fields, mixed $values, mixed $whereCondition = null, mixed $dataTypes = null ): bool
Обновление данных в таблице с использованием пользовательского синтаксиса SQL СУБД
public function updateAsDict( string $table, mixed $data, mixed $whereCondition = null, mixed $dataTypes = null ): bool
Обновляет данные в таблице с помощью пользовательского синтаксиса RBDM SQL. Другой, более удобный синтаксис
// Обновление существующего счета-фактуры $success = $connection->updateAsDict( 'co_invoices', [ 'inv_title' => 'Invoice for ACME Inc.', ], 'inv_id = 1' ) // Следующее предложение SQL отправляется в систему базы данных UPDATE `co_invoices` SET `inv_title` = 'Invoice for ACME Inc.' WHERE inv_id = 1
public function useExplicitIdValue(): bool
Проверяет, требуется ли системе базы данных явное значение для столбцов идентификаторов
public function viewExists( string $viewName, string $schemaName = null ): bool
Создает SQL-проверку на наличие представления схемы
Пользовательский адаптер
Интерфейс Phalcon\Db\Adapter\AdapterInterface должен быть реализован для создания собственных адаптеров баз данных или расширения существующих. Кроме того, вы можете расширить Phalcon\Db\Adapter\AbstractAdapter, который уже имеет некоторую реализацию для вашего пользовательского адаптера.
Экранирование
Экранирование идентификаторов включено по умолчанию. Однако если вам нужно отключить эту функцию, вы можете сделать это с помощью метода setup()
:
<?php \Phalcon\Db::setup( [ 'escapeIdentifiers' => false, ] );
Фабрика
newInstance()
Хотя все классы адаптеров могут быть созданы с помощью ключевого слова new, Phalcon предлагает класс Phalcon\Db\Adapter\PdoFactory , так что вы можете легко создавать экземпляры адаптеров PDO. Все вышеперечисленные адаптеры зарегистрированы на заводе и лениво загружаются при вызове. Фабрика позволяет регистрировать дополнительные (пользовательские) классы адаптеров. Единственное, что нужно учитывать, - это выбор названия адаптера по сравнению с существующими. Если вы определяете одно и то же имя, вы перезапишете встроенное. Объекты кэшируются на заводе, поэтому, если вы вызовете метод newInstance()
с теми же параметрами во время того же запроса, вы получите тот же объект обратно.
Зарезервированные имена::
mysql
- Phalcon\Db\Adapter\Pdo\Mysqlpostgresql
- Phalcon\Db\Adapter\Pdo\Postgresqlsqlite
- Phalcon\Db\Adapter\Pdo\Sqlite
Пример ниже показывает, как можно создать адаптер MySQL с ключевым словом new
или фабрикой:
<?php use Phalcon\Db\Adapter\Pdo\MySQL; $connection = new MySQL( [ 'host' => 'localhost', 'username' => 'root', 'password' => '', 'dbname' => 'test', ] );
<?php use Phalcon\Db\Adapter\Pdo\PdoFactory; $factory = PdoFactory(); $connection = $factory ->newInstance( 'mysql', [ 'host' => 'localhost', 'username' => 'root', 'password' => '', 'dbname' => 'test', ] ) ;
load()
Вы также можете использовать метод load()
для создания адаптера с помощью объекта конфигурации или массива. В приведенном ниже примере используется ini
-файл для создания экземпляра подключения к базе данных с помощью load()
.
[database] host = TEST_DB_MYSQL_HOST username = TEST_DB_MYSQL_USER password = TEST_DB_MYSQL_PASSWD dbname = TEST_DB_MYSQL_NAME port = TEST_DB_MYSQL_PORT charset = TEST_DB_MYSQL_CHARSET adapter = mysql
<?php use Phalcon\Config\Adapter\Ini; use Phalcon\Di; use Phalcon\Db\Adapter\Pdo\Factory; $container = new Di(); $config = new Ini('config.ini'); $container->set('config', $config); $container->set( 'db', function () { return (new Factory())->load($this->config->database); } );
Диалекты
Встроенный
Phalcon инкапсулирует конкретные детали каждого компонента database engine в диалектах. Phalcon\Db\Dialect предоставляет адаптерам общие функции и генератор SQL.
Класс | Описание |
---|---|
Phalcon\Db\Dialect\Mysql | Специфический диалект SQL для системы баз данных MySQL |
Phalcon\Db\Dialect\Postgresql | Специфический диалект SQL для системы баз данных PostgreSQL |
Phalcon\Db\Dialect\Sqlite | Специфический диалект SQL для системы баз данных SQLite |
Пользовательский диалект
С помощью Phalcon интерфейса Phalcon\Db\DialectInterface должны быть реализованы для того, чтобы создавать свои собственные диалекты базу или расширить уже существующие. Вы также можете улучшить свой текущий диалект, добавив больше команд / методов, которые поймет PHQL. Например, при использовании адаптера MySQL, вы, возможно, захотите, чтобы PHQL признать MATCH ... AGAINST ...
синтаксис. Мы связываем этот синтаксис с MATCH_AGAINST
Мы создаем экземпляр диалекта. Мы добавляем пользовательскую функцию, чтобы PHQL понимал, что делать, когда он находит ее в процессе синтаксического анализа. В приведенном ниже примере мы регистрируем новую пользовательскую функциюMATCH_AGAINST
. После этого все, что нам нужно сделать, это добавить настроенный объект диалекта в наше соединение.
<?php use Phalcon\Db\Dialect\MySQL as SqlDialect; use Phalcon\Db\Adapter\Pdo\MySQL as Connection; $dialect = new SqlDialect(); $dialect->registerCustomFunction( 'MATCH_AGAINST', function ($dialect, $expression) { $arguments = $expression['arguments']; return sprintf( ' MATCH (%s) AGAINST (%)', $dialect->getSqlExpression($arguments[0]), $dialect->getSqlExpression($arguments[1]) ); } ); $connection = new Connection( [ 'host' => 'localhost', 'username' => 'root', 'password' => '', 'dbname' => 'test', 'dialectClass' => $dialect, ] );
Теперь мы можем использовать эту новую функцию в PHQL, которая, в свою очередь, переведет ее на правильный синтаксис SQL:
<?php $phql = ' SELECT * FROM Invoices WHERE MATCH_AGAINST(title, :pattern:)'; $posts = $modelsManager->executeQuery( $phql, [ 'pattern' => $pattern, ] );
Примечание: существует больше примеров о том, как расширить PHQL в документе PHQL.
Подключить
Для создания соединения необходимо создать экземпляр класса adapter. Для этого требуется только массив с параметрами подключения. В приведенном ниже примере показано, как создать соединение, передающее как обязательные, так и необязательные параметры:
Адаптер | Параметр | Статус |
---|---|---|
MySQL |
host |
обязательный |
username |
обязательный | |
password |
обязательный | |
dbname |
обязательный | |
persistent |
необязательный | |
PostgreSQL |
host |
обязательный |
username |
обязательный | |
password |
обязательный | |
dbname |
обязательный | |
schema |
необязательный | |
Sqlite |
dbname |
обязательный |
Подключение к каждому адаптеру может быть достигнуто либо фабрикой, как показано выше, либо путем передачи соответствующих опций конструктору каждого класса.
<?php use Phalcon\Db\Adapter\Pdo\Mysql; use Phalcon\Db\Adapter\Pdo\Postgresql; use Phalcon\Db\Adapter\Pdo\Sqlite; $config = [ 'host' => '127.0.0.1', 'username' => 'mike', 'password' => 'sigma', 'dbname' => 'test_db', ]; $connection = new Mysql($config); $config = [ 'host' => 'localhost', 'username' => 'postgres', 'password' => 'secret1', 'dbname' => 'template', ]; $connection = new Postgresql($config); $config = [ 'dbname' => '/path/to/database.db', ]; $connection = new Sqlite($config);
Дополнительные опции PDO
Вы можете установить параметры PDO во время подключения, передав параметры options
:
<?php use Phalcon\Db\Adapter\Pdo\Mysql; $connection = new Mysql( [ 'host' => 'localhost', 'username' => 'root', 'password' => 'sigma', 'dbname' => 'test_db', 'options' => [ PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'", PDO::ATTR_CASE => PDO::CASE_LOWER, ] ] );
Создание.
Чтобы вставить строку в базу данных, можно использовать raw SQL или использовать методы, представленные адаптером:
<?php $sql = " INSERT INTO `co_invoices` ( `inv_cst_id`, `inv_title` ) VALUES ( 1, 'Invoice for ACME Inc.' ) "; $success = $connection->execute($sql);
Raw SQL
<?php $sql = ' INSERT INTO `co_invoices` ( `inv_cst_id`, `inv_title` ) VALUES ( ?, ? ) '; $success = $connection->execute( $sql, [ 1, 'Invoice for ACME Inc.', ] );
Подстановки
<?php $success = $connection->insert( 'co_invoices', [ 1, 'Invoice for ACME Inc.', ], [ 'inv_cst_id', 'inv_title', ] );
Динамическая генерация
<?php $success = $connection->insertAsDict( 'co_invoices', [ 'inv_cst_id' => 1, 'inv_title' => 'Invoice for ACME Inc.', ] );
Динамическая генерация (альтернативный синтаксис)
Обновление
Чтобы обновить строку в базе данных, можно использовать raw SQL или методы, представленные адаптером:
<?php $sql = " UPDATE `co_invoices` SET `inv_cst_id`= 1, `inv_title` = 'Invoice for ACME Inc.' WHERE `inv_id` = 4 "; $success = $connection->execute($sql);
Raw SQL
<?php $sql = " UPDATE `co_invoices` SET `inv_cst_id`= ?, `inv_title` = ? WHERE `inv_id` = ? "; $success = $connection->execute( $sql, [ 1, 'Invoice for ACME Inc.', 4, ] );
<?php $sql = " UPDATE `co_invoices` SET `inv_cst_id`= ?, `inv_title` = ? WHERE `inv_id` = ? "; $success = $connection->execute( $sql, [ 1, 'Invoice for ACME Inc.', 4, ] );
Подстановки
<?php $success = $connection->update( 'co_invoices', [ 'inv_cst_id', 'inv_title', ], [ 1, 'Invoice for ACME Inc.', ], 'inv_id = 4' );
Динамическая генерация
Примечание: с синтаксисом выше, переменные для
where
частиupdate
(inv_id = 4
) не экранируются!
<?php $success = $connection->updateAsDict( 'co_invoices', [ 'inv_cst_id' => 1, 'inv_title' => 'Invoice for ACME Inc.', ], 'inv_id = 4' );
Динамическая генерация (альтернативный синтаксис)
Примечание: с синтаксисом выше, переменные для
where
частиupdate
(inv_id = 4
) не экранируются!
<?php $success = $connection->update( 'co_invoices', [ 'inv_cst_id', 'inv_title', ], [ 1, 'Invoice for ACME Inc.', ], [ 'conditions' => 'id = ?', 'bind' => [ 4 ], 'bindTypes' => [ \PDO::PARAM_INT ], ] );
С экранированными символами
<?php $success = $connection->updateAsDict( 'co_invoices', [ 'inv_cst_id' => 1, 'inv_title' => 'Invoice for ACME Inc.', ], [ 'conditions' => 'id = ?', 'bind' => [ 4 ], 'bindTypes' => [ \PDO::PARAM_INT ], ] );
С экранированными символами (альтернативный синтаксис)
Удалить
<?php $sql = ' DELETE `co_invoices` WHERE `inv_id` = 4 '; $success = $connection->execute($sql);
Raw SQL
<?php $sql = ' DELETE `co_invoices` WHERE `inv_id` = ? '; $success = $connection->execute( $sql, [ 4 ] );
Подстановки
<?php $success = $connection->delete( 'co_invoices', 'inv_id = ?', [ 4, ] );
Динамическая генерация
Параметры
Адаптеры Phalcon\Db
предоставляют несколько методов для запроса строк из таблиц. В этом случае требуется определенный синтаксис SQL целевого компонента database engine:
<?php $sql = ' SELECT inv_id, inv_title FROM co_invoices ORDER BY inv_created_at '; $result = $connection->query($sql); while ($invoice = $result->fetch()) { echo $invoice['inv_title']; } $invoices = $connection->fetchAll($sql); foreach ($invoices as $invoice) { echo $invoice['inv_title']; } $invoice = $connection->fetchOne($sql);
По умолчанию эти вызовы создают массивы как с ассоциативными, так и с числовыми индексами. Это поведение можно изменить с помощью функции Phalcon\Db\Result::setFetchMode()
. Этот метод получает константу, определяющую, какой тип индекса требуется.
Постоянный | Описание |
---|---|
Phalcon\Db\Enum::FETCH_NUM |
Возвращает массив с числовыми индексами |
Phalcon\Db\Enum::FETCH_ASSOC |
Возвращает массив с ассоциативными индексами |
Phalcon\Db\Enum::FETCH_BOTH |
Возвращает массив с ассоциативными и числовыми индексами |
Phalcon\Db\Enum::FETCH_OBJ |
Возвращает объект вместо массива |
<?php $sql = ' SELECT inv_id, inv_title FROM co_invoices ORDER BY inv_created_at '; $result = $connection->query($sql); $result->setFetchMode( Phalcon\Db\Enum::FETCH_NUM ); while ($invoice = $result->fetch()) { echo $invoice[0]; }
Метод query()
возвращает экземпляр Phalcon\Db\Result\Pdo. Эти объекты инкапсулируют всю функциональность, связанную с возвращаемым результирующим набором, т. е. обход, поиск определенных записей, подсчет и т. д.
<?php $sql = ' SELECT inv_id, inv_title FROM co_invoices ORDER BY inv_created_at '; $result = $connection->query($sql); while ($invoice = $result->fetch()) { echo $invoice['name']; } $result->seek(2); $invoice = $result->fetch(); echo $result->numRows();
Связывание
Привязанные параметры также поддерживаются. Хотя использование связанных параметров оказывает минимальное влияние на производительность, настоятельно рекомендуется использовать эту методологию, чтобы исключить возможность того, что ваш код будет подвержен атакам SQL-инъекций. Поддерживаются как строковые, так и позиционные заполнители.
<?php $sql = ' SELECT inv_id, inv_title FROM co_invoices WHERE inv_cst_id = ? ORDER BY inv_created_at '; $result = $connection->query( $sql, [ 4, ] );
Привязка с числовыми заполнителями
<?php $sql = " UPDATE `co_invoices` SET `inv_cst_id`= :cstId, `inv_title` = :title WHERE `inv_id` = :id "; $success = $connection->query( $sql, [ 'cstId' => 1, 'title' => 'Invoice for ACME Inc.', 'id' => 4, ] );
Привязка с именованными местозаполнителями
При использовании числовых заполнителей вам нужно будет определить их как целые числа, т. е. 1
или 2
. В этом случае '1'
или '2'
или ' 2 ' считаются строками, а не числами, поэтому заполнитель не может быть успешно заменен. С любым адаптером данные автоматически экранируются с помощью PDO Quote. Эта функция учитывает кодировку соединения, поэтому рекомендуется определить правильную кодировку в параметрах соединения или в конфигурации сервера базы данных, так как неправильная кодировка приведет к нежелательным последствиям при хранении или извлечении данных.
Кроме того, вы можете передать свои параметры непосредственно в методы execute
или query
. В этом случае привязанные параметры передаются непосредственно в PDO:
<?php $sql = ' SELECT inv_id, inv_title FROM co_invoices WHERE inv_cst_id = ? ORDER BY inv_created_at '; $result = $connection->query( $sql, [ 1 => 4, ] );
Связывание с заполнителями PDO
Типизация
Заполнители позволяют привязывать параметры, чтобы избежать SQL-инъекций:
<?php $phql = ' SELECT inv_id, inv_title FROM Invoices WHERE inv_cst_id = :customerId: ORDER BY inv_created_at '; $invoices = $this ->modelsManager ->executeQuery( $phql, [ 'customerId' => 4, ] ) ;
Однако некоторые системы баз данных требуют дополнительных действий при использовании заполнителей, таких как указание типа связанного параметра:
<?php use Phalcon\Db\Column; // ... $phql = ' SELECT inv_id, inv_title FROM Invoices WHERE inv_cst_id = :customerId: ORDER BY inv_created_at '; $invoices = $this ->modelsManager ->executeQuery( $phql, [ 'customerId' => 4, ], Column::BIND_PARAM_INT ) ;
<?php use Phalcon\Db\Column; // ... $phql = ' SELECT inv_id, inv_title FROM Invoices WHERE inv_cst_id = :customerId: ORDER BY inv_created_at '; $invoices = $this ->modelsManager ->executeQuery( $phql, [ 'customerId' => 4, ], Column::BIND_PARAM_INT ) ;
Вы можете использовать типизированные плейсхолдеры в параметрах, вместо того, чтобы указывать тип привязки в метод executeQuery()
:
<?php $phql = ' SELECT inv_id, inv_title FROM Invoices WHERE inv_cst_id = {customerId:int} ORDER BY inv_created_at '; $invoices = $this ->modelsManager ->executeQuery( $phql, [ 'customerId' => 4, ], ) ; $phql = ' SELECT inv_id, inv_title FROM Invoices WHERE inv_title <> {title:str} ORDER BY inv_created_at '; $invoices = $this ->modelsManager ->executeQuery( $phql, [ 'title' => 'Invoice for ACME Inc', ], ) ;
Вы также можете опустить тип, если вам не нужно его указывать:
<?php $phql = ' SELECT inv_id, inv_title FROM Invoices WHERE inv_cst_id = {customerId} ORDER BY inv_created_at '; $invoices = $this ->modelsManager ->executeQuery( $phql, [ 'customerId' => 4, ], ) ;
Типизированные заполнители также являются более мощными, так как теперь мы можем связать статический массив без необходимости передавать каждый элемент независимо в качестве заполнителя:
<?php $phql = ' SELECT inv_id, inv_title FROM Invoices WHERE inv_cst_id IN ({ids:array}) ORDER BY inv_created_at '; $invoices = $this ->modelsManager ->executeQuery( $phql, [ 'ids' => [1, 3, 5], ], ) ;
Доступны следующие типы:
Тип Привязки | Константа Типа Привязки | Пример |
---|---|---|
str | Column::BIND_PARAM_STR |
{name:str} |
int | Column::BIND_PARAM_INT |
{number:int} |
double | Column::BIND_PARAM_DECIMAL |
{price:double} |
bool | Column::BIND_PARAM_BOOL |
{enabled:bool} |
blob | Column::BIND_PARAM_BLOB |
{image:blob} |
null | Column::BIND_PARAM_NULL |
{exists:null} |
array | Array of Column::BIND_PARAM_STR |
{codes:array} |
array-str | Array of Column::BIND_PARAM_STR |
{names:array-str} |
array-int | Array of Column::BIND_PARAM_INT |
{flags:array-int} |
Cast
По умолчанию привязанные параметры не приводятся в поле пользователя PHP к указанным типам привязки. Эта опция позволяет делать значения Phalcon cast перед привязкой их с PDO. Распространенным сценарием является передача строки в местозаполнитель LIMIT
/OFFSET
:
<?php $number = '100'; $phql = ' SELECT inv_id, inv_title FROM Invoices LIMIT {number:int} '; $invoices = $modelsManager->executeQuery( $phql, [ 'number' => $number, ] );
Это приводит к следующему исключению:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''100'' at line 1' in ....
Это происходит потому, что '100'
является строковой переменной. Он легко фиксируется путем ввода значения в целое число:
<?php $number = '100'; $phql = ' SELECT inv_id, inv_title FROM Invoices LIMIT {number:int} '; $invoices = $modelsManager->executeQuery( $phql, [ 'number' => (int) $number, ] );
Однако это решение требует, чтобы разработчик уделял особое внимание тому, как передаются связанные параметры и их типы. Чтобы упростить эту задачу и избежать непредвиденных исключений, вы можете дать указание Phalcon сделать это для вас:
<?php \Phalcon\Db::setup( [ 'forceCasting' => true, ] );
Следующие действия выполняются в соответствии с указанным типом привязки:
Тип Привязки | Действие |
---|---|
Column::BIND_PARAM_STR |
Приведение значения в виде собственной строки PHP |
Column::BIND_PARAM_INT |
Приведение значения в виде собственного целого числа PHP |
Column::BIND_PARAM_BOOL |
Приведение значения как собственное логическое значение PHP |
Column::BIND_PARAM_DECIMAL |
Привести значение как собственный PHP-двойная |
Гидратация
Значения, возвращаемые из системы баз данных, всегда представляются PDO в виде строковых значений, независимо от того, принадлежит ли значение столбцу типа numeric
или boolean
. Это происходит потому, что некоторые типы столбцов не могут быть представлены соответствующими собственными типами PHP из-за их ограничений по размеру. Например, BIGINT
в MySQL может хранить большие целые числа, которые не могут быть представлены как 32-битное целое число в PHP. Поэтому PDO и ORM по умолчанию принимают безопасное решение оставить все значения в виде строк.
Вы можете настроить ORM для автоматического приведения этих типов к соответствующим собственным типам PHP:
<?php use Phalcon\Mvc\Model; Model::setup( [ 'castOnHydrate' => true, ] );
Таким образом, вы можете использовать строгие операторы или делать предположения о типе переменных:
<?php $invoice = Invoices::findFirst(); if (11 === $invoice->inv_id) { echo $invoice->inv_title; }
Таким образом, вы можете использовать строгие операторы или делать предположения о типе переменных:
<?php $invoice = Invoices::findFirst(); if (11 === $invoice->inv_id) { echo $invoice->inv_title; }
Примечание: Если вы хотите вернуть первичный ключ при использовании
lastInsertId
в качествеinteger
, вы можете использовать функциюcastLastInsertIdToInt => true
в модели.
Транзакции
Работа с транзакциями поддерживается так же, как и с PDO. Использование транзакций повышает производительность в большинстве систем баз данных, а также обеспечивает целостность данных:
<?php try { $connection->begin(); $connection->execute('DELETE `co_invoices` WHERE `inv_id` = 1'); $connection->execute('DELETE `co_invoices` WHERE `inv_id` = 2'); $connection->execute('DELETE `co_invoices` WHERE `inv_id` = 3'); $connection->commit(); } catch (Exception $e) { $connection->rollback(); }
В дополнение к стандартным транзакциям, адаптеры предлагают встроенную поддержку вложенных транзакций, если используемая система баз данных поддерживает их. При повторном вызове функции begin()
создается вложенная транзакция:
<?php try { $connection->begin(); $connection->execute('DELETE `co_invoices` WHERE `inv_id` = 1'); try { $connection->begin(); $connection->execute('DELETE `co_invoices` WHERE `inv_id` = 2'); $connection->execute('DELETE `co_invoices` WHERE `inv_id` = 3'); $connection->commit(); } catch (Exception $e) { $connection->rollback(); } $connection->execute('DELETE `co_invoices` WHERE `inv_id` = 4'); $connection->commit(); } catch (Exception $e) { // Произошло исключение откат транзакции $connection->rollback(); }
События
Адаптеры также отправляют события менеджеру событий, если он присутствует. Если событие возвращает false
, оно может остановить текущую операцию. Поддерживаются следующие события:
Имя события | Тригиры | Можно остановить |
---|---|---|
afterQuery |
После выполнения запроса | Нет |
beforeQuery |
Перед выполнением запроса | Да |
beginTransaction |
Прежде чем транзакция начинается | Нет |
createSavepoint |
Перед созданием точки сохранения | Нет |
commitTransaction |
Перед совершением транзакции | Нет |
releaseSavepoint |
Перед освобождением точки сохранения | Нет |
rollbackTransaction |
Прежде чем транзакция откатывается | Нет |
rollbackSavepoint |
Перед откатом точки сохранения | Нет |
Если вы свяжете Диспетчер событий с подключением к базе данных, все события с типом db
будут включены и запущены для соответствующих слушателей.
<?php use Phalcon\Events\Manager; use Phalcon\Db\Adapter\Pdo\Mysql; $manager = new Manager(); $manager->attach('db', $listener); $connection = new Mysql( [ 'host' => 'localhost', 'username' => 'root', 'password' => 'secret', 'dbname' => 'tutorial', ] ); $connection->setEventsManager($manager);
Вы можете использовать силу этих событий, чтобы защитить ваше приложение от опасных операций SQL.
<?php use Phalcon\Events\Event; $manager->attach( 'db:beforeQuery', function (Event $event, $connection) { $sql = $connection->getSQLStatement(); if (true === preg_match('/DROP|ALTER/i', $sql)) { return false; } return true; } );
<?php use Phalcon\Events\Event; $manager->attach( 'db:beforeQuery', function (Event $event, $connection) { $sql = $connection->getSQLStatement(); if (true === preg_match('/DROP|ALTER/i', $sql)) { return false; } return true; } );
Профилирование
Адаптер включает компонент Phalcon\Db\Profiler, который используется для анализа производительности операций с базами данных с целью диагностики проблем производительности и обнаружения узких мест.
<?php use Phalcon\Events\Event; use Phalcon\Events\Manager; use Phalcon\Db\Profiler; $manager = new Manager(); $profiler = new Profiler(); $manager->attach( 'db', function (Event $event, $connection) use ($profiler) { if ($event->getType() === 'beforeQuery') { $sql = $connection->getSQLStatement(); $profiler->startProfile($sql); } if ($event->getType() === 'afterQuery') { $profiler->stopProfile(); } } ); $connection->setEventsManager($manager); $sql = ' SELECT inv_id, inv_title FROM co_invoices '; $connection->query($sql); $profile = $profiler->getLastProfile(); echo 'SQL Statement: ', $profile->getSQLStatement(), PHP_EOL, 'Start Time: ', $profile->getInitialTime(), PHP_EOL, 'Final Time: ', $profile->getFinalTime(), PHP_EOL, 'Total Elapsed Time: ', $profile->getTotalElapsedSeconds(), PHP_EOL;
Вы также можете создать свой собственный класс профиля на основе класса Phalcon\Db\Profiler для записи статистики операторов в реальном времени, отправляемых в базу данных:
<?php use Phalcon\Events\Manager; use Phalcon\Db\Profiler; use Phalcon\Db\Profiler\Item; class DbProfiler extends Profiler { public function beforeStartProfile(Item $profile) { echo $profile->getSQLStatement(); } public function afterEndProfile(Item $profile) { echo $profile->getTotalElapsedSeconds(); } } $manager = new Manager(); $listener = new DbProfiler(); $manager->attach('db', $listener);
Регистрация
Использование высокоуровневых компонентов абстракции, таких как адаптеры Phalcon\Db
для доступа к базе данных, затрудняет понимание того, какие операторы отправляются в систему базы данных. Компонент Phalcon\Logger взаимодействует с адаптерами Phalcon\Db
, предлагая возможности ведения журнала на уровне абстракции базы данных.
<?php use Phalcon\Events\Event; use Phalcon\Events\Manager; use Phalcon\Logger; use Phalcon\Logger\Adapter\Stream; $adapter = new Stream('/storage/logs/queries.log'); $logger = new Logger( 'messages', [ 'main' => $adapter, ] ); $manager = new Manager(); $manager->attach( 'db:beforeQuery', function (Event $event, $connection) use ($logger) { $sql = $connection->getSQLStatement(); $logger->info( sprintf( '%s - [%s]', $connection->getSQLStatement(), json_encode($connection->getSQLVariables()) ) ); } ); $connection->setEventsManager($manager); $connection->insert( 'products', [ 'Hot pepper', 3.50, ], [ 'name', 'price', ] ); $connection->insert( 'co_invoices', [ 1, 'Invoice for ACME Inc.', ], [ 'inv_cst_id', 'inv_title', ] );
Как и выше, файл /storage/logs/queries.log
будет содержать что-то вроде этого:
[2019-12-25 01:02:03][INFO] INSERT INTO `co_invoices` SET (`inv_cst_id`, `inv_title`) VALUES (1, 'Invoice for ACME Inc.')
Слушатель также будет работать с моделями и их операциями. Он также будет включать все связанные параметры, используемые запросом в конце протоколируемой инструкции.
[2019-12-25 01:02:03][INFO] SELECT `co_customers`.`cst_id`, ..., FROM `co_customers` WHERE LOWER(`co_customers`.`cst_email`) = :cst_email LIMIT :APL0 - [{"emp_email":"team@phalcon.ld","APL0":1}]
Таблицы
Описание
Адаптеры Phalcon\Db
также предоставляют методы для получения подробной информации о таблицах и представлениях:
<?php $tables = $connection->listTables('gonano');
Получить таблицы в базе данных gonano
<?php $exists = $connection->tableExists('co_invoices');
Проверить, есть ли в базе данных таблица с именем co_invoices
?
<?php $fields = $connection->describeColumns('co_invoices'); foreach ($fields as $field) { echo 'Column Type: ', $field['Type']; }
Печать имени и типов данных таблицы co_invoices
<?php $indexes = $connection->describeIndexes('co_invoices'); foreach ($indexes as $index) { print_r( $index->getColumns() ); }
Печать индексов в таблице co_invoices
<?php $references = $connection->describeReferences('co_invoices'); foreach ($references as $reference) { print_r( $reference->getReferencedColumns() ); }
Печать внешних ключей в таблице co_invoices
Описание таблицы очень похоже на команду MySQL DESCRIBE
, она содержит следующую информацию:
Field | Type | Key | Null |
---|---|---|---|
Имя поля | тип столбца | Является ли столбец частью первичного ключа или индекса? | Допускает ли столбец нулевые значения? |
Методы получения информации о представлениях также реализованы для каждой поддерживаемой системы баз данных:
<?php $tables = $connection->listViews('gonano');
Получить представление о базе данных gonano
<?php $exists = $connection->viewExists('vw_invoices');
Check if there is a view vw_invoices
in the database
Создавать
Различные системы баз данных (MySQL, Postgresql и др.) возможность создавать, изменять или удалять таблицы с помощью таких команд, как CREATE
, ALTER
или DROP
. Синтаксис SQL отличается в зависимости от того, какая система баз данных используется. Phalcon\Db
adapters предлагает унифицированный интерфейс для изменения таблиц, без необходимости дифференцировать синтаксис SQL на основе целевой системы хранения.
<?php use \Phalcon\Db\Column as Column; $connection->createTable( 'co_invoices', null, [ 'columns' => [ new Column( 'inv_id', [ 'type' => Column::TYPE_INTEGER, 'size' => 10, 'notNull' => true, 'autoIncrement' => true, 'primary' => true, ] ), new Column( 'inv_cst_id', [ 'type' => Column::TYPE_INTEGER, 'size' => 11, 'notNull' => true, ] ), new Column( 'inv_title', [ 'type' => Column::TYPE_VARCHAR, 'size' => 100, 'notNull' => true, ] ), ] ] );
Метод createTable
принимает ассоциативный массив, описывающий таблицу. Столбцы определяются с помощью класса Phalcon\Db\Column. В таблице ниже приведены параметры, доступные для определения столбца:
Вариант | Описание | Необязательный |
---|---|---|
after |
Столбец должен быть размещен после указанного столбца | Да |
autoIncrement |
Укажите, будет ли этот столбец автоматически приращен базой данных. Только один столбец в таблице может иметь этот атрибут. | Да |
bind |
Одна из констант BIND_TYPE_ * , указывающая, как столбец должен быть привязан перед сохранением |
Да |
default |
Значение по умолчанию (при использовании с 'notNull' => true ). |
Да |
first |
Столбец должен быть помещен в первую позицию порядка столбцов | Да |
notNull |
Столбец может хранить значения NULL | Да |
primary |
true Если столбец является частью первичного ключа таблицы |
Да |
scale |
Столбцы DECIMAL или NUMBER могут иметь масштаб, указывающий, сколько десятичных знаков должно храниться |
Да |
size |
Некоторые типы столбцов, такие как VARCHAR или INTEGER , могут иметь определенный размер |
Да |
type |
Тип колонки. Должна быть константой Phalcon\Db\Column (список см. ниже) | Нет |
unsigned |
Столбцы INTEGER могут быть signed или unsigned . Этот параметр не применяется к столбцам других типов |
Да |
Адаптеры поддерживают следующие типы столбцов базы данных:
Phalcon\Db\Column::TYPE_INTEGER
Phalcon\Db\Column::TYPE_DATE
Phalcon\Db\Column::TYPE_VARCHAR
Phalcon\Db\Column::TYPE_DECIMAL
Phalcon\Db\Column::TYPE_DATETIME
Phalcon\Db\Column::TYPE_CHAR
Phalcon\Db\Column::TYPE_TEXT
Ассоциативный массив, переданный в createTable ()
, может иметь следующие ключи:
Индекс | Описание | Необязательный |
---|---|---|
columns |
Массив со столбцами, определенными с помощью Phalcon\Db\Column | Нет |
indexes |
Массив с индексами, определенными с помощью Phalcon\Db\Index | Да |
references |
Массив со ссылками (внешними ключами), определенный с помощью Phalcon\Db\Reference | Да |
options |
Массив с опциями создания. (Для системы базы данных) | Да |
Изменять
По мере роста приложения может потребоваться изменить базу данных в рамках рефакторинга или добавления новых функций. Не все системы баз данных позволяют изменять существующие столбцы или добавлять столбцы между двумя существующими. Phalcon\Db\Column ограничен этими ограничениями.
Ниже приведен пример создания таблицы:
<?php use Phalcon\Db\Column as Column; $connection->addColumn( 'co_invoices', null, new Column( 'inv_status_flag', [ 'type' => Column::TYPE_INTEGER, 'size' => 1, 'notNull' => true, 'default' => 0, 'after' => 'inv_cst_id', ] ) ); $connection->modifyColumn( 'co_invoices', null, new Column( 'inv_status_flag', [ 'type' => Column::TYPE_INTEGER, 'size' => 2, 'notNull' => true, ] ) ); $connection->dropColumn( 'co_invoices', null, 'inv_status_flag' );
Удаление
Чтобы удалить существующую таблицу из текущей базы данных, используйте метод dropTable
. Чтобы удалить таблицу из пользовательской базы данных, можно использовать второй параметр для задания имени базы данных.
<?php $connection->dropTable('co_invoices');
Удаление таблицы co_invoices
из активной базы данных
<?php $connection->dropTable('co_invoices', 'gonano');
Удалить таблицу co_invoices
из базы данных gonano