From 7f39c5d784715bf1991ccfcc16e90eff5561c530 Mon Sep 17 00:00:00 2001 From: laminas-bot Date: Thu, 1 Feb 2024 18:56:16 +0000 Subject: [PATCH] Automated deployment: Thu Feb 1 18:56:16 UTC 2024 2.19.0 --- adapter/index.html | 31 ++++++++++------ adapters/adapter-aware-trait/index.html | 31 ++++++++++------ .../index.html | 29 +++++++++------ index.html | 33 +++++++++++------- metadata/index.html | 31 ++++++++++------ pages/404.html | 24 ++++++++----- result-set/index.html | 31 ++++++++++------ row-gateway/index.html | 31 ++++++++++------ search/lunr.js | 2 +- search/main.js | 9 ++++- search/search_index.json | 2 +- sitemap.xml | 20 +++++------ sitemap.xml.gz | Bin 309 -> 310 bytes sql-ddl/index.html | 33 ++++++++++++------ sql/index.html | 31 ++++++++++------ table-gateway/index.html | 31 ++++++++++------ 16 files changed, 245 insertions(+), 124 deletions(-) diff --git a/adapter/index.html b/adapter/index.html index 5ec7f631..57beb19a 100644 --- a/adapter/index.html +++ b/adapter/index.html @@ -5,7 +5,14 @@ - + + + + + + + + @@ -303,8 +310,8 @@

Search - - GitHub + + GitHub @@ -858,7 +865,9 @@

Examples

@@ -867,7 +876,9 @@

Examples

@@ -1086,13 +1097,13 @@
  • - +
  • - +
  • - +
  • @@ -1108,7 +1119,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -1118,7 +1129,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.

    diff --git a/adapters/adapter-aware-trait/index.html b/adapters/adapter-aware-trait/index.html index 3d28defd..78478be0 100644 --- a/adapters/adapter-aware-trait/index.html +++ b/adapters/adapter-aware-trait/index.html @@ -5,7 +5,14 @@ - + + + + + + + + @@ -303,8 +310,8 @@

    Search - - GitHub + + GitHub @@ -486,7 +493,9 @@

    Concrete Implementations

  • @@ -495,7 +504,9 @@

    Concrete Implementations

    @@ -714,13 +725,13 @@
  • - +
  • - +
  • - +
  • @@ -736,7 +747,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -746,7 +757,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.

    diff --git a/application-integration/usage-in-a-laminas-mvc-application/index.html b/application-integration/usage-in-a-laminas-mvc-application/index.html index 34af6ba5..4a86fd14 100644 --- a/application-integration/usage-in-a-laminas-mvc-application/index.html +++ b/application-integration/usage-in-a-laminas-mvc-application/index.html @@ -5,7 +5,14 @@ - + + + + + + + + @@ -303,8 +310,8 @@

    Search - - GitHub + + GitHub @@ -393,7 +400,7 @@

    Usage in a laminas-mvc ApplicationWhen installing the Laminas MVC Skeleton Application

    While Composer is installing the MVC Application, you can add the laminas-db package while prompted.

    Adding to an existing Laminas MVC Skeleton Application

    -

    If the MVC application is already created, then use Composer to add the laminas-db package.

    +

    If the MVC application is already created, then use Composer to add the laminas-db package.

    The Abstract Factory

    Now that the laminas-db package is installed, the abstract factory Laminas\Db\Adapter\AdapterAbstractServiceFactory is available to be used with the service configuration.

    Configuring the adapter

    @@ -553,7 +560,9 @@

    Initiating the database schemas

  • @@ -777,13 +786,13 @@
  • - +
  • - +
  • - +
  • @@ -799,7 +808,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -809,7 +818,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.

    diff --git a/index.html b/index.html index 92b98636..31556542 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,14 @@ - + + + + + + + + @@ -303,8 +310,8 @@

    Search - - GitHub + + GitHub @@ -349,7 +356,7 @@

    Using Composer

    Support

    @@ -369,7 +376,9 @@

    Support

  • @@ -588,13 +597,13 @@
  • - +
  • - +
  • - +
  • @@ -610,7 +619,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -620,7 +629,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.

    @@ -667,6 +676,6 @@ diff --git a/metadata/index.html b/metadata/index.html index 34e20516..ce7a5cde 100644 --- a/metadata/index.html +++ b/metadata/index.html @@ -5,7 +5,14 @@ - + + + + + + + + @@ -303,8 +310,8 @@

    Search - - GitHub + + GitHub @@ -580,7 +587,9 @@

    TriggerObject

  • @@ -589,7 +598,9 @@

    TriggerObject

    @@ -808,13 +819,13 @@
  • - +
  • - +
  • - +
  • @@ -830,7 +841,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -840,7 +851,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.

    diff --git a/pages/404.html b/pages/404.html index 02854eae..ded7ca7c 100644 --- a/pages/404.html +++ b/pages/404.html @@ -5,7 +5,15 @@ - + + + + + + + + + laminas-db - Laminas Docs @@ -302,8 +310,8 @@

    Search - - GitHub + + GitHub @@ -542,13 +550,13 @@

  • - +
  • - +
  • - +
  • @@ -564,7 +572,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -574,7 +582,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.

    diff --git a/result-set/index.html b/result-set/index.html index 2d37412c..9be68749 100644 --- a/result-set/index.html +++ b/result-set/index.html @@ -5,7 +5,14 @@ - + + + + + + + + @@ -303,8 +310,8 @@

    Search - - GitHub + + GitHub @@ -512,7 +519,9 @@

    Laminas\Db\ResultSet\HydratingResu @@ -521,7 +530,9 @@

    Laminas\Db\ResultSet\HydratingResu @@ -740,13 +751,13 @@

  • - +
  • - +
  • - +
  • @@ -762,7 +773,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -772,7 +783,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.

    diff --git a/row-gateway/index.html b/row-gateway/index.html index 586be6f2..9f2479ba 100644 --- a/row-gateway/index.html +++ b/row-gateway/index.html @@ -5,7 +5,14 @@ - + + + + + + + + @@ -303,8 +310,8 @@

    Search - - GitHub + + GitHub @@ -455,7 +462,9 @@

    ActiveRecord Style Objects

  • @@ -464,7 +473,9 @@

    ActiveRecord Style Objects

    @@ -683,13 +694,13 @@
  • - +
  • - +
  • - +
  • @@ -705,7 +716,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -715,7 +726,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.

    diff --git a/search/lunr.js b/search/lunr.js index 6aa370fb..aca0a167 100644 --- a/search/lunr.js +++ b/search/lunr.js @@ -3456,7 +3456,7 @@ lunr.QueryParser.parseBoost = function (parser) { } else if (typeof exports === 'object') { /** * Node. Does not work with strict CommonJS, but - * only CommonJS-like enviroments that support module.exports, + * only CommonJS-like environments that support module.exports, * like Node. */ module.exports = factory() diff --git a/search/main.js b/search/main.js index c5ccfa61..a5e469d7 100644 --- a/search/main.js +++ b/search/main.js @@ -21,8 +21,15 @@ function joinUrl (base, path) { return base + "/" + path; } +function escapeHtml (value) { + return value.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); +} + function formatResult (location, title, summary) { - return ''; + return ''; } function displayResults (results) { diff --git a/search/search_index.json b/search/search_index.json index 365c2f94..7c06a846 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"laminas-db Laminas\\Db is a component that abstract the access to a Database using an object oriented API to build the queries. Laminas\\Db consumes different storage adapters to access different database vendors such as MySQL, PostgreSQL, Oracle, IBM DB2, Microsoft Sql Server, PDO, etc. Contributing Please be sure to read the contributor's guide for general information on contributing. This section outlines specifics for laminas-db. Test suites The phpunit.xml.dist file defines two test suites, \"unit test\" and \"integration test\". You can run one or the other using the --testsuite option to phpunit : $ ./vendor/bin/phpunit --testsuite \"unit test\" # unit tests only $ ./vendor/bin/phpunit --testsuite \"integration test\" # integration tests only Unit tests do not require additional functionality beyond having the appropriate database extensions present and loaded in your PHP binary. Integration tests To run the integration tests, you need databases. The repository includes a Vagrantfile which allows you to fire up a vagrant box with several of our target databases, including: MySQL PostgreSQL SQL Server To start up vagrant: $ vagrant up Copy phpunit.xml.dist to phpunit.xml , and change the following ENV var declaration values to \"true\": TESTS_LAMINAS_DB_ADAPTER_DRIVER_MYSQL TESTS_LAMINAS_DB_ADAPTER_DRIVER_SQLSRV TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL TESTS_LAMINAS_DB_ADAPTER_DRIVER_SQLITE_MEMORY From there, you can run the integration tests: $ ./vendor/bin/phpunit --testsuite \"integration test\" File issues at https://github.com/laminas/laminas-db/issues Documentation is at https://docs.laminas.dev/laminas-db/","title":"Home"},{"location":"#laminas-db","text":"Laminas\\Db is a component that abstract the access to a Database using an object oriented API to build the queries. Laminas\\Db consumes different storage adapters to access different database vendors such as MySQL, PostgreSQL, Oracle, IBM DB2, Microsoft Sql Server, PDO, etc.","title":"laminas-db"},{"location":"#contributing","text":"Please be sure to read the contributor's guide for general information on contributing. This section outlines specifics for laminas-db.","title":"Contributing"},{"location":"adapter/","text":"Adapters Laminas\\Db\\Adapter\\Adapter is the central object of the laminas-db component. It is responsible for adapting any code written in or for laminas-db to the targeted PHP extensions and vendor databases. In doing this, it creates an abstraction layer for the PHP extensions in the Driver subnamespace of Laminas\\Db\\Adapter . It also creates a lightweight \"Platform\" abstraction layer, for the various idiosyncrasies that each vendor-specific platform might have in its SQL/RDBMS implementation, separate from the driver implementations. Creating an adapter using configuration Create an adapter by instantiating the Laminas\\Db\\Adapter\\Adapter class. The most common use case, while not the most explicit, is to pass an array of configuration to the Adapter : use Laminas\\Db\\Adapter\\Adapter; $adapter = new Adapter($configArray); This driver array is an abstraction for the extension level required parameters. Here is a table for the key-value pairs that should be in configuration array. Key Is Required? Value driver required Mysqli , Sqlsrv , Pdo_Sqlite , Pdo_Mysql , Pdo (= Other PDO Driver) database generally required the name of the database (schema) username generally required the connection username password generally required the connection password hostname not generally required the IP address or hostname to connect to port not generally required the port to connect to (if applicable) charset not generally required the character set to use Options are adapter-dependent Other names will work as well. Effectively, if the PHP manual uses a particular naming, this naming will be supported by the associated driver. For example, dbname in most cases will also work for 'database'. Another example is that in the case of Sqlsrv , UID will work in place of username . Which format you choose is up to you, but the above table represents the official abstraction names. For example, a MySQL connection using ext/mysqli: $adapter = new Laminas\\Db\\Adapter\\Adapter([ 'driver' => 'Mysqli', 'database' => 'laminas_db_example', 'username' => 'developer', 'password' => 'developer-password', ]); Another example, of a Sqlite connection via PDO: $adapter = new Laminas\\Db\\Adapter\\Adapter([ 'driver' => 'Pdo_Sqlite', 'database' => 'path/to/sqlite.db', ]); Another example, of an IBM i DB2 connection via IbmDb2: $adapter = new Laminas\\Db\\Adapter\\Adapter([ 'database' => '*LOCAL', // or name from WRKRDBDIRE, may be serial # 'driver' => 'IbmDb2', 'driver_options' => [ 'autocommit' => DB2_AUTOCOMMIT_ON, 'i5_naming' => DB2_I5_NAMING_ON, 'i5_libl' => 'SCHEMA1 SCHEMA2 SCHEMA3', ], 'username' => '__USER__', 'password' => '__PASS__', // 'persistent' => true, 'platform' => 'IbmDb2', 'platform_options' => ['quote_identifiers' => false], ]); Another example, of an IBM i DB2 connection via PDO: $adapter = new Laminas\\Db\\Adapter\\Adapter([ 'dsn' => 'ibm:DB_NAME', // DB_NAME is from WRKRDBDIRE, may be serial # 'driver' => 'pdo', 'driver_options' => [ // PDO::ATTR_PERSISTENT => true, PDO::ATTR_AUTOCOMMIT => true, PDO::I5_ATTR_DBC_SYS_NAMING => true, PDO::I5_ATTR_DBC_CURLIB => '', PDO::I5_ATTR_DBC_LIBL => 'SCHEMA1 SCHEMA2 SCHEMA3', ], 'username' => '__USER__', 'password' => '__PASS__', 'platform' => 'IbmDb2', 'platform_options' => ['quote_identifiers' => false], ]); It is important to know that by using this style of adapter creation, the Adapter will attempt to create any dependencies that were not explicitly provided. A Driver object will be created from the configuration array provided in the constructor. A Platform object will be created based off the type of Driver class that was instantiated. And lastly, a default ResultSet object is created and utilized. Any of these objects can be injected, to do this, see the next section. The list of officially supported drivers: IbmDb2 : The ext/ibm_db2 driver Mysqli : The ext/mysqli driver Oci8 : The ext/oci8 driver Pgsql : The ext/pgsql driver Sqlsrv : The ext/sqlsrv driver (from Microsoft) Pdo_Mysql : MySQL via the PDO extension Pdo_Sqlite : SQLite via the PDO extension Pdo_Pgsql : PostgreSQL via the PDO extension Creating an adapter using dependency injection The more mezzio and explicit way of creating an adapter is by injecting all your dependencies up front. Laminas\\Db\\Adapter\\Adapter uses constructor injection, and all required dependencies are injected through the constructor, which has the following signature (in pseudo-code): use Laminas\\Db\\Adapter\\Platform\\PlatformInterface; use Laminas\\Db\\ResultSet\\ResultSet; class Laminas\\Db\\Adapter\\Adapter { public function __construct( $driver, PlatformInterface $platform = null, ResultSet $queryResultSetPrototype = null ); } What can be injected: $driver : an array of connection parameters (see above) or an instance of Laminas\\Db\\Adapter\\Driver\\DriverInterface . $platform (optional): an instance of Laminas\\Db\\Platform\\PlatformInterface ; the default will be created based off the driver implementation. $queryResultSetPrototype (optional): an instance of Laminas\\Db\\ResultSet\\ResultSet ; to understand this object's role, see the section below on querying. Query Preparation By default, Laminas\\Db\\Adapter\\Adapter::query() prefers that you use \"preparation\" as a means for processing SQL statements. This generally means that you will supply a SQL statement containing placeholders for the values, and separately provide substitutions for those placeholders. As an example: $adapter->query('SELECT * FROM `artist` WHERE `id` = ?', [5]); The above example will go through the following steps: create a new Statement object. prepare the array [5] into a ParameterContainer if necessary. inject the ParameterContainer into the Statement object. execute the Statement object, producing a Result object. check the Result object to check if the supplied SQL was a result set producing statement: if the query produced a result set, clone the ResultSet prototype, inject the Result as its datasource, and return the new ResultSet instance. otherwise, return the Result . Query Execution In some cases, you have to execute statements directly without preparation. One possible reason for doing so would be to execute a DDL statement, as most extensions and RDBMS systems are incapable of preparing such statements. To execute a query without the preparation step, you will need to pass a flag as the second argument indicating execution is required: $adapter->query( 'ALTER TABLE ADD INDEX(`foo_index`) ON (`foo_column`)', Adapter::QUERY_MODE_EXECUTE ); The primary difference to notice is that you must provide the Adapter::QUERY_MODE_EXECUTE (execute) flag as the second parameter. Creating Statements While query() is highly useful for one-off and quick querying of a database via the Adapter , it generally makes more sense to create a statement and interact with it directly, so that you have greater control over the prepare-then-execute workflow. To do this, Adapter gives you a routine called createStatement() that allows you to create a Driver specific Statement to use so you can manage your own prepare-then-execute workflow. // with optional parameters to bind up-front: $statement = $adapter->createStatement($sql, $optionalParameters); $result = $statement->execute(); Using the Driver Object The Driver object is the primary place where Laminas\\Db\\Adapter\\Adapter implements the connection level abstraction specific to a given extension. To make this possible, each driver is composed of 3 objects: A connection: Laminas\\Db\\Adapter\\Driver\\ConnectionInterface A statement: Laminas\\Db\\Adapter\\Driver\\StatementInterface A result: Laminas\\Db\\Adapter\\Driver\\ResultInterface Each of the built-in drivers practice \"prototyping\" as a means of creating objects when new instances are requested. The workflow looks like this: An adapter is created with a set of connection parameters. The adapter chooses the proper driver to instantiate (for example, Laminas\\Db\\Adapter\\Driver\\Mysqli ) That driver class is instantiated. If no connection, statement, or result objects are injected, defaults are instantiated. This driver is now ready to be called on when particular workflows are requested. Here is what the Driver API looks like: namespace Laminas\\Db\\Adapter\\Driver; interface DriverInterface { const PARAMETERIZATION_POSITIONAL = 'positional'; const PARAMETERIZATION_NAMED = 'named'; const NAME_FORMAT_CAMELCASE = 'camelCase'; const NAME_FORMAT_NATURAL = 'natural'; public function getDatabasePlatformName(string $nameFormat = self::NAME_FORMAT_CAMELCASE) : string; public function checkEnvironment() : bool; public function getConnection() : ConnectionInterface; public function createStatement(string|resource $sqlOrResource = null) : StatementInterface; public function createResult(resource $resource) : ResultInterface; public function getPrepareType() :string; public function formatParameterName(string $name, $type = null) : string; public function getLastGeneratedValue() : mixed; } From this DriverInterface , you can Determine the name of the platform this driver supports (useful for choosing the proper platform object). Check that the environment can support this driver. Return the Connection instance. Create a Statement instance which is optionally seeded by an SQL statement (this will generally be a clone of a prototypical statement object). Create a Result object which is optionally seeded by a statement resource (this will generally be a clone of a prototypical result object) Format parameter names; this is important to distinguish the difference between the various ways parameters are named between extensions Retrieve the overall last generated value (such as an auto-increment value). Now let's turn to the Statement API: namespace Laminas\\Db\\Adapter\\Driver; interface StatementInterface extends StatementContainerInterface { public function getResource() : resource; public function prepare($sql = null) : void; public function isPrepared() : bool; public function execute(null|array|ParameterContainer $parameters = null) : ResultInterface; /** Inherited from StatementContainerInterface */ public function setSql(string $sql) : void; public function getSql() : string; public function setParameterContainer(ParameterContainer $parameterContainer) : void; public function getParameterContainer() : ParameterContainer; } And finally, the Result API: namespace Laminas\\Db\\Adapter\\Driver; use Countable; use Iterator; interface ResultInterface extends Countable, Iterator { public function buffer() : void; public function isQueryResult() : bool; public function getAffectedRows() : int; public function getGeneratedValue() : mixed; public function getResource() : resource; public function getFieldCount() : int; } Using The Platform Object The Platform object provides an API to assist in crafting queries in a way that is specific to the SQL implementation of a particular vendor. The object handles nuances such as how identifiers or values are quoted, or what the identifier separator character is. To get an idea of the capabilities, the interface for a platform object looks like this: namespace Laminas\\Db\\Adapter\\Platform; interface PlatformInterface { public function getName() : string; public function getQuoteIdentifierSymbol() : string; public function quoteIdentifier(string $identifier) : string; public function quoteIdentifierChain(string|string[] $identiferChain) : string; public function getQuoteValueSymbol() : string; public function quoteValue(string $value) : string; public function quoteTrustedValue(string $value) : string; public function quoteValueList(string|string[] $valueList) : string; public function getIdentifierSeparator() : string; public function quoteIdentifierInFragment(string $identifier, array $additionalSafeWords = []) : string; } While you can directly instantiate a Platform object, generally speaking, it is easier to get the proper Platform instance from the configured adapter (by default the Platform type will match the underlying driver implementation): $platform = $adapter->getPlatform(); // or $platform = $adapter->platform; // magic property access The following are examples of Platform usage: // $adapter is a Laminas\\Db\\Adapter\\Adapter instance; // $platform is a Laminas\\Db\\Adapter\\Platform\\Sql92 instance. $platform = $adapter->getPlatform(); // \"first_name\" echo $platform->quoteIdentifier('first_name'); // \" echo $platform->getQuoteIdentifierSymbol(); // \"schema\".\"mytable\" echo $platform->quoteIdentifierChain(['schema', 'mytable']); // ' echo $platform->getQuoteValueSymbol(); // 'myvalue' echo $platform->quoteValue('myvalue'); // 'value', 'Foo O\\\\'Bar' echo $platform->quoteValueList(['value', \"Foo O'Bar\"]); // . echo $platform->getIdentifierSeparator(); // \"foo\" as \"bar\" echo $platform->quoteIdentifierInFragment('foo as bar'); // additionally, with some safe words: // (\"foo\".\"bar\" = \"boo\".\"baz\") echo $platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', ['(', ')', '=']); Using The Parameter Container The ParameterContainer object is a container for the various parameters that need to be passed into a Statement object to fulfill all the various parameterized parts of the SQL statement. This object implements the ArrayAccess interface. Below is the ParameterContainer API: namespace Laminas\\Db\\Adapter; use ArrayAccess; use ArrayIterator; use Countable; use Iterator; class ParameterContainer implements Iterator, ArrayAccess, Countable { public function __construct(array $data = []) /** methods to interact with values */ public function offsetExists(string|int $name) : bool; public function offsetGet(string|int $name) : mixed; public function offsetSetReference(string|int $name, string|int $from) : void; public function offsetSet(string|int $name, mixed $value, mixed $errata = null, int $maxLength = null) : void; public function offsetUnset(string|int $name) : void; /** set values from array (will reset first) */ public function setFromArray(array $data) : ParameterContainer; /** methods to interact with value errata */ public function offsetSetErrata(string|int $name, mixed $errata) : void; public function offsetGetErrata(string|int $name) : mixed; public function offsetHasErrata(string|int $name) : bool; public function offsetUnsetErrata(string|int $name) : void; /** errata only iterator */ public function getErrataIterator() : ArrayIterator; /** get array with named keys */ public function getNamedArray() : array; /** get array with int keys, ordered by position */ public function getPositionalArray() : array; /** iterator: */ public function count() : int; public function current() : mixed; public function next() : mixed; public function key() : string|int; public function valid() : bool; public function rewind() : void; /** merge existing array of parameters with existing parameters */ public function merge(array $parameters) : ParameterContainer; } In addition to handling parameter names and values, the container will assist in tracking parameter types for PHP type to SQL type handling. For example, it might be important that: $container->offsetSet('limit', 5); be bound as an integer. To achieve this, pass in the ParameterContainer::TYPE_INTEGER constant as the 3rd parameter: $container->offsetSet('limit', 5, $container::TYPE_INTEGER); This will ensure that if the underlying driver supports typing of bound parameters, that this translated information will also be passed along to the actual php database driver. Examples Creating a Driver , a vendor-portable query, and preparing and iterating the result: $adapter = new Laminas\\Db\\Adapter\\Adapter($driverConfig); $qi = function ($name) use ($adapter) { return $adapter->platform->quoteIdentifier($name); }; $fp = function ($name) use ($adapter) { return $adapter->driver->formatParameterName($name); }; $sql = 'UPDATE ' . $qi('artist') . ' SET ' . $qi('name') . ' = ' . $fp('name') . ' WHERE ' . $qi('id') . ' = ' . $fp('id'); $statement = $adapter->query($sql); $parameters = [ 'name' => 'Updated Artist', 'id' => 1, ]; $statement->execute($parameters); // DATA INSERTED, NOW CHECK $statement = $adapter->query( 'SELECT * FROM ' . $qi('artist') . ' WHERE id = ' . $fp('id') ); $results = $statement->execute(['id' => 1]); $row = $results->current(); $name = $row['name'];","title":"Introduction"},{"location":"adapter/#adapters","text":"Laminas\\Db\\Adapter\\Adapter is the central object of the laminas-db component. It is responsible for adapting any code written in or for laminas-db to the targeted PHP extensions and vendor databases. In doing this, it creates an abstraction layer for the PHP extensions in the Driver subnamespace of Laminas\\Db\\Adapter . It also creates a lightweight \"Platform\" abstraction layer, for the various idiosyncrasies that each vendor-specific platform might have in its SQL/RDBMS implementation, separate from the driver implementations.","title":"Adapters"},{"location":"adapter/#creating-an-adapter-using-configuration","text":"Create an adapter by instantiating the Laminas\\Db\\Adapter\\Adapter class. The most common use case, while not the most explicit, is to pass an array of configuration to the Adapter : use Laminas\\Db\\Adapter\\Adapter; $adapter = new Adapter($configArray); This driver array is an abstraction for the extension level required parameters. Here is a table for the key-value pairs that should be in configuration array. Key Is Required? Value driver required Mysqli , Sqlsrv , Pdo_Sqlite , Pdo_Mysql , Pdo (= Other PDO Driver) database generally required the name of the database (schema) username generally required the connection username password generally required the connection password hostname not generally required the IP address or hostname to connect to port not generally required the port to connect to (if applicable) charset not generally required the character set to use","title":"Creating an adapter using configuration"},{"location":"adapter/#creating-an-adapter-using-dependency-injection","text":"The more mezzio and explicit way of creating an adapter is by injecting all your dependencies up front. Laminas\\Db\\Adapter\\Adapter uses constructor injection, and all required dependencies are injected through the constructor, which has the following signature (in pseudo-code): use Laminas\\Db\\Adapter\\Platform\\PlatformInterface; use Laminas\\Db\\ResultSet\\ResultSet; class Laminas\\Db\\Adapter\\Adapter { public function __construct( $driver, PlatformInterface $platform = null, ResultSet $queryResultSetPrototype = null ); } What can be injected: $driver : an array of connection parameters (see above) or an instance of Laminas\\Db\\Adapter\\Driver\\DriverInterface . $platform (optional): an instance of Laminas\\Db\\Platform\\PlatformInterface ; the default will be created based off the driver implementation. $queryResultSetPrototype (optional): an instance of Laminas\\Db\\ResultSet\\ResultSet ; to understand this object's role, see the section below on querying.","title":"Creating an adapter using dependency injection"},{"location":"adapter/#query-preparation","text":"By default, Laminas\\Db\\Adapter\\Adapter::query() prefers that you use \"preparation\" as a means for processing SQL statements. This generally means that you will supply a SQL statement containing placeholders for the values, and separately provide substitutions for those placeholders. As an example: $adapter->query('SELECT * FROM `artist` WHERE `id` = ?', [5]); The above example will go through the following steps: create a new Statement object. prepare the array [5] into a ParameterContainer if necessary. inject the ParameterContainer into the Statement object. execute the Statement object, producing a Result object. check the Result object to check if the supplied SQL was a result set producing statement: if the query produced a result set, clone the ResultSet prototype, inject the Result as its datasource, and return the new ResultSet instance. otherwise, return the Result .","title":"Query Preparation"},{"location":"adapter/#query-execution","text":"In some cases, you have to execute statements directly without preparation. One possible reason for doing so would be to execute a DDL statement, as most extensions and RDBMS systems are incapable of preparing such statements. To execute a query without the preparation step, you will need to pass a flag as the second argument indicating execution is required: $adapter->query( 'ALTER TABLE ADD INDEX(`foo_index`) ON (`foo_column`)', Adapter::QUERY_MODE_EXECUTE ); The primary difference to notice is that you must provide the Adapter::QUERY_MODE_EXECUTE (execute) flag as the second parameter.","title":"Query Execution"},{"location":"adapter/#creating-statements","text":"While query() is highly useful for one-off and quick querying of a database via the Adapter , it generally makes more sense to create a statement and interact with it directly, so that you have greater control over the prepare-then-execute workflow. To do this, Adapter gives you a routine called createStatement() that allows you to create a Driver specific Statement to use so you can manage your own prepare-then-execute workflow. // with optional parameters to bind up-front: $statement = $adapter->createStatement($sql, $optionalParameters); $result = $statement->execute();","title":"Creating Statements"},{"location":"adapter/#using-the-driver-object","text":"The Driver object is the primary place where Laminas\\Db\\Adapter\\Adapter implements the connection level abstraction specific to a given extension. To make this possible, each driver is composed of 3 objects: A connection: Laminas\\Db\\Adapter\\Driver\\ConnectionInterface A statement: Laminas\\Db\\Adapter\\Driver\\StatementInterface A result: Laminas\\Db\\Adapter\\Driver\\ResultInterface Each of the built-in drivers practice \"prototyping\" as a means of creating objects when new instances are requested. The workflow looks like this: An adapter is created with a set of connection parameters. The adapter chooses the proper driver to instantiate (for example, Laminas\\Db\\Adapter\\Driver\\Mysqli ) That driver class is instantiated. If no connection, statement, or result objects are injected, defaults are instantiated. This driver is now ready to be called on when particular workflows are requested. Here is what the Driver API looks like: namespace Laminas\\Db\\Adapter\\Driver; interface DriverInterface { const PARAMETERIZATION_POSITIONAL = 'positional'; const PARAMETERIZATION_NAMED = 'named'; const NAME_FORMAT_CAMELCASE = 'camelCase'; const NAME_FORMAT_NATURAL = 'natural'; public function getDatabasePlatformName(string $nameFormat = self::NAME_FORMAT_CAMELCASE) : string; public function checkEnvironment() : bool; public function getConnection() : ConnectionInterface; public function createStatement(string|resource $sqlOrResource = null) : StatementInterface; public function createResult(resource $resource) : ResultInterface; public function getPrepareType() :string; public function formatParameterName(string $name, $type = null) : string; public function getLastGeneratedValue() : mixed; } From this DriverInterface , you can Determine the name of the platform this driver supports (useful for choosing the proper platform object). Check that the environment can support this driver. Return the Connection instance. Create a Statement instance which is optionally seeded by an SQL statement (this will generally be a clone of a prototypical statement object). Create a Result object which is optionally seeded by a statement resource (this will generally be a clone of a prototypical result object) Format parameter names; this is important to distinguish the difference between the various ways parameters are named between extensions Retrieve the overall last generated value (such as an auto-increment value). Now let's turn to the Statement API: namespace Laminas\\Db\\Adapter\\Driver; interface StatementInterface extends StatementContainerInterface { public function getResource() : resource; public function prepare($sql = null) : void; public function isPrepared() : bool; public function execute(null|array|ParameterContainer $parameters = null) : ResultInterface; /** Inherited from StatementContainerInterface */ public function setSql(string $sql) : void; public function getSql() : string; public function setParameterContainer(ParameterContainer $parameterContainer) : void; public function getParameterContainer() : ParameterContainer; } And finally, the Result API: namespace Laminas\\Db\\Adapter\\Driver; use Countable; use Iterator; interface ResultInterface extends Countable, Iterator { public function buffer() : void; public function isQueryResult() : bool; public function getAffectedRows() : int; public function getGeneratedValue() : mixed; public function getResource() : resource; public function getFieldCount() : int; }","title":"Using the Driver Object"},{"location":"adapter/#using-the-platform-object","text":"The Platform object provides an API to assist in crafting queries in a way that is specific to the SQL implementation of a particular vendor. The object handles nuances such as how identifiers or values are quoted, or what the identifier separator character is. To get an idea of the capabilities, the interface for a platform object looks like this: namespace Laminas\\Db\\Adapter\\Platform; interface PlatformInterface { public function getName() : string; public function getQuoteIdentifierSymbol() : string; public function quoteIdentifier(string $identifier) : string; public function quoteIdentifierChain(string|string[] $identiferChain) : string; public function getQuoteValueSymbol() : string; public function quoteValue(string $value) : string; public function quoteTrustedValue(string $value) : string; public function quoteValueList(string|string[] $valueList) : string; public function getIdentifierSeparator() : string; public function quoteIdentifierInFragment(string $identifier, array $additionalSafeWords = []) : string; } While you can directly instantiate a Platform object, generally speaking, it is easier to get the proper Platform instance from the configured adapter (by default the Platform type will match the underlying driver implementation): $platform = $adapter->getPlatform(); // or $platform = $adapter->platform; // magic property access The following are examples of Platform usage: // $adapter is a Laminas\\Db\\Adapter\\Adapter instance; // $platform is a Laminas\\Db\\Adapter\\Platform\\Sql92 instance. $platform = $adapter->getPlatform(); // \"first_name\" echo $platform->quoteIdentifier('first_name'); // \" echo $platform->getQuoteIdentifierSymbol(); // \"schema\".\"mytable\" echo $platform->quoteIdentifierChain(['schema', 'mytable']); // ' echo $platform->getQuoteValueSymbol(); // 'myvalue' echo $platform->quoteValue('myvalue'); // 'value', 'Foo O\\\\'Bar' echo $platform->quoteValueList(['value', \"Foo O'Bar\"]); // . echo $platform->getIdentifierSeparator(); // \"foo\" as \"bar\" echo $platform->quoteIdentifierInFragment('foo as bar'); // additionally, with some safe words: // (\"foo\".\"bar\" = \"boo\".\"baz\") echo $platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', ['(', ')', '=']);","title":"Using The Platform Object"},{"location":"adapter/#using-the-parameter-container","text":"The ParameterContainer object is a container for the various parameters that need to be passed into a Statement object to fulfill all the various parameterized parts of the SQL statement. This object implements the ArrayAccess interface. Below is the ParameterContainer API: namespace Laminas\\Db\\Adapter; use ArrayAccess; use ArrayIterator; use Countable; use Iterator; class ParameterContainer implements Iterator, ArrayAccess, Countable { public function __construct(array $data = []) /** methods to interact with values */ public function offsetExists(string|int $name) : bool; public function offsetGet(string|int $name) : mixed; public function offsetSetReference(string|int $name, string|int $from) : void; public function offsetSet(string|int $name, mixed $value, mixed $errata = null, int $maxLength = null) : void; public function offsetUnset(string|int $name) : void; /** set values from array (will reset first) */ public function setFromArray(array $data) : ParameterContainer; /** methods to interact with value errata */ public function offsetSetErrata(string|int $name, mixed $errata) : void; public function offsetGetErrata(string|int $name) : mixed; public function offsetHasErrata(string|int $name) : bool; public function offsetUnsetErrata(string|int $name) : void; /** errata only iterator */ public function getErrataIterator() : ArrayIterator; /** get array with named keys */ public function getNamedArray() : array; /** get array with int keys, ordered by position */ public function getPositionalArray() : array; /** iterator: */ public function count() : int; public function current() : mixed; public function next() : mixed; public function key() : string|int; public function valid() : bool; public function rewind() : void; /** merge existing array of parameters with existing parameters */ public function merge(array $parameters) : ParameterContainer; } In addition to handling parameter names and values, the container will assist in tracking parameter types for PHP type to SQL type handling. For example, it might be important that: $container->offsetSet('limit', 5); be bound as an integer. To achieve this, pass in the ParameterContainer::TYPE_INTEGER constant as the 3rd parameter: $container->offsetSet('limit', 5, $container::TYPE_INTEGER); This will ensure that if the underlying driver supports typing of bound parameters, that this translated information will also be passed along to the actual php database driver.","title":"Using The Parameter Container"},{"location":"adapter/#examples","text":"Creating a Driver , a vendor-portable query, and preparing and iterating the result: $adapter = new Laminas\\Db\\Adapter\\Adapter($driverConfig); $qi = function ($name) use ($adapter) { return $adapter->platform->quoteIdentifier($name); }; $fp = function ($name) use ($adapter) { return $adapter->driver->formatParameterName($name); }; $sql = 'UPDATE ' . $qi('artist') . ' SET ' . $qi('name') . ' = ' . $fp('name') . ' WHERE ' . $qi('id') . ' = ' . $fp('id'); $statement = $adapter->query($sql); $parameters = [ 'name' => 'Updated Artist', 'id' => 1, ]; $statement->execute($parameters); // DATA INSERTED, NOW CHECK $statement = $adapter->query( 'SELECT * FROM ' . $qi('artist') . ' WHERE id = ' . $fp('id') ); $results = $statement->execute(['id' => 1]); $row = $results->current(); $name = $row['name'];","title":"Examples"},{"location":"metadata/","text":"RDBMS Metadata Laminas\\Db\\Metadata is as sub-component of laminas-db that makes it possible to get metadata information about tables, columns, constraints, triggers, and other information from a database in a standardized way. The primary interface for Metadata is: namespace Laminas\\Db\\Metadata; interface MetadataInterface { public function getSchemas(); public function getTableNames(string $schema = null, bool $includeViews = false) : string[]; public function getTables(string $schema = null, bool $includeViews = false) : Object\\TableObject[]; public function getTable(string $tableName, string $schema = null) : Object\\TableObject; public function getViewNames(string $schema = null) : string[]; public function getViews(string $schema = null) : Object\\ViewObject[]; public function getView(string $viewName, string $schema = null) : Object\\ViewObject; public function getColumnNames(string string $table, $schema = null) : string[]; public function getColumns(string $table, string $schema = null) : Object\\ColumnObject[]; public function getColumn(string $columnName, string $table, string $schema = null) Object\\ColumnObject; public function getConstraints(string $table, $string schema = null) : Object\\ConstraintObject[]; public function getConstraint(string $constraintName, string $table, string $schema = null) : Object\\ConstraintObject; public function getConstraintKeys(string $constraint, string $table, string $schema = null) : Object\\ConstraintKeyObject[]; public function getTriggerNames(string $schema = null) : string[]; public function getTriggers(string $schema = null) : Object\\TriggerObject[]; public function getTrigger(string $triggerName, string $schema = null) : Object\\TriggerObject; } Basic Usage Usage of Laminas\\Db\\Metadata involves: Constructing a Laminas\\Db\\Metadata\\Metadata instance with an Adapter . Choosing a strategy for retrieving metadata, based on the database platform used. In most cases, information will come from querying the INFORMATION_SCHEMA tables for the currently accessible schema. The Metadata::get*Names() methods will return arrays of strings, while the other methods will return value objects specific to the type queried. $metadata = new Laminas\\Db\\Metadata\\Metadata($adapter); // get the table names $tableNames = $metadata->getTableNames(); foreach ($tableNames as $tableName) { echo 'In Table ' . $tableName . PHP_EOL; $table = $metadata->getTable($tableName); echo ' With columns: ' . PHP_EOL; foreach ($table->getColumns() as $column) { echo ' ' . $column->getName() . ' -> ' . $column->getDataType() . PHP_EOL; } echo PHP_EOL; echo ' With constraints: ' . PHP_EOL; foreach ($metadata->getConstraints($tableName) as $constraint) { echo ' ' . $constraint->getName() . ' -> ' . $constraint->getType() . PHP_EOL; if (! $constraint->hasColumns()) { continue; } echo ' column: ' . implode(', ', $constraint->getColumns()); if ($constraint->isForeignKey()) { $fkCols = []; foreach ($constraint->getReferencedColumns() as $refColumn) { $fkCols[] = $constraint->getReferencedTableName() . '.' . $refColumn; } echo ' => ' . implode(', ', $fkCols); } echo PHP_EOL; } echo '----' . PHP_EOL; } Metadata value objects Metadata returns value objects that provide an interface to help developers better explore the metadata. Below is the API for the various value objects: TableObject class Laminas\\Db\\Metadata\\Object\\TableObject { public function __construct($name); public function setColumns(array $columns); public function getColumns(); public function setConstraints($constraints); public function getConstraints(); public function setName($name); public function getName(); } ColumnObject class Laminas\\Db\\Metadata\\Object\\ColumnObject { public function __construct($name, $tableName, $schemaName = null); public function setName($name); public function getName(); public function getTableName(); public function setTableName($tableName); public function setSchemaName($schemaName); public function getSchemaName(); public function getOrdinalPosition(); public function setOrdinalPosition($ordinalPosition); public function getColumnDefault(); public function setColumnDefault($columnDefault); public function getIsNullable(); public function setIsNullable($isNullable); public function isNullable(); public function getDataType(); public function setDataType($dataType); public function getCharacterMaximumLength(); public function setCharacterMaximumLength($characterMaximumLength); public function getCharacterOctetLength(); public function setCharacterOctetLength($characterOctetLength); public function getNumericPrecision(); public function setNumericPrecision($numericPrecision); public function getNumericScale(); public function setNumericScale($numericScale); public function getNumericUnsigned(); public function setNumericUnsigned($numericUnsigned); public function isNumericUnsigned(); public function getErratas(); public function setErratas(array $erratas); public function getErrata($errataName); public function setErrata($errataName, $errataValue); } ConstraintObject class Laminas\\Db\\Metadata\\Object\\ConstraintObject { public function __construct($name, $tableName, $schemaName = null); public function setName($name); public function getName(); public function setSchemaName($schemaName); public function getSchemaName(); public function getTableName(); public function setTableName($tableName); public function setType($type); public function getType(); public function hasColumns(); public function getColumns(); public function setColumns(array $columns); public function getReferencedTableSchema(); public function setReferencedTableSchema($referencedTableSchema); public function getReferencedTableName(); public function setReferencedTableName($referencedTableName); public function getReferencedColumns(); public function setReferencedColumns(array $referencedColumns); public function getMatchOption(); public function setMatchOption($matchOption); public function getUpdateRule(); public function setUpdateRule($updateRule); public function getDeleteRule(); public function setDeleteRule($deleteRule); public function getCheckClause(); public function setCheckClause($checkClause); public function isPrimaryKey(); public function isUnique(); public function isForeignKey(); public function isCheck(); } TriggerObject class Laminas\\Db\\Metadata\\Object\\TriggerObject { public function getName(); public function setName($name); public function getEventManipulation(); public function setEventManipulation($eventManipulation); public function getEventObjectCatalog(); public function setEventObjectCatalog($eventObjectCatalog); public function getEventObjectSchema(); public function setEventObjectSchema($eventObjectSchema); public function getEventObjectTable(); public function setEventObjectTable($eventObjectTable); public function getActionOrder(); public function setActionOrder($actionOrder); public function getActionCondition(); public function setActionCondition($actionCondition); public function getActionStatement(); public function setActionStatement($actionStatement); public function getActionOrientation(); public function setActionOrientation($actionOrientation); public function getActionTiming(); public function setActionTiming($actionTiming); public function getActionReferenceOldTable(); public function setActionReferenceOldTable($actionReferenceOldTable); public function getActionReferenceNewTable(); public function setActionReferenceNewTable($actionReferenceNewTable); public function getActionReferenceOldRow(); public function setActionReferenceOldRow($actionReferenceOldRow); public function getActionReferenceNewRow(); public function setActionReferenceNewRow($actionReferenceNewRow); public function getCreated(); public function setCreated($created); }","title":"RDBMS Metadata"},{"location":"metadata/#rdbms-metadata","text":"Laminas\\Db\\Metadata is as sub-component of laminas-db that makes it possible to get metadata information about tables, columns, constraints, triggers, and other information from a database in a standardized way. The primary interface for Metadata is: namespace Laminas\\Db\\Metadata; interface MetadataInterface { public function getSchemas(); public function getTableNames(string $schema = null, bool $includeViews = false) : string[]; public function getTables(string $schema = null, bool $includeViews = false) : Object\\TableObject[]; public function getTable(string $tableName, string $schema = null) : Object\\TableObject; public function getViewNames(string $schema = null) : string[]; public function getViews(string $schema = null) : Object\\ViewObject[]; public function getView(string $viewName, string $schema = null) : Object\\ViewObject; public function getColumnNames(string string $table, $schema = null) : string[]; public function getColumns(string $table, string $schema = null) : Object\\ColumnObject[]; public function getColumn(string $columnName, string $table, string $schema = null) Object\\ColumnObject; public function getConstraints(string $table, $string schema = null) : Object\\ConstraintObject[]; public function getConstraint(string $constraintName, string $table, string $schema = null) : Object\\ConstraintObject; public function getConstraintKeys(string $constraint, string $table, string $schema = null) : Object\\ConstraintKeyObject[]; public function getTriggerNames(string $schema = null) : string[]; public function getTriggers(string $schema = null) : Object\\TriggerObject[]; public function getTrigger(string $triggerName, string $schema = null) : Object\\TriggerObject; }","title":"RDBMS Metadata"},{"location":"metadata/#basic-usage","text":"Usage of Laminas\\Db\\Metadata involves: Constructing a Laminas\\Db\\Metadata\\Metadata instance with an Adapter . Choosing a strategy for retrieving metadata, based on the database platform used. In most cases, information will come from querying the INFORMATION_SCHEMA tables for the currently accessible schema. The Metadata::get*Names() methods will return arrays of strings, while the other methods will return value objects specific to the type queried. $metadata = new Laminas\\Db\\Metadata\\Metadata($adapter); // get the table names $tableNames = $metadata->getTableNames(); foreach ($tableNames as $tableName) { echo 'In Table ' . $tableName . PHP_EOL; $table = $metadata->getTable($tableName); echo ' With columns: ' . PHP_EOL; foreach ($table->getColumns() as $column) { echo ' ' . $column->getName() . ' -> ' . $column->getDataType() . PHP_EOL; } echo PHP_EOL; echo ' With constraints: ' . PHP_EOL; foreach ($metadata->getConstraints($tableName) as $constraint) { echo ' ' . $constraint->getName() . ' -> ' . $constraint->getType() . PHP_EOL; if (! $constraint->hasColumns()) { continue; } echo ' column: ' . implode(', ', $constraint->getColumns()); if ($constraint->isForeignKey()) { $fkCols = []; foreach ($constraint->getReferencedColumns() as $refColumn) { $fkCols[] = $constraint->getReferencedTableName() . '.' . $refColumn; } echo ' => ' . implode(', ', $fkCols); } echo PHP_EOL; } echo '----' . PHP_EOL; }","title":"Basic Usage"},{"location":"metadata/#metadata-value-objects","text":"Metadata returns value objects that provide an interface to help developers better explore the metadata. Below is the API for the various value objects:","title":"Metadata value objects"},{"location":"result-set/","text":"Result Sets Laminas\\Db\\ResultSet is a sub-component of laminas-db for abstracting the iteration of results returned from queries producing rowsets. While data sources for this can be anything that is iterable, generally these will be populated from Laminas\\Db\\Adapter\\Driver\\ResultInterface instances. Result sets must implement the Laminas\\Db\\ResultSet\\ResultSetInterface , and all sub-components of laminas-db that return a result set as part of their API will assume an instance of a ResultSetInterface should be returned. In most cases, the prototype pattern will be used by consuming object to clone a prototype of a ResultSet and return a specialized ResultSet with a specific data source injected. ResultSetInterface is defined as follows: use Countable; use Traversable; interface ResultSetInterface extends Traversable, Countable { public function initialize(mixed $dataSource) : void; public function getFieldCount() : int; } Quick start Laminas\\Db\\ResultSet\\ResultSet is the most basic form of a ResultSet object that will expose each row as either an ArrayObject -like object or an array of row data. By default, Laminas\\Db\\Adapter\\Adapter will use a prototypical Laminas\\Db\\ResultSet\\ResultSet object for iterating when using the Laminas\\Db\\Adapter\\Adapter::query() method. The following is an example workflow similar to what one might find inside Laminas\\Db\\Adapter\\Adapter::query() : use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\ResultSet\\ResultSet; $statement = $driver->createStatement('SELECT * FROM users'); $statement->prepare(); $result = $statement->execute($parameters); if ($result instanceof ResultInterface && $result->isQueryResult()) { $resultSet = new ResultSet; $resultSet->initialize($result); foreach ($resultSet as $row) { echo $row->my_column . PHP_EOL; } } Laminas\\Db\\ResultSet\\ResultSet and Laminas\\Db\\ResultSet\\AbstractResultSet For most purposes, either an instance of Laminas\\Db\\ResultSet\\ResultSet or a derivative of Laminas\\Db\\ResultSet\\AbstractResultSet will be used. The implementation of the AbstractResultSet offers the following core functionality: namespace Laminas\\Db\\ResultSet; use Iterator; abstract class AbstractResultSet implements Iterator, ResultSetInterface { public function initialize(array|Iterator|IteratorAggregate|ResultInterface $dataSource) : self; public function getDataSource() : Iterator|IteratorAggregate|ResultInterface; public function getFieldCount() : int; /** Iterator */ public function next() : mixed; public function key() : string|int; public function current() : mixed; public function valid() : bool; public function rewind() : void; /** countable */ public function count() : int; /** get rows as array */ public function toArray() : array; } Laminas\\Db\\ResultSet\\HydratingResultSet Laminas\\Db\\ResultSet\\HydratingResultSet is a more flexible ResultSet object that allows the developer to choose an appropriate \"hydration strategy\" for getting row data into a target object. While iterating over results, HydratingResultSet will take a prototype of a target object and clone it once for each row. The HydratingResultSet will then hydrate that clone with the row data. The HydratingResultSet depends on laminas-hydrator , which you will need to install: $ composer require laminas/laminas-hydrator In the example below, rows from the database will be iterated, and during iteration, HydratingResultSet will use the Reflection based hydrator to inject the row data directly into the protected members of the cloned UserEntity object: use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\ResultSet\\HydratingResultSet; use Laminas\\Hydrator\\Reflection as ReflectionHydrator; class UserEntity { protected $first_name; protected $last_name; public function getFirstName() { return $this->first_name; } public function getLastName() { return $this->last_name; } public function setFirstName($firstName) { $this->first_name = $firstName; } public function setLastName($lastName) { $this->last_name = $lastName; } } $statement = $driver->createStatement($sql); $statement->prepare($parameters); $result = $statement->execute(); if ($result instanceof ResultInterface && $result->isQueryResult()) { $resultSet = new HydratingResultSet(new ReflectionHydrator, new UserEntity); $resultSet->initialize($result); foreach ($resultSet as $user) { echo $user->getFirstName() . ' ' . $user->getLastName() . PHP_EOL; } } For more information, see the laminas-hydrator documentation to get a better sense of the different strategies that can be employed in order to populate a target object.","title":"Result Sets"},{"location":"result-set/#result-sets","text":"Laminas\\Db\\ResultSet is a sub-component of laminas-db for abstracting the iteration of results returned from queries producing rowsets. While data sources for this can be anything that is iterable, generally these will be populated from Laminas\\Db\\Adapter\\Driver\\ResultInterface instances. Result sets must implement the Laminas\\Db\\ResultSet\\ResultSetInterface , and all sub-components of laminas-db that return a result set as part of their API will assume an instance of a ResultSetInterface should be returned. In most cases, the prototype pattern will be used by consuming object to clone a prototype of a ResultSet and return a specialized ResultSet with a specific data source injected. ResultSetInterface is defined as follows: use Countable; use Traversable; interface ResultSetInterface extends Traversable, Countable { public function initialize(mixed $dataSource) : void; public function getFieldCount() : int; }","title":"Result Sets"},{"location":"result-set/#quick-start","text":"Laminas\\Db\\ResultSet\\ResultSet is the most basic form of a ResultSet object that will expose each row as either an ArrayObject -like object or an array of row data. By default, Laminas\\Db\\Adapter\\Adapter will use a prototypical Laminas\\Db\\ResultSet\\ResultSet object for iterating when using the Laminas\\Db\\Adapter\\Adapter::query() method. The following is an example workflow similar to what one might find inside Laminas\\Db\\Adapter\\Adapter::query() : use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\ResultSet\\ResultSet; $statement = $driver->createStatement('SELECT * FROM users'); $statement->prepare(); $result = $statement->execute($parameters); if ($result instanceof ResultInterface && $result->isQueryResult()) { $resultSet = new ResultSet; $resultSet->initialize($result); foreach ($resultSet as $row) { echo $row->my_column . PHP_EOL; } }","title":"Quick start"},{"location":"result-set/#laminasdbresultsetresultset-and-laminasdbresultsetabstractresultset","text":"For most purposes, either an instance of Laminas\\Db\\ResultSet\\ResultSet or a derivative of Laminas\\Db\\ResultSet\\AbstractResultSet will be used. The implementation of the AbstractResultSet offers the following core functionality: namespace Laminas\\Db\\ResultSet; use Iterator; abstract class AbstractResultSet implements Iterator, ResultSetInterface { public function initialize(array|Iterator|IteratorAggregate|ResultInterface $dataSource) : self; public function getDataSource() : Iterator|IteratorAggregate|ResultInterface; public function getFieldCount() : int; /** Iterator */ public function next() : mixed; public function key() : string|int; public function current() : mixed; public function valid() : bool; public function rewind() : void; /** countable */ public function count() : int; /** get rows as array */ public function toArray() : array; }","title":"Laminas\\Db\\ResultSet\\ResultSet and Laminas\\Db\\ResultSet\\AbstractResultSet"},{"location":"result-set/#laminasdbresultsethydratingresultset","text":"Laminas\\Db\\ResultSet\\HydratingResultSet is a more flexible ResultSet object that allows the developer to choose an appropriate \"hydration strategy\" for getting row data into a target object. While iterating over results, HydratingResultSet will take a prototype of a target object and clone it once for each row. The HydratingResultSet will then hydrate that clone with the row data. The HydratingResultSet depends on laminas-hydrator , which you will need to install: $ composer require laminas/laminas-hydrator In the example below, rows from the database will be iterated, and during iteration, HydratingResultSet will use the Reflection based hydrator to inject the row data directly into the protected members of the cloned UserEntity object: use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\ResultSet\\HydratingResultSet; use Laminas\\Hydrator\\Reflection as ReflectionHydrator; class UserEntity { protected $first_name; protected $last_name; public function getFirstName() { return $this->first_name; } public function getLastName() { return $this->last_name; } public function setFirstName($firstName) { $this->first_name = $firstName; } public function setLastName($lastName) { $this->last_name = $lastName; } } $statement = $driver->createStatement($sql); $statement->prepare($parameters); $result = $statement->execute(); if ($result instanceof ResultInterface && $result->isQueryResult()) { $resultSet = new HydratingResultSet(new ReflectionHydrator, new UserEntity); $resultSet->initialize($result); foreach ($resultSet as $user) { echo $user->getFirstName() . ' ' . $user->getLastName() . PHP_EOL; } } For more information, see the laminas-hydrator documentation to get a better sense of the different strategies that can be employed in order to populate a target object.","title":"Laminas\\Db\\ResultSet\\HydratingResultSet"},{"location":"row-gateway/","text":"Row Gateways Laminas\\Db\\RowGateway is a sub-component of laminas-db that implements the Row Data Gateway pattern described in the book Patterns of Enterprise Application Architecture . Row Data Gateways model individual rows of a database table, and provide methods such as save() and delete() that persist the row to the database. Likewise, after a row from the database is retrieved, it can then be manipulated and save() 'd back to the database in the same position (row), or it can be delete() 'd from the table. RowGatewayInterface defines the methods save() and delete() : namespace Laminas\\Db\\RowGateway; interface RowGatewayInterface { public function save(); public function delete(); } Quick start RowGateway is generally used in conjunction with objects that produce Laminas\\Db\\ResultSet s, though it may also be used standalone. To use it standalone, you need an Adapter instance and a set of data to work with. The following demonstrates a basic use case. use Laminas\\Db\\RowGateway\\RowGateway; // Query the database: $resultSet = $adapter->query('SELECT * FROM `user` WHERE `id` = ?', [2]); // Get array of data: $rowData = $resultSet->current()->getArrayCopy(); // Create a row gateway: $rowGateway = new RowGateway('id', 'my_table', $adapter); $rowGateway->populate($rowData, true); // Manipulate the row and persist it: $rowGateway->first_name = 'New Name'; $rowGateway->save(); // Or delete this row: $rowGateway->delete(); The workflow described above is greatly simplified when RowGateway is used in conjunction with the TableGateway RowGatewayFeature . In that paradigm, select() operations will produce a ResultSet that iterates RowGateway instances. As an example: use Laminas\\Db\\TableGateway\\Feature\\RowGatewayFeature; use Laminas\\Db\\TableGateway\\TableGateway; $table = new TableGateway('artist', $adapter, new RowGatewayFeature('id')); $results = $table->select(['id' => 2]); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save(); ActiveRecord Style Objects If you wish to have custom behaviour in your RowGateway objects — essentially making them behave similarly to the ActiveRecord pattern), pass a prototype object implementing the RowGatewayInterface to the RowGatewayFeature constructor instead of a primary key: use Laminas\\Db\\TableGateway\\Feature\\RowGatewayFeature; use Laminas\\Db\\TableGateway\\TableGateway; use Laminas\\Db\\RowGateway\\RowGatewayInterface; class Artist implements RowGatewayInterface { protected $adapter; public function __construct($adapter) { $this->adapter = $adapter; } // ... save() and delete() implementations } $table = new TableGateway('artist', $adapter, new RowGatewayFeature(new Artist($adapter)));","title":"Row Gateways"},{"location":"row-gateway/#row-gateways","text":"Laminas\\Db\\RowGateway is a sub-component of laminas-db that implements the Row Data Gateway pattern described in the book Patterns of Enterprise Application Architecture . Row Data Gateways model individual rows of a database table, and provide methods such as save() and delete() that persist the row to the database. Likewise, after a row from the database is retrieved, it can then be manipulated and save() 'd back to the database in the same position (row), or it can be delete() 'd from the table. RowGatewayInterface defines the methods save() and delete() : namespace Laminas\\Db\\RowGateway; interface RowGatewayInterface { public function save(); public function delete(); }","title":"Row Gateways"},{"location":"row-gateway/#quick-start","text":"RowGateway is generally used in conjunction with objects that produce Laminas\\Db\\ResultSet s, though it may also be used standalone. To use it standalone, you need an Adapter instance and a set of data to work with. The following demonstrates a basic use case. use Laminas\\Db\\RowGateway\\RowGateway; // Query the database: $resultSet = $adapter->query('SELECT * FROM `user` WHERE `id` = ?', [2]); // Get array of data: $rowData = $resultSet->current()->getArrayCopy(); // Create a row gateway: $rowGateway = new RowGateway('id', 'my_table', $adapter); $rowGateway->populate($rowData, true); // Manipulate the row and persist it: $rowGateway->first_name = 'New Name'; $rowGateway->save(); // Or delete this row: $rowGateway->delete(); The workflow described above is greatly simplified when RowGateway is used in conjunction with the TableGateway RowGatewayFeature . In that paradigm, select() operations will produce a ResultSet that iterates RowGateway instances. As an example: use Laminas\\Db\\TableGateway\\Feature\\RowGatewayFeature; use Laminas\\Db\\TableGateway\\TableGateway; $table = new TableGateway('artist', $adapter, new RowGatewayFeature('id')); $results = $table->select(['id' => 2]); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save();","title":"Quick start"},{"location":"row-gateway/#activerecord-style-objects","text":"If you wish to have custom behaviour in your RowGateway objects — essentially making them behave similarly to the ActiveRecord pattern), pass a prototype object implementing the RowGatewayInterface to the RowGatewayFeature constructor instead of a primary key: use Laminas\\Db\\TableGateway\\Feature\\RowGatewayFeature; use Laminas\\Db\\TableGateway\\TableGateway; use Laminas\\Db\\RowGateway\\RowGatewayInterface; class Artist implements RowGatewayInterface { protected $adapter; public function __construct($adapter) { $this->adapter = $adapter; } // ... save() and delete() implementations } $table = new TableGateway('artist', $adapter, new RowGatewayFeature(new Artist($adapter)));","title":"ActiveRecord Style Objects"},{"location":"sql-ddl/","text":"DDL Abstraction Laminas\\Db\\Sql\\Ddl is a sub-component of Laminas\\Db\\Sql allowing creation of DDL (Data Definition Language) SQL statements. When combined with a platform specific Laminas\\Db\\Sql\\Sql object, DDL objects are capable of producing platform-specific CREATE TABLE statements, with specialized data types, constraints, and indexes for a database/schema. The following platforms have platform specializations for DDL: MySQL All databases compatible with ANSI SQL92 Creating Tables Like Laminas\\Db\\Sql objects, each statement type is represented by a class. For example, CREATE TABLE is modeled by the CreateTable class; this is likewise the same for ALTER TABLE (as AlterTable ), and DROP TABLE (as DropTable ). You can create instances using a number of approaches: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; $table = new Ddl\\CreateTable(); // With a table name: $table = new Ddl\\CreateTable('bar'); // With a schema name \"foo\": $table = new Ddl\\CreateTable(new TableIdentifier('bar', 'foo')); // Optionally, as a temporary table: $table = new Ddl\\CreateTable('bar', true); You can also set the table after instantiation: $table->setTable('bar'); Currently, columns are added by creating a column object (described in the data type table below ): use Laminas\\Db\\Sql\\Ddl\\Column; $table->addColumn(new Column\\Integer('id')); $table->addColumn(new Column\\Varchar('name', 255)); Beyond adding columns to a table, you may also add constraints: use Laminas\\Db\\Sql\\Ddl\\Constraint; $table->addConstraint(new Constraint\\PrimaryKey('id')); $table->addConstraint( new Constraint\\UniqueKey(['name', 'foo'], 'my_unique_key') ); You can also use the AUTO_INCREMENT attribute for MySQL: use Laminas\\Db\\Sql\\Ddl\\Column; $column = new Column\\Integer('id'); $column->setOption('AUTO_INCREMENT', true); Altering Tables Similar to CreateTable , you may also use AlterTable instances: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; $table = new Ddl\\AlterTable(); // With a table name: $table = new Ddl\\AlterTable('bar'); // With a schema name \"foo\": $table = new Ddl\\AlterTable(new TableIdentifier('bar', 'foo')); // Optionally, as a temporary table: $table = new Ddl\\AlterTable('bar', true); The primary difference between a CreateTable and AlterTable is that the AlterTable takes into account that the table and its assets already exist. Therefore, while you still have addColumn() and addConstraint() , you will also have the ability to alter existing columns: use Laminas\\Db\\Sql\\Ddl\\Column; $table->changeColumn('name', Column\\Varchar('new_name', 50)); You may also drop existing columns or constraints: $table->dropColumn('foo'); $table->dropConstraint('my_index'); Dropping Tables To drop a table, create a DropTable instance: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; // With a table name: $drop = new Ddl\\DropTable('bar'); // With a schema name \"foo\": $drop = new Ddl\\DropTable(new TableIdentifier('bar', 'foo')); Executing DDL Statements After a DDL statement object has been created and configured, at some point you will need to execute the statement. This requires an Adapter instance and a properly seeded Sql instance. The workflow looks something like this, with $ddl being a CreateTable , AlterTable , or DropTable instance: use Laminas\\Db\\Sql\\Sql; // Existence of $adapter is assumed. $sql = new Sql($adapter); $adapter->query( $sql->getSqlStringForSqlObject($ddl), $adapter::QUERY_MODE_EXECUTE ); By passing the $ddl object through the $sql instance's getSqlStringForSqlObject() method, we ensure that any platform specific specializations/modifications are utilized to create a platform specific SQL statement. Next, using the constant Laminas\\Db\\Adapter\\Adapter::QUERY_MODE_EXECUTE ensures that the SQL statement is not prepared, as most DDL statements on most platforms cannot be prepared, only executed. Currently Supported Data Types These types exist in the Laminas\\Db\\Sql\\Ddl\\Column namespace. Data types must implement Laminas\\Db\\Sql\\Ddl\\Column\\ColumnInterface . In alphabetical order: Type Arguments For Construction BigInteger $name , $nullable = false , $default = null , array $options = array() Binary $name , $length , nullable = false , $default = null , array $options = array() Blob $name , $length , nullable = false , $default = null , array $options = array() Boolean $name Char $name , length Column (generic) $name = null Date $name DateTime $name Decimal $name , $precision , $scale = null Float $name , $digits , $decimal (Note: this class is deprecated as of 2.4.0; use Floating instead) Floating $name , $digits , $decimal Integer $name , $nullable = false , default = null , array $options = array() Text $name , $length , nullable = false , $default = null , array $options = array() Time $name Timestamp $name Varbinary $name , $length Varchar $name , $length Each of the above types can be utilized in any place that accepts a Column\\ColumnInterface instance. Currently, this is primarily in CreateTable::addColumn() and AlterTable 's addColumn() and changeColumn() methods. Currently Supported Constraint Types These types exist in the Laminas\\Db\\Sql\\Ddl\\Constraint namespace. Data types must implement Laminas\\Db\\Sql\\Ddl\\Constraint\\ConstraintInterface . In alphabetical order: Type Arguments For Construction Check $expression , $name ForeignKey $name , $column , $referenceTable , $referenceColumn , $onDeleteRule = null , $onUpdateRule = null PrimaryKey $columns UniqueKey $column , $name = null Each of the above types can be utilized in any place that accepts a Column\\ConstraintInterface instance. Currently, this is primarily in CreateTable::addConstraint() and AlterTable::addConstraint() .","title":"DDL Abstraction"},{"location":"sql-ddl/#ddl-abstraction","text":"Laminas\\Db\\Sql\\Ddl is a sub-component of Laminas\\Db\\Sql allowing creation of DDL (Data Definition Language) SQL statements. When combined with a platform specific Laminas\\Db\\Sql\\Sql object, DDL objects are capable of producing platform-specific CREATE TABLE statements, with specialized data types, constraints, and indexes for a database/schema. The following platforms have platform specializations for DDL: MySQL All databases compatible with ANSI SQL92","title":"DDL Abstraction"},{"location":"sql-ddl/#creating-tables","text":"Like Laminas\\Db\\Sql objects, each statement type is represented by a class. For example, CREATE TABLE is modeled by the CreateTable class; this is likewise the same for ALTER TABLE (as AlterTable ), and DROP TABLE (as DropTable ). You can create instances using a number of approaches: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; $table = new Ddl\\CreateTable(); // With a table name: $table = new Ddl\\CreateTable('bar'); // With a schema name \"foo\": $table = new Ddl\\CreateTable(new TableIdentifier('bar', 'foo')); // Optionally, as a temporary table: $table = new Ddl\\CreateTable('bar', true); You can also set the table after instantiation: $table->setTable('bar'); Currently, columns are added by creating a column object (described in the data type table below ): use Laminas\\Db\\Sql\\Ddl\\Column; $table->addColumn(new Column\\Integer('id')); $table->addColumn(new Column\\Varchar('name', 255)); Beyond adding columns to a table, you may also add constraints: use Laminas\\Db\\Sql\\Ddl\\Constraint; $table->addConstraint(new Constraint\\PrimaryKey('id')); $table->addConstraint( new Constraint\\UniqueKey(['name', 'foo'], 'my_unique_key') ); You can also use the AUTO_INCREMENT attribute for MySQL: use Laminas\\Db\\Sql\\Ddl\\Column; $column = new Column\\Integer('id'); $column->setOption('AUTO_INCREMENT', true);","title":"Creating Tables"},{"location":"sql-ddl/#altering-tables","text":"Similar to CreateTable , you may also use AlterTable instances: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; $table = new Ddl\\AlterTable(); // With a table name: $table = new Ddl\\AlterTable('bar'); // With a schema name \"foo\": $table = new Ddl\\AlterTable(new TableIdentifier('bar', 'foo')); // Optionally, as a temporary table: $table = new Ddl\\AlterTable('bar', true); The primary difference between a CreateTable and AlterTable is that the AlterTable takes into account that the table and its assets already exist. Therefore, while you still have addColumn() and addConstraint() , you will also have the ability to alter existing columns: use Laminas\\Db\\Sql\\Ddl\\Column; $table->changeColumn('name', Column\\Varchar('new_name', 50)); You may also drop existing columns or constraints: $table->dropColumn('foo'); $table->dropConstraint('my_index');","title":"Altering Tables"},{"location":"sql-ddl/#dropping-tables","text":"To drop a table, create a DropTable instance: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; // With a table name: $drop = new Ddl\\DropTable('bar'); // With a schema name \"foo\": $drop = new Ddl\\DropTable(new TableIdentifier('bar', 'foo'));","title":"Dropping Tables"},{"location":"sql-ddl/#executing-ddl-statements","text":"After a DDL statement object has been created and configured, at some point you will need to execute the statement. This requires an Adapter instance and a properly seeded Sql instance. The workflow looks something like this, with $ddl being a CreateTable , AlterTable , or DropTable instance: use Laminas\\Db\\Sql\\Sql; // Existence of $adapter is assumed. $sql = new Sql($adapter); $adapter->query( $sql->getSqlStringForSqlObject($ddl), $adapter::QUERY_MODE_EXECUTE ); By passing the $ddl object through the $sql instance's getSqlStringForSqlObject() method, we ensure that any platform specific specializations/modifications are utilized to create a platform specific SQL statement. Next, using the constant Laminas\\Db\\Adapter\\Adapter::QUERY_MODE_EXECUTE ensures that the SQL statement is not prepared, as most DDL statements on most platforms cannot be prepared, only executed.","title":"Executing DDL Statements"},{"location":"sql-ddl/#currently-supported-data-types","text":"These types exist in the Laminas\\Db\\Sql\\Ddl\\Column namespace. Data types must implement Laminas\\Db\\Sql\\Ddl\\Column\\ColumnInterface . In alphabetical order: Type Arguments For Construction BigInteger $name , $nullable = false , $default = null , array $options = array() Binary $name , $length , nullable = false , $default = null , array $options = array() Blob $name , $length , nullable = false , $default = null , array $options = array() Boolean $name Char $name , length Column (generic) $name = null Date $name DateTime $name Decimal $name , $precision , $scale = null Float $name , $digits , $decimal (Note: this class is deprecated as of 2.4.0; use Floating instead) Floating $name , $digits , $decimal Integer $name , $nullable = false , default = null , array $options = array() Text $name , $length , nullable = false , $default = null , array $options = array() Time $name Timestamp $name Varbinary $name , $length Varchar $name , $length Each of the above types can be utilized in any place that accepts a Column\\ColumnInterface instance. Currently, this is primarily in CreateTable::addColumn() and AlterTable 's addColumn() and changeColumn() methods.","title":"Currently Supported Data Types"},{"location":"sql-ddl/#currently-supported-constraint-types","text":"These types exist in the Laminas\\Db\\Sql\\Ddl\\Constraint namespace. Data types must implement Laminas\\Db\\Sql\\Ddl\\Constraint\\ConstraintInterface . In alphabetical order: Type Arguments For Construction Check $expression , $name ForeignKey $name , $column , $referenceTable , $referenceColumn , $onDeleteRule = null , $onUpdateRule = null PrimaryKey $columns UniqueKey $column , $name = null Each of the above types can be utilized in any place that accepts a Column\\ConstraintInterface instance. Currently, this is primarily in CreateTable::addConstraint() and AlterTable::addConstraint() .","title":"Currently Supported Constraint Types"},{"location":"sql/","text":"SQL Abstraction Laminas\\Db\\Sql is a SQL abstraction layer for building platform-specific SQL queries via an object-oriented API. The end result of a Laminas\\Db\\Sql object will be to either produce a Statement and ParameterContainer that represents the target query, or a full string that can be directly executed against the database platform. To achieve this, Laminas\\Db\\Sql objects require a Laminas\\Db\\Adapter\\Adapter object in order to produce the desired results. Quick start There are four primary tasks associated with interacting with a database defined by Data Manipulation Language (DML): selecting, inserting, updating, and deleting. As such, there are four primary classes that developers can interact with in order to build queries in the Laminas\\Db\\Sql namespace: Select , Insert , Update , and Delete . Since these four tasks are so closely related and generally used together within the same application, the Laminas\\Db\\Sql\\Sql class helps you create them and produce the result you are attempting to achieve. use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); // returns a Laminas\\Db\\Sql\\Select instance $insert = $sql->insert(); // returns a Laminas\\Db\\Sql\\Insert instance $update = $sql->update(); // returns a Laminas\\Db\\Sql\\Update instance $delete = $sql->delete(); // returns a Laminas\\Db\\Sql\\Delete instance As a developer, you can now interact with these objects, as described in the sections below, to customize each query. Once they have been populated with values, they are ready to either be prepared or executed. To prepare (using a Select object): use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(['id' => 2]); $statement = $sql->prepareStatementForSqlObject($select); $results = $statement->execute(); To execute (using a Select object) use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(['id' => 2]); $selectString = $sql->buildSqlString($select); $results = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE); Laminas\\\\Db\\\\Sql\\\\Sql objects can also be bound to a particular table so that in obtaining a Select , Insert , Update , or Delete instance, the object will be seeded with the table: use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter, 'foo'); $select = $sql->select(); $select->where(['id' => 2]); // $select already has from('foo') applied Common interfaces for SQL implementations Each of these objects implements the following two interfaces: interface PreparableSqlInterface { public function prepareStatement(Adapter $adapter, StatementInterface $statement) : void; } interface SqlInterface { public function getSqlString(PlatformInterface $adapterPlatform = null) : string; } Use these functions to produce either (a) a prepared statement, or (b) a string to execute. Select Laminas\\Db\\Sql\\Select presents a unified API for building platform-specific SQL SELECT queries. Instances may be created and consumed without Laminas\\Db\\Sql\\Sql : use Laminas\\Db\\Sql\\Select; $select = new Select(); // or, to produce a $select bound to a specific table $select = new Select('foo'); If a table is provided to the Select object, then from() cannot be called later to change the name of the table. Once you have a valid Select object, the following API can be used to further specify various select statement parts: class Select extends AbstractSql implements SqlInterface, PreparableSqlInterface { const JOIN_INNER = 'inner'; const JOIN_OUTER = 'outer'; const JOIN_FULL_OUTER = 'full outer'; const JOIN_LEFT = 'left'; const JOIN_RIGHT = 'right'; const SQL_STAR = '*'; const ORDER_ASCENDING = 'ASC'; const ORDER_DESCENDING = 'DESC'; public $where; // @param Where $where public function __construct(string|array|TableIdentifier $table = null); public function from(string|array|TableIdentifier $table) : self; public function columns(array $columns, bool $prefixColumnsWithTable = true) : self; public function join(string|array|TableIdentifier $name, string $on, string|array $columns = self::SQL_STAR, string $type = self::JOIN_INNER) : self; public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; public function group(string|array $group); public function having(Having|callable|string|array $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; public function order(string|array $order) : self; public function limit(int $limit) : self; public function offset(int $offset) : self; } from() // As a string: $select->from('foo'); // As an array to specify an alias // (produces SELECT \"t\".* FROM \"table\" AS \"t\") $select->from(['t' => 'table']); // Using a Sql\\TableIdentifier: // (same output as above) $select->from(['t' => new TableIdentifier('table')]); columns() // As an array of names $select->columns(['foo', 'bar']); // As an associative array with aliases as the keys // (produces 'bar' AS 'foo', 'bax' AS 'baz') $select->columns([ 'foo' => 'bar', 'baz' => 'bax' ]); // Sql function call on the column // (produces CONCAT_WS('/', 'bar', 'bax') AS 'foo') $select->columns([ 'foo' => new \\Laminas\\Db\\Sql\\Expression(\"CONCAT_WS('/', 'bar', 'bax')\") ]); join() $select->join( 'foo', // table name 'id = bar.id', // expression to join on (will be quoted by platform object before insertion), ['bar', 'baz'], // (optional) list of columns, same requirements as columns() above $select::JOIN_OUTER // (optional), one of inner, outer, full outer, left, right also represented by constants in the API ); $select ->from(['f' => 'foo']) // base table ->join( ['b' => 'bar'], // join table with alias 'f.foo_id = b.foo_id' // join expression ); where(), having() Laminas\\Db\\Sql\\Select provides bit of flexibility as it regards to what kind of parameters are acceptable when calling where() or having() . The method signature is listed as: /** * Create where clause * * @param Where|callable|string|array $predicate * @param string $combination One of the OP_* constants from Predicate\\PredicateSet * @return Select */ public function where($predicate, $combination = Predicate\\PredicateSet::OP_AND); If you provide a Laminas\\Db\\Sql\\Where instance to where() or a Laminas\\Db\\Sql\\Having instance to having() , any previous internal instances will be replaced completely. When either instance is processed, this object will be iterated to produce the WHERE or HAVING section of the SELECT statement. If you provide a PHP callable to where() or having() , this function will be called with the Select 's Where / Having instance as the only parameter. This enables code like the following: $select->where(function (Where $where) { $where->like('username', 'ralph%'); }); If you provide a string , this string will be used to create a Laminas\\Db\\Sql\\Predicate\\Expression instance, and its contents will be applied as-is, with no quoting: // SELECT \"foo\".* FROM \"foo\" WHERE x = 5 $select->from('foo')->where('x = 5'); If you provide an array with integer indices, the value can be one of: a string; this will be used to build a Predicate\\Expression . any object implementing Predicate\\PredicateInterface . In either case, the instances are pushed onto the Where stack with the $combination provided (defaulting to AND ). As an example: // SELECT \"foo\".* FROM \"foo\" WHERE x = 5 AND y = z $select->from('foo')->where(['x = 5', 'y = z']); If you provide an associative array with string keys, any value with a string key will be cast as follows: PHP value Predicate type null Predicate\\IsNull array Predicate\\In string Predicate\\Operator , where the key is the identifier. As an example: // SELECT \"foo\".* FROM \"foo\" WHERE \"c1\" IS NULL AND \"c2\" IN (?, ?, ?) AND \"c3\" IS NOT NULL $select->from('foo')->where([ 'c1' => null, 'c2' => [1, 2, 3], new \\Laminas\\Db\\Sql\\Predicate\\IsNotNull('c3'), ]); As another example of complex queries with nested conditions e.g. SELECT * WHERE (column1 is null or column1 = 2) AND (column2 = 3) you need to use the nest() and unnest() methods, as follows: $select->where->nest() // bracket opened ->isNull('column1') ->or ->equalTo('column1', '2') ->unnest(); // bracket closed ->equalTo('column2', '3'); order() $select = new Select; $select->order('id DESC'); // produces 'id' DESC $select = new Select; $select ->order('id DESC') ->order('name ASC, age DESC'); // produces 'id' DESC, 'name' ASC, 'age' DESC $select = new Select; $select->order(['name ASC', 'age DESC']); // produces 'name' ASC, 'age' DESC limit() and offset() $select = new Select; $select->limit(5); // always takes an integer/numeric $select->offset(10); // similarly takes an integer/numeric Insert The Insert API: class Insert implements SqlInterface, PreparableSqlInterface { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public function __construct(string|TableIdentifier $table = null); public function into(string|TableIdentifier $table) : self; public function columns(array $columns) : self; public function values(array $values, string $flag = self::VALUES_SET) : self; } As with Select , the table may be provided during instantiation or via the into() method. columns() $insert->columns(['foo', 'bar']); // set the valid columns values() The default behavior of values is to set the values. Successive calls will not preserve values from previous calls. $insert->values([ 'col_1' => 'value1', 'col_2' => 'value2', ]); To merge values with previous calls, provide the appropriate flag: Laminas\\Db\\Sql\\Insert::VALUES_MERGE $insert->values(['col_2' => 'value2'], $insert::VALUES_MERGE); Update class Update { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public $where; // @param Where $where public function __construct(string|TableIdentifier $table = null); public function table(string|TableIdentifier $table) : self; public function set(array $values, string $flag = self::VALUES_SET) : self; public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; } set() $update->set(['foo' => 'bar', 'baz' => 'bax']); where() See the section on Where and Having . Delete class Delete { public $where; // @param Where $where public function __construct(string|TableIdentifier $table = null); public function from(string|TableIdentifier $table); public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; } where() See the section on Where and Having . Where and Having In the following, we will talk about Where ; note, however, that Having utilizes the same API. Effectively, Where and Having extend from the same base object, a Predicate (and PredicateSet ). All of the parts that make up a WHERE or HAVING clause that are AND'ed or OR'd together are called predicates . The full set of predicates is called a PredicateSet . A Predicate generally contains the values (and identifiers) separate from the fragment they belong to until the last possible moment when the statement is either prepared (parameteritized) or executed. In parameterization, the parameters will be replaced with their proper placeholder (a named or positional parameter), and the values stored inside an Adapter\\ParameterContainer . When executed, the values will be interpolated into the fragments they belong to and properly quoted. In the Where / Having API, a distinction is made between what elements are considered identifiers ( TYPE_IDENTIFIER ) and which are values ( TYPE_VALUE ). There is also a special use case type for literal values ( TYPE_LITERAL ). All element types are expressed via the Laminas\\Db\\Sql\\ExpressionInterface interface. Literals In Laminas 2.1, an actual Literal type was added. Laminas\\Db\\Sql now makes the distinction that literals will not have any parameters that need interpolating, while Expression objects might have parameters that need interpolating. In cases where there are parameters in an Expression , Laminas\\Db\\Sql\\AbstractSql will do its best to identify placeholders when the Expression is processed during statement creation. In short, if you don't have parameters, use Literal objects. The Where and Having API is that of Predicate and PredicateSet : // Where & Having extend Predicate: class Predicate extends PredicateSet { public $and; public $or; public $AND; public $OR; public $NEST; public $UNNEST; public function nest() : Predicate; public function setUnnest(Predicate $predicate) : void; public function unnest() : Predicate; public function equalTo( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function notEqualTo( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function lessThan( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function greaterThan( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function lessThanOrEqualTo( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function greaterThanOrEqualTo( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function like(string $identifier, string $like) : self; public function notLike(string $identifier, string $notLike) : self; public function literal(string $literal) : self; public function expression(string $expression, array $parameters = null) : self; public function isNull(string $identifier) : self; public function isNotNull(string $identifier) : self; public function in(string $identifier, array $valueSet = []) : self; public function notIn(string $identifier, array $valueSet = []) : self; public function between( string $identifier, int|float|string $minValue, int|float|string $maxValue ) : self; public function notBetween( string $identifier, int|float|string $minValue, int|float|string $maxValue ) : self; public function predicate(PredicateInterface $predicate) : self; // Inherited From PredicateSet public function addPredicate(PredicateInterface $predicate, $combination = null) : self; public function getPredicates() PredicateInterface[]; public function orPredicate(PredicateInterface $predicate) : self; public function andPredicate(PredicateInterface $predicate) : self; public function getExpressionData() : array; public function count() : int; } Each method in the API will produce a corresponding Predicate object of a similarly named type, as described below. equalTo(), lessThan(), greaterThan(), lessThanOrEqualTo(), greaterThanOrEqualTo() $where->equalTo('id', 5); // The above is equivalent to: $where->addPredicate( new Predicate\\Operator($left, Operator::OPERATOR_EQUAL_TO, $right, $leftType, $rightType) ); Operators use the following API: class Operator implements PredicateInterface { const OPERATOR_EQUAL_TO = '='; const OP_EQ = '='; const OPERATOR_NOT_EQUAL_TO = '!='; const OP_NE = '!='; const OPERATOR_LESS_THAN = '<'; const OP_LT = '<'; const OPERATOR_LESS_THAN_OR_EQUAL_TO = '<='; const OP_LTE = '<='; const OPERATOR_GREATER_THAN = '>'; const OP_GT = '>'; const OPERATOR_GREATER_THAN_OR_EQUAL_TO = '>='; const OP_GTE = '>='; public function __construct( int|float|bool|string $left = null, string $operator = self::OPERATOR_EQUAL_TO, int|float|bool|string $right = null, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ); public function setLeft(int|float|bool|string $left); public function getLeft() : int|float|bool|string; public function setLeftType(string $type) : self; public function getLeftType() : string; public function setOperator(string $operator); public function getOperator() : string; public function setRight(int|float|bool|string $value) : self; public function getRight() : int|float|bool|string; public function setRightType(string $type) : self; public function getRightType() : string; public function getExpressionData() : array; } like($identifier, $like), notLike($identifier, $notLike) $where->like($identifier, $like): // The above is equivalent to: $where->addPredicate( new Predicate\\Like($identifier, $like) ); The following is the Like API: class Like implements PredicateInterface { public function __construct(string $identifier = null, string $like = null); public function setIdentifier(string $identifier) : self; public function getIdentifier() : string; public function setLike(string $like) : self; public function getLike() : string; } literal($literal) $where->literal($literal); // The above is equivalent to: $where->addPredicate( new Predicate\\Literal($literal) ); The following is the Literal API: class Literal implements ExpressionInterface, PredicateInterface { const PLACEHOLDER = '?'; public function __construct(string $literal = ''); public function setLiteral(string $literal) : self; public function getLiteral() : string; } expression($expression, $parameter) $where->expression($expression, $parameter); // The above is equivalent to: $where->addPredicate( new Predicate\\Expression($expression, $parameter) ); The following is the Expression API: class Expression implements ExpressionInterface, PredicateInterface { const PLACEHOLDER = '?'; public function __construct( string $expression = null, int|float|bool|string|array $valueParameter = null /* [, $valueParameter, ... ] */ ); public function setExpression(string $expression) : self; public function getExpression() : string; public function setParameters(int|float|bool|string|array $parameters) : self; public function getParameters() : array; } isNull($identifier) $where->isNull($identifier); // The above is equivalent to: $where->addPredicate( new Predicate\\IsNull($identifier) ); The following is the IsNull API: class IsNull implements PredicateInterface { public function __construct(string $identifier = null); public function setIdentifier(string $identifier) : self; public function getIdentifier() : string; } isNotNull($identifier) $where->isNotNull($identifier); // The above is equivalent to: $where->addPredicate( new Predicate\\IsNotNull($identifier) ); The following is the IsNotNull API: class IsNotNull implements PredicateInterface { public function __construct(string $identifier = null); public function setIdentifier(string $identifier) : self; public function getIdentifier() : string; } in($identifier, $valueSet), notIn($identifier, $valueSet) $where->in($identifier, $valueSet); // The above is equivalent to: $where->addPredicate( new Predicate\\In($identifier, $valueSet) ); The following is the In API: class In implements PredicateInterface { public function __construct( string|array $identifier = null, array|Select $valueSet = null ); public function setIdentifier(string|array $identifier) : self; public function getIdentifier() : string|array; public function setValueSet(array|Select $valueSet) : self; public function getValueSet() : array|Select; } between($identifier, $minValue, $maxValue), notBetween($identifier, $minValue, $maxValue) $where->between($identifier, $minValue, $maxValue); // The above is equivalent to: $where->addPredicate( new Predicate\\Between($identifier, $minValue, $maxValue) ); The following is the Between API: class Between implements PredicateInterface { public function __construct( string $identifier = null, int|float|string $minValue = null, int|float|string $maxValue = null ); public function setIdentifier(string $identifier) : self; public function getIdentifier() : string; public function setMinValue(int|float|string $minValue) : self; public function getMinValue() : int|float|string; public function setMaxValue(int|float|string $maxValue) : self; public function getMaxValue() : int|float|string; public function setSpecification(string $specification); }","title":"SQL Abstraction"},{"location":"sql/#sql-abstraction","text":"Laminas\\Db\\Sql is a SQL abstraction layer for building platform-specific SQL queries via an object-oriented API. The end result of a Laminas\\Db\\Sql object will be to either produce a Statement and ParameterContainer that represents the target query, or a full string that can be directly executed against the database platform. To achieve this, Laminas\\Db\\Sql objects require a Laminas\\Db\\Adapter\\Adapter object in order to produce the desired results.","title":"SQL Abstraction"},{"location":"sql/#quick-start","text":"There are four primary tasks associated with interacting with a database defined by Data Manipulation Language (DML): selecting, inserting, updating, and deleting. As such, there are four primary classes that developers can interact with in order to build queries in the Laminas\\Db\\Sql namespace: Select , Insert , Update , and Delete . Since these four tasks are so closely related and generally used together within the same application, the Laminas\\Db\\Sql\\Sql class helps you create them and produce the result you are attempting to achieve. use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); // returns a Laminas\\Db\\Sql\\Select instance $insert = $sql->insert(); // returns a Laminas\\Db\\Sql\\Insert instance $update = $sql->update(); // returns a Laminas\\Db\\Sql\\Update instance $delete = $sql->delete(); // returns a Laminas\\Db\\Sql\\Delete instance As a developer, you can now interact with these objects, as described in the sections below, to customize each query. Once they have been populated with values, they are ready to either be prepared or executed. To prepare (using a Select object): use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(['id' => 2]); $statement = $sql->prepareStatementForSqlObject($select); $results = $statement->execute(); To execute (using a Select object) use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(['id' => 2]); $selectString = $sql->buildSqlString($select); $results = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE); Laminas\\\\Db\\\\Sql\\\\Sql objects can also be bound to a particular table so that in obtaining a Select , Insert , Update , or Delete instance, the object will be seeded with the table: use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter, 'foo'); $select = $sql->select(); $select->where(['id' => 2]); // $select already has from('foo') applied","title":"Quick start"},{"location":"sql/#common-interfaces-for-sql-implementations","text":"Each of these objects implements the following two interfaces: interface PreparableSqlInterface { public function prepareStatement(Adapter $adapter, StatementInterface $statement) : void; } interface SqlInterface { public function getSqlString(PlatformInterface $adapterPlatform = null) : string; } Use these functions to produce either (a) a prepared statement, or (b) a string to execute.","title":"Common interfaces for SQL implementations"},{"location":"sql/#select","text":"Laminas\\Db\\Sql\\Select presents a unified API for building platform-specific SQL SELECT queries. Instances may be created and consumed without Laminas\\Db\\Sql\\Sql : use Laminas\\Db\\Sql\\Select; $select = new Select(); // or, to produce a $select bound to a specific table $select = new Select('foo'); If a table is provided to the Select object, then from() cannot be called later to change the name of the table. Once you have a valid Select object, the following API can be used to further specify various select statement parts: class Select extends AbstractSql implements SqlInterface, PreparableSqlInterface { const JOIN_INNER = 'inner'; const JOIN_OUTER = 'outer'; const JOIN_FULL_OUTER = 'full outer'; const JOIN_LEFT = 'left'; const JOIN_RIGHT = 'right'; const SQL_STAR = '*'; const ORDER_ASCENDING = 'ASC'; const ORDER_DESCENDING = 'DESC'; public $where; // @param Where $where public function __construct(string|array|TableIdentifier $table = null); public function from(string|array|TableIdentifier $table) : self; public function columns(array $columns, bool $prefixColumnsWithTable = true) : self; public function join(string|array|TableIdentifier $name, string $on, string|array $columns = self::SQL_STAR, string $type = self::JOIN_INNER) : self; public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; public function group(string|array $group); public function having(Having|callable|string|array $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; public function order(string|array $order) : self; public function limit(int $limit) : self; public function offset(int $offset) : self; }","title":"Select"},{"location":"sql/#insert","text":"The Insert API: class Insert implements SqlInterface, PreparableSqlInterface { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public function __construct(string|TableIdentifier $table = null); public function into(string|TableIdentifier $table) : self; public function columns(array $columns) : self; public function values(array $values, string $flag = self::VALUES_SET) : self; } As with Select , the table may be provided during instantiation or via the into() method.","title":"Insert"},{"location":"sql/#update","text":"class Update { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public $where; // @param Where $where public function __construct(string|TableIdentifier $table = null); public function table(string|TableIdentifier $table) : self; public function set(array $values, string $flag = self::VALUES_SET) : self; public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; }","title":"Update"},{"location":"sql/#delete","text":"class Delete { public $where; // @param Where $where public function __construct(string|TableIdentifier $table = null); public function from(string|TableIdentifier $table); public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; }","title":"Delete"},{"location":"sql/#where-and-having","text":"In the following, we will talk about Where ; note, however, that Having utilizes the same API. Effectively, Where and Having extend from the same base object, a Predicate (and PredicateSet ). All of the parts that make up a WHERE or HAVING clause that are AND'ed or OR'd together are called predicates . The full set of predicates is called a PredicateSet . A Predicate generally contains the values (and identifiers) separate from the fragment they belong to until the last possible moment when the statement is either prepared (parameteritized) or executed. In parameterization, the parameters will be replaced with their proper placeholder (a named or positional parameter), and the values stored inside an Adapter\\ParameterContainer . When executed, the values will be interpolated into the fragments they belong to and properly quoted. In the Where / Having API, a distinction is made between what elements are considered identifiers ( TYPE_IDENTIFIER ) and which are values ( TYPE_VALUE ). There is also a special use case type for literal values ( TYPE_LITERAL ). All element types are expressed via the Laminas\\Db\\Sql\\ExpressionInterface interface.","title":"Where and Having"},{"location":"table-gateway/","text":"Table Gateways The Table Gateway subcomponent provides an object-oriented representation of a database table; its methods mirror the most common table operations. In code, the interface resembles: namespace Laminas\\Db\\TableGateway; use Laminas\\Db\\ResultSet\\ResultSetInterface; use Laminas\\Db\\Sql\\Where; interface TableGatewayInterface { public function getTable() : string; public function select(Where|callable|string|array $where = null) : ResultSetInterface; public function insert(array $set) : int; public function update( array $set, Where|callable|string|array $where = null, array $joins = null ) : int; public function delete(Where|callable|string|array $where) : int; } There are two primary implementations of the TableGatewayInterface , AbstractTableGateway and TableGateway . The AbstractTableGateway is an abstract basic implementation that provides functionality for select() , insert() , update() , delete() , as well as an additional API for doing these same kinds of tasks with explicit Laminas\\Db\\Sql objects: selectWith() , insertWith() , updateWith() , and deleteWith() . In addition, AbstractTableGateway also implements a \"Feature\" API, that allows for expanding the behaviors of the base TableGateway implementation without having to extend the class with this new functionality. The TableGateway concrete implementation simply adds a sensible constructor to the AbstractTableGateway class so that out-of-the-box, TableGateway does not need to be extended in order to be consumed and utilized to its fullest. Quick start The following example uses Laminas\\Db\\TableGateway\\TableGateway , which defines the following API: namespace Laminas\\Db\\TableGateway; use Laminas\\Db\\Adapter\\AdapterInterface; use Laminas\\Db\\ResultSet\\ResultSet; use Laminas\\Db\\ResultSet\\ResultSetInterface; use Laminas\\Db\\Sql; use Laminas\\Db\\Sql\\TableIdentifier; class TableGateway extends AbstractTableGateway { public $lastInsertValue; public $table; public $adapter; public function __construct( string|TableIdentifier $table, AdapterInterface $adapter, Feature\\AbstractFeature|Feature\\FeatureSet|Feature\\AbstractFeature[] $features = null, ResultSetInterface $resultSetPrototype = null, Sql\\Sql $sql = null ); /** Inherited from AbstractTableGateway */ public function isInitialized() : bool; public function initialize() : void; public function getTable() : string; public function getAdapter() : AdapterInterface; public function getColumns() : array; public function getFeatureSet() Feature\\FeatureSet; public function getResultSetPrototype() : ResultSetInterface; public function getSql() | Sql\\Sql; public function select(Sql\\Where|callable|string|array $where = null) : ResultSetInterface; public function selectWith(Sql\\Select $select) : ResultSetInterface; public function insert(array $set) : int; public function insertWith(Sql\\Insert $insert) | int; public function update( array $set, Sql\\Where|callable|string|array $where = null, array $joins = null ) : int; public function updateWith(Sql\\Update $update) : int; public function delete(Sql\\Where|callable|string|array $where) : int; public function deleteWith(Sql\\Delete $delete) : int; public function getLastInsertValue() : int; } The concrete TableGateway object uses constructor injection for getting dependencies and options into the instance. The table name and an instance of an Adapter are all that is required to create an instance. Out of the box, this implementation makes no assumptions about table structure or metadata, and when select() is executed, a simple ResultSet object with the populated Adapter 's Result (the datasource) will be returned and ready for iteration. use Laminas\\Db\\TableGateway\\TableGateway; $projectTable = new TableGateway('project', $adapter); $rowset = $projectTable->select(['type' => 'PHP']); echo 'Projects of type PHP: ' . PHP_EOL; foreach ($rowset as $projectRow) { echo $projectRow['name'] . PHP_EOL; } // Or, when expecting a single row: $artistTable = new TableGateway('artist', $adapter); $rowset = $artistTable->select(['id' => 2]); $artistRow = $rowset->current(); var_dump($artistRow); The select() method takes the same arguments as Laminas\\Db\\Sql\\Select::where() ; arguments will be passed to the Select instance used to build the SELECT query. This means the following is possible: use Laminas\\Db\\TableGateway\\TableGateway; use Laminas\\Db\\Sql\\Select; $artistTable = new TableGateway('artist', $adapter); // Search for at most 2 artists who's name starts with Brit, ascending: $rowset = $artistTable->select(function (Select $select) { $select->where->like('name', 'Brit%'); $select->order('name ASC')->limit(2); }); TableGateway Features The Features API allows for extending the functionality of the base TableGateway object without having to polymorphically extend the base class. This allows for a wider array of possible mixing and matching of features to achieve a particular behavior that needs to be attained to make the base implementation of TableGateway useful for a particular problem. With the TableGateway object, features should be injected through the constructor. The constructor can take features in 3 different forms: as a single Feature instance as a FeatureSet instance as an array of Feature instances There are a number of features built-in and shipped with laminas-db: GlobalAdapterFeature : the ability to use a global/static adapter without needing to inject it into a TableGateway instance. This is only useful when you are extending the AbstractTableGateway implementation: use Laminas\\Db\\TableGateway\\AbstractTableGateway; use Laminas\\Db\\TableGateway\\Feature; class MyTableGateway extends AbstractTableGateway { public function __construct() { $this->table = 'my_table'; $this->featureSet = new Feature\\FeatureSet(); $this->featureSet->addFeature(new Feature\\GlobalAdapterFeature()); $this->initialize(); } } // elsewhere in code, in a bootstrap Laminas\\Db\\TableGateway\\Feature\\GlobalAdapterFeature::setStaticAdapter($adapter); // in a controller, or model somewhere $table = new MyTableGateway(); // adapter is statically loaded MasterSlaveFeature : the ability to use a master adapter for insert() , update() , and delete() , but switch to a slave adapter for all select() operations. $table = new TableGateway('artist', $adapter, new Feature\\MasterSlaveFeature($slaveAdapter)); MetadataFeature : the ability populate TableGateway with column information from a Metadata object. It will also store the primary key information in case the RowGatewayFeature needs to consume this information. $table = new TableGateway('artist', $adapter, new Feature\\MetadataFeature()); EventFeature : the ability to compose a laminas-eventmanager EventManager instance within your TableGateway instance, and attach listeners to the various events of its lifecycle. See the section on lifecycle events below for more information on available events and the parameters they compose. $table = new TableGateway('artist', $adapter, new Feature\\EventFeature($eventManagerInstance)); RowGatewayFeature : the ability for select() to return a ResultSet object that upon iteration will return a RowGateway instance for each row. $table = new TableGateway('artist', $adapter, new Feature\\RowGatewayFeature('id')); $results = $table->select(['id' => 2]); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save(); TableGateway LifeCycle Events When the EventFeature is enabled on the TableGateway instance, you may attach to any of the following events, which provide access to the parameters listed. preInitialize (no parameters) postInitialize (no parameters) preSelect , with the following parameters: select , with type Laminas\\Db\\Sql\\Select postSelect , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface resultSet , with type Laminas\\Db\\ResultSet\\ResultSetInterface preInsert , with the following parameters: insert , with type Laminas\\Db\\Sql\\Insert postInsert , with the following parameters: statement with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result with type Laminas\\Db\\Adapter\\Driver\\ResultInterface preUpdate , with the following parameters: update , with type Laminas\\Db\\Sql\\Update postUpdate , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface preDelete , with the following parameters: delete , with type Laminas\\Db\\Sql\\Delete postDelete , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface Listeners receive a Laminas\\Db\\TableGateway\\Feature\\EventFeature\\TableGatewayEvent instance as an argument. Within the listener, you can retrieve a parameter by name from the event using the following syntax: $parameter = $event->getParam($paramName); As an example, you might attach a listener on the postInsert event as follows: use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\TableGateway\\Feature\\EventFeature\\TableGatewayEvent; use Laminas\\EventManager\\EventManager; /** @var EventManager $eventManager */ $eventManager->attach('postInsert', function (TableGatewayEvent $event) { /** @var ResultInterface $result */ $result = $event->getParam('result'); $generatedId = $result->getGeneratedValue(); // do something with the generated identifier... });","title":"Table Gateways"},{"location":"table-gateway/#table-gateways","text":"The Table Gateway subcomponent provides an object-oriented representation of a database table; its methods mirror the most common table operations. In code, the interface resembles: namespace Laminas\\Db\\TableGateway; use Laminas\\Db\\ResultSet\\ResultSetInterface; use Laminas\\Db\\Sql\\Where; interface TableGatewayInterface { public function getTable() : string; public function select(Where|callable|string|array $where = null) : ResultSetInterface; public function insert(array $set) : int; public function update( array $set, Where|callable|string|array $where = null, array $joins = null ) : int; public function delete(Where|callable|string|array $where) : int; } There are two primary implementations of the TableGatewayInterface , AbstractTableGateway and TableGateway . The AbstractTableGateway is an abstract basic implementation that provides functionality for select() , insert() , update() , delete() , as well as an additional API for doing these same kinds of tasks with explicit Laminas\\Db\\Sql objects: selectWith() , insertWith() , updateWith() , and deleteWith() . In addition, AbstractTableGateway also implements a \"Feature\" API, that allows for expanding the behaviors of the base TableGateway implementation without having to extend the class with this new functionality. The TableGateway concrete implementation simply adds a sensible constructor to the AbstractTableGateway class so that out-of-the-box, TableGateway does not need to be extended in order to be consumed and utilized to its fullest.","title":"Table Gateways"},{"location":"table-gateway/#quick-start","text":"The following example uses Laminas\\Db\\TableGateway\\TableGateway , which defines the following API: namespace Laminas\\Db\\TableGateway; use Laminas\\Db\\Adapter\\AdapterInterface; use Laminas\\Db\\ResultSet\\ResultSet; use Laminas\\Db\\ResultSet\\ResultSetInterface; use Laminas\\Db\\Sql; use Laminas\\Db\\Sql\\TableIdentifier; class TableGateway extends AbstractTableGateway { public $lastInsertValue; public $table; public $adapter; public function __construct( string|TableIdentifier $table, AdapterInterface $adapter, Feature\\AbstractFeature|Feature\\FeatureSet|Feature\\AbstractFeature[] $features = null, ResultSetInterface $resultSetPrototype = null, Sql\\Sql $sql = null ); /** Inherited from AbstractTableGateway */ public function isInitialized() : bool; public function initialize() : void; public function getTable() : string; public function getAdapter() : AdapterInterface; public function getColumns() : array; public function getFeatureSet() Feature\\FeatureSet; public function getResultSetPrototype() : ResultSetInterface; public function getSql() | Sql\\Sql; public function select(Sql\\Where|callable|string|array $where = null) : ResultSetInterface; public function selectWith(Sql\\Select $select) : ResultSetInterface; public function insert(array $set) : int; public function insertWith(Sql\\Insert $insert) | int; public function update( array $set, Sql\\Where|callable|string|array $where = null, array $joins = null ) : int; public function updateWith(Sql\\Update $update) : int; public function delete(Sql\\Where|callable|string|array $where) : int; public function deleteWith(Sql\\Delete $delete) : int; public function getLastInsertValue() : int; } The concrete TableGateway object uses constructor injection for getting dependencies and options into the instance. The table name and an instance of an Adapter are all that is required to create an instance. Out of the box, this implementation makes no assumptions about table structure or metadata, and when select() is executed, a simple ResultSet object with the populated Adapter 's Result (the datasource) will be returned and ready for iteration. use Laminas\\Db\\TableGateway\\TableGateway; $projectTable = new TableGateway('project', $adapter); $rowset = $projectTable->select(['type' => 'PHP']); echo 'Projects of type PHP: ' . PHP_EOL; foreach ($rowset as $projectRow) { echo $projectRow['name'] . PHP_EOL; } // Or, when expecting a single row: $artistTable = new TableGateway('artist', $adapter); $rowset = $artistTable->select(['id' => 2]); $artistRow = $rowset->current(); var_dump($artistRow); The select() method takes the same arguments as Laminas\\Db\\Sql\\Select::where() ; arguments will be passed to the Select instance used to build the SELECT query. This means the following is possible: use Laminas\\Db\\TableGateway\\TableGateway; use Laminas\\Db\\Sql\\Select; $artistTable = new TableGateway('artist', $adapter); // Search for at most 2 artists who's name starts with Brit, ascending: $rowset = $artistTable->select(function (Select $select) { $select->where->like('name', 'Brit%'); $select->order('name ASC')->limit(2); });","title":"Quick start"},{"location":"table-gateway/#tablegateway-features","text":"The Features API allows for extending the functionality of the base TableGateway object without having to polymorphically extend the base class. This allows for a wider array of possible mixing and matching of features to achieve a particular behavior that needs to be attained to make the base implementation of TableGateway useful for a particular problem. With the TableGateway object, features should be injected through the constructor. The constructor can take features in 3 different forms: as a single Feature instance as a FeatureSet instance as an array of Feature instances There are a number of features built-in and shipped with laminas-db: GlobalAdapterFeature : the ability to use a global/static adapter without needing to inject it into a TableGateway instance. This is only useful when you are extending the AbstractTableGateway implementation: use Laminas\\Db\\TableGateway\\AbstractTableGateway; use Laminas\\Db\\TableGateway\\Feature; class MyTableGateway extends AbstractTableGateway { public function __construct() { $this->table = 'my_table'; $this->featureSet = new Feature\\FeatureSet(); $this->featureSet->addFeature(new Feature\\GlobalAdapterFeature()); $this->initialize(); } } // elsewhere in code, in a bootstrap Laminas\\Db\\TableGateway\\Feature\\GlobalAdapterFeature::setStaticAdapter($adapter); // in a controller, or model somewhere $table = new MyTableGateway(); // adapter is statically loaded MasterSlaveFeature : the ability to use a master adapter for insert() , update() , and delete() , but switch to a slave adapter for all select() operations. $table = new TableGateway('artist', $adapter, new Feature\\MasterSlaveFeature($slaveAdapter)); MetadataFeature : the ability populate TableGateway with column information from a Metadata object. It will also store the primary key information in case the RowGatewayFeature needs to consume this information. $table = new TableGateway('artist', $adapter, new Feature\\MetadataFeature()); EventFeature : the ability to compose a laminas-eventmanager EventManager instance within your TableGateway instance, and attach listeners to the various events of its lifecycle. See the section on lifecycle events below for more information on available events and the parameters they compose. $table = new TableGateway('artist', $adapter, new Feature\\EventFeature($eventManagerInstance)); RowGatewayFeature : the ability for select() to return a ResultSet object that upon iteration will return a RowGateway instance for each row. $table = new TableGateway('artist', $adapter, new Feature\\RowGatewayFeature('id')); $results = $table->select(['id' => 2]); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save();","title":"TableGateway Features"},{"location":"table-gateway/#tablegateway-lifecycle-events","text":"When the EventFeature is enabled on the TableGateway instance, you may attach to any of the following events, which provide access to the parameters listed. preInitialize (no parameters) postInitialize (no parameters) preSelect , with the following parameters: select , with type Laminas\\Db\\Sql\\Select postSelect , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface resultSet , with type Laminas\\Db\\ResultSet\\ResultSetInterface preInsert , with the following parameters: insert , with type Laminas\\Db\\Sql\\Insert postInsert , with the following parameters: statement with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result with type Laminas\\Db\\Adapter\\Driver\\ResultInterface preUpdate , with the following parameters: update , with type Laminas\\Db\\Sql\\Update postUpdate , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface preDelete , with the following parameters: delete , with type Laminas\\Db\\Sql\\Delete postDelete , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface Listeners receive a Laminas\\Db\\TableGateway\\Feature\\EventFeature\\TableGatewayEvent instance as an argument. Within the listener, you can retrieve a parameter by name from the event using the following syntax: $parameter = $event->getParam($paramName); As an example, you might attach a listener on the postInsert event as follows: use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\TableGateway\\Feature\\EventFeature\\TableGatewayEvent; use Laminas\\EventManager\\EventManager; /** @var EventManager $eventManager */ $eventManager->attach('postInsert', function (TableGatewayEvent $event) { /** @var ResultInterface $result */ $result = $event->getParam('result'); $generatedId = $result->getGeneratedValue(); // do something with the generated identifier... });","title":"TableGateway LifeCycle Events"},{"location":"adapters/adapter-aware-trait/","text":"AdapterAwareTrait The trait Laminas\\Db\\Adapter\\AdapterAwareTrait , which provides implementation for Laminas\\Db\\Adapter\\AdapterAwareInterface , and allowed removal of duplicated implementations in several components of Laminas or in custom applications. The interface defines only the method setDbAdapter() with one parameter for an instance of Laminas\\Db\\Adapter\\Adapter : public function setDbAdapter(\\Laminas\\Db\\Adapter\\Adapter $adapter) : self; Basic Usage Create Class and Add Trait use Laminas\\Db\\Adapter\\AdapterAwareTrait; use Laminas\\Db\\Adapter\\AdapterAwareInterface; class Example implements AdapterAwareInterface { use AdapterAwareTrait; } Create and Set Adapter Create a database adapter and set the adapter to the instance of the Example class: $adapter = new Laminas\\Db\\Adapter\\Adapter([ 'driver' => 'Pdo_Sqlite', 'database' => 'path/to/sqlite.db', ]); $example = new Example(); $example->setAdapter($adapter); AdapterServiceDelegator The delegator Laminas\\Db\\Adapter\\AdapterServiceDelegator can be used to set a database adapter via the service manager of laminas-servicemanager . The delegator tries to fetch a database adapter via the name Laminas\\Db\\Adapter\\AdapterInterface from the service container and sets the adapter to the requested service. The adapter itself must be an instance of Laminas\\Db\\Adapter\\Adapter . Integration for Mezzio and laminas-mvc based Applications In a Mezzio or laminas-mvc based application the database adapter is already registered during the installation with the laminas-component-installer. Create Class and Use Trait Create a class and add the trait AdapterAwareTrait . use Laminas\\Db\\Adapter\\Adapter; use Laminas\\Db\\Adapter\\AdapterInterface; class Example implements AdapterAwareInterface { use AdapterAwareTrait; public function getAdapter() : ?Adapter { return $this->adapter; } } (A getter method is also added for demonstration.) Create and Configure Service Manager Create and configured the service manager : use Interop\\Container\\ContainerInterface; use Laminas\\Db\\Adapter\\AdapterInterface; use Laminas\\Db\\Adapter\\AdapterServiceDelegator; use Laminas\\Db\\Adapter\\AdapterAwareTrait; use Laminas\\Db\\Adapter\\AdapterAwareInterface; $serviceManager = new Laminas\\ServiceManager\\ServiceManager([ 'factories' => [ // Database adapter AdapterInterface::class => static function(ContainerInterface $container) { return new Laminas\\Db\\Adapter\\Adapter([ 'driver' => 'Pdo_Sqlite', 'database' => 'path/to/sqlite.db', ]); } ], 'invokables' => [ // Example class Example::class => Example::class, ], 'delegators' => [ // Delegator for Example class to set the adapter Example::class => [ AdapterServiceDelegator::class, ], ], ]); Get Instance of Class Retrieving an instance of the Example class with a database adapter: /** @var Example $example */ $example = $serviceManager->get(Example::class); var_dump($example->getAdapter() instanceof Laminas\\Db\\Adapter\\Adapter); // true Concrete Implementations The validators Db\\RecordExists and Db\\NoRecordExists implements the trait and the plugin manager of laminas-validator includes the delegator to set the database adapter for both validators.","title":"AdapterAwareTrait"},{"location":"adapters/adapter-aware-trait/#adapterawaretrait","text":"The trait Laminas\\Db\\Adapter\\AdapterAwareTrait , which provides implementation for Laminas\\Db\\Adapter\\AdapterAwareInterface , and allowed removal of duplicated implementations in several components of Laminas or in custom applications. The interface defines only the method setDbAdapter() with one parameter for an instance of Laminas\\Db\\Adapter\\Adapter : public function setDbAdapter(\\Laminas\\Db\\Adapter\\Adapter $adapter) : self;","title":"AdapterAwareTrait"},{"location":"adapters/adapter-aware-trait/#basic-usage","text":"","title":"Basic Usage"},{"location":"adapters/adapter-aware-trait/#adapterservicedelegator","text":"The delegator Laminas\\Db\\Adapter\\AdapterServiceDelegator can be used to set a database adapter via the service manager of laminas-servicemanager . The delegator tries to fetch a database adapter via the name Laminas\\Db\\Adapter\\AdapterInterface from the service container and sets the adapter to the requested service. The adapter itself must be an instance of Laminas\\Db\\Adapter\\Adapter .","title":"AdapterServiceDelegator"},{"location":"adapters/adapter-aware-trait/#concrete-implementations","text":"The validators Db\\RecordExists and Db\\NoRecordExists implements the trait and the plugin manager of laminas-validator includes the delegator to set the database adapter for both validators.","title":"Concrete Implementations"},{"location":"application-integration/usage-in-a-laminas-mvc-application/","text":"Usage in a laminas-mvc Application The minimal installation for a laminas-mvc based application doesn't include any database features. When installing the Laminas MVC Skeleton Application While Composer is installing the MVC Application , you can add the laminas-db package while prompted. Adding to an existing Laminas MVC Skeleton Application If the MVC application is already created, then use Composer to add the laminas-db package. The Abstract Factory Now that the laminas-db package is installed, the abstract factory Laminas\\Db\\Adapter\\AdapterAbstractServiceFactory is available to be used with the service configuration. Configuring the adapter The abstract factory expects the configuration key db in order to create a Laminas\\Db\\Adapter\\Adapter instance. Working with a Sqlite database Sqlite is a lightweight option to have the application working with a database. Here is an example of the configuration array for a sqlite database. Assuming the sqlite file path is data/sample.sqlite , the following configuration will produce the adapter: return [ 'db' => [ 'driver' => 'Pdo', 'adapters' => [ sqliteAdapter::class => [ 'driver' => 'Pdo', 'dsn' => 'sqlite:data/sample.sqlite', ], ], ], ]; The data/ filepath for the sqlite file is the default data/ directory from the Laminas MVC application. Working with a MySQL database Unlike a sqlite database, the MySQL database adapter requires a MySQL server. Here is an example of a configuration array for a MySQL database. return [ 'db' => [ 'driver' => 'Pdo', 'adapters' => [ mysqlAdapter::class => [ 'driver' => 'Pdo', 'dsn' => 'mysql:dbname=your_database_name;host=your_mysql_host;charset=utf8', 'username' => 'your_mysql_username', 'password' => 'your_mysql_password', 'driver_options' => [ PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \\'UTF8\\'' ], ], ], ], ]; Working with the adapter Once you have configured an adapter, as in the above examples, you now have a Laminas\\Db\\Adapter\\Adapter available to your application. A factory for a class that consumes an adapter can pull the adapter by the name used in configuration. As an example, for the sqlite database configured earlier, we could write the following: use sqliteAdapter ; $adapter = $container->get(sqliteAdapter::class) ; For the MySQL Database configured earlier: use mysqlAdapter ; $adapter = $container->get(mysqlAdapter::class) ; You can read more about the adapter in the adapter chapter of the documentation . Running with Docker When working with a MySQL database and when running the application with Docker, some files need to be added or adjusted. Adding the MySQL extension to the PHP container Change the Dockerfile to add the PDO MySQL extension to PHP. FROM php:7.3-apache RUN apt-get update \\ && apt-get install -y git zlib1g-dev libzip-dev \\ && docker-php-ext-install zip pdo_mysql \\ && a2enmod rewrite \\ && sed -i 's!/var/www/html!/var/www/public!g' /etc/apache2/sites-available/000-default.conf \\ && mv /var/www/html /var/www/public \\ && curl -sS https://getcomposer.org/installer \\ | php -- --install-dir=/usr/local/bin --filename=composer WORKDIR /var/www Adding the mysql container Change the docker-compose.yml file to add a new container for mysql. mysql: image: mysql ports: - 3306:3306 command: --default-authentication-plugin=mysql_native_password volumes: - ./.data/db:/var/lib/mysql - ./.docker/mysql/:/docker-entrypoint-initdb.d/ environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} Though it is not the topic to explain how to write a docker-compose.yml file, a few details need to be highlighted : The name of the container is mysql . MySQL database files will be stored in the directory /.data/db/ . SQL schemas will need to be added to the /.docker/mysql/ directory so that Docker will be able to build and populate the database(s). The mysql docker image is using the $MYSQL_ROOT_PASSWORD environment variable to set the mysql root password. Link the containers Now link the mysql container and the laminas container so that the application knows where to find the mysql server. laminas: build: context: . dockerfile: Dockerfile ports: - 8080:80 volumes: - .:/var/www links: - mysql:mysql Adding phpMyAdmin Optionnally, you can also add a container for phpMyAdmin. phpmyadmin: image: phpmyadmin/phpmyadmin ports: - 8081:80 environment: - PMA_HOST=${PMA_HOST} The image uses the $PMA_HOST environment variable to set the host of the mysql server. The expected value is the name of the mysql container. Putting everything together: version: \"2.1\" services: laminas: build: context: . dockerfile: Dockerfile ports: - 8080:80 volumes: - .:/var/www links: - mysql:mysql mysql: image: mysql ports: - 3306:3306 command: --default-authentication-plugin=mysql_native_password volumes: - ./.data/db:/var/lib/mysql - ./.docker/mysql/:/docker-entrypoint-initdb.d/ environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} phpmyadmin: image: phpmyadmin/phpmyadmin ports: - 8081:80 environment: - PMA_HOST=${PMA_HOST} Defining credentials The docker-compose.yml file uses ENV variables to define the credentials. Docker will read the ENV variables from a .env file. MYSQL_ROOT_PASSWORD=rootpassword PMA_HOST=mysql Initiating the database schemas At build, if the /.data/db directory is missing, Docker will create the mysql database with any .sql files found in the .docker/mysql/ directory. (These are the files with the CREATE DATABASE , USE (database) , and CREATE TABLE, INSERT INTO directives defined earlier in this document). If multiple .sql files are present, it is a good idea to safely order the list because Docker will read the files in ascending order.","title":"Integrating in a Laminas MVC application"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#usage-in-a-laminas-mvc-application","text":"The minimal installation for a laminas-mvc based application doesn't include any database features.","title":"Usage in a laminas-mvc Application"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#when-installing-the-laminas-mvc-skeleton-application","text":"While Composer is installing the MVC Application , you can add the laminas-db package while prompted.","title":"When installing the Laminas MVC Skeleton Application"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#adding-to-an-existing-laminas-mvc-skeleton-application","text":"If the MVC application is already created, then use Composer to add the laminas-db package.","title":"Adding to an existing Laminas MVC Skeleton Application"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#the-abstract-factory","text":"Now that the laminas-db package is installed, the abstract factory Laminas\\Db\\Adapter\\AdapterAbstractServiceFactory is available to be used with the service configuration.","title":"The Abstract Factory"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#working-with-the-adapter","text":"Once you have configured an adapter, as in the above examples, you now have a Laminas\\Db\\Adapter\\Adapter available to your application. A factory for a class that consumes an adapter can pull the adapter by the name used in configuration. As an example, for the sqlite database configured earlier, we could write the following: use sqliteAdapter ; $adapter = $container->get(sqliteAdapter::class) ; For the MySQL Database configured earlier: use mysqlAdapter ; $adapter = $container->get(mysqlAdapter::class) ; You can read more about the adapter in the adapter chapter of the documentation .","title":"Working with the adapter"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#running-with-docker","text":"When working with a MySQL database and when running the application with Docker, some files need to be added or adjusted.","title":"Running with Docker"}]} \ No newline at end of file +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"laminas-db 🇷🇺 Русским гражданам Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм. У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую. Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите \"Нет войне!\" 🇺🇸 To Citizens of Russia We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism. One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences. You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say \"stop the war!\" Laminas\\Db is a component that abstract the access to a Database using an object oriented API to build the queries. Laminas\\Db consumes different storage adapters to access different database vendors such as MySQL, PostgreSQL, Oracle, IBM DB2, Microsoft Sql Server, PDO, etc. Contributing Please be sure to read the contributor's guide for general information on contributing. This section outlines specifics for laminas-db. Test suites The phpunit.xml.dist file defines two test suites, \"unit test\" and \"integration test\". You can run one or the other using the --testsuite option to phpunit : $ ./vendor/bin/phpunit --testsuite \"unit test\" # unit tests only $ ./vendor/bin/phpunit --testsuite \"integration test\" # integration tests only Unit tests do not require additional functionality beyond having the appropriate database extensions present and loaded in your PHP binary. Integration tests To run the integration tests, you need databases. The repository includes a Vagrantfile which allows you to fire up a vagrant box with several of our target databases, including: MySQL PostgreSQL SQL Server To start up vagrant: $ vagrant up Copy phpunit.xml.dist to phpunit.xml , and change the following ENV var declaration values to \"true\": TESTS_LAMINAS_DB_ADAPTER_DRIVER_MYSQL TESTS_LAMINAS_DB_ADAPTER_DRIVER_SQLSRV TESTS_LAMINAS_DB_ADAPTER_DRIVER_PGSQL TESTS_LAMINAS_DB_ADAPTER_DRIVER_SQLITE_MEMORY From there, you can run the integration tests: $ ./vendor/bin/phpunit --testsuite \"integration test\" File issues at https://github.com/laminas/laminas-db/issues Documentation is at https://docs.laminas.dev/laminas-db/","title":"Home"},{"location":"#laminas-db","text":"","title":"laminas-db"},{"location":"#_1","text":"Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм. У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую. Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите \"Нет войне!\"","title":"🇷🇺 Русским гражданам"},{"location":"#to-citizens-of-russia","text":"We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism. One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences. You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say \"stop the war!\" Laminas\\Db is a component that abstract the access to a Database using an object oriented API to build the queries. Laminas\\Db consumes different storage adapters to access different database vendors such as MySQL, PostgreSQL, Oracle, IBM DB2, Microsoft Sql Server, PDO, etc.","title":"🇺🇸 To Citizens of Russia"},{"location":"#contributing","text":"Please be sure to read the contributor's guide for general information on contributing. This section outlines specifics for laminas-db.","title":"Contributing"},{"location":"adapter/","text":"Adapters Laminas\\Db\\Adapter\\Adapter is the central object of the laminas-db component. It is responsible for adapting any code written in or for laminas-db to the targeted PHP extensions and vendor databases. In doing this, it creates an abstraction layer for the PHP extensions in the Driver subnamespace of Laminas\\Db\\Adapter . It also creates a lightweight \"Platform\" abstraction layer, for the various idiosyncrasies that each vendor-specific platform might have in its SQL/RDBMS implementation, separate from the driver implementations. Creating an adapter using configuration Create an adapter by instantiating the Laminas\\Db\\Adapter\\Adapter class. The most common use case, while not the most explicit, is to pass an array of configuration to the Adapter : use Laminas\\Db\\Adapter\\Adapter; $adapter = new Adapter($configArray); This driver array is an abstraction for the extension level required parameters. Here is a table for the key-value pairs that should be in configuration array. Key Is Required? Value driver required Mysqli , Sqlsrv , Pdo_Sqlite , Pdo_Mysql , Pdo (= Other PDO Driver) database generally required the name of the database (schema) username generally required the connection username password generally required the connection password hostname not generally required the IP address or hostname to connect to port not generally required the port to connect to (if applicable) charset not generally required the character set to use Options are adapter-dependent Other names will work as well. Effectively, if the PHP manual uses a particular naming, this naming will be supported by the associated driver. For example, dbname in most cases will also work for 'database'. Another example is that in the case of Sqlsrv , UID will work in place of username . Which format you choose is up to you, but the above table represents the official abstraction names. For example, a MySQL connection using ext/mysqli: $adapter = new Laminas\\Db\\Adapter\\Adapter([ 'driver' => 'Mysqli', 'database' => 'laminas_db_example', 'username' => 'developer', 'password' => 'developer-password', ]); Another example, of a Sqlite connection via PDO: $adapter = new Laminas\\Db\\Adapter\\Adapter([ 'driver' => 'Pdo_Sqlite', 'database' => 'path/to/sqlite.db', ]); Another example, of an IBM i DB2 connection via IbmDb2: $adapter = new Laminas\\Db\\Adapter\\Adapter([ 'database' => '*LOCAL', // or name from WRKRDBDIRE, may be serial # 'driver' => 'IbmDb2', 'driver_options' => [ 'autocommit' => DB2_AUTOCOMMIT_ON, 'i5_naming' => DB2_I5_NAMING_ON, 'i5_libl' => 'SCHEMA1 SCHEMA2 SCHEMA3', ], 'username' => '__USER__', 'password' => '__PASS__', // 'persistent' => true, 'platform' => 'IbmDb2', 'platform_options' => ['quote_identifiers' => false], ]); Another example, of an IBM i DB2 connection via PDO: $adapter = new Laminas\\Db\\Adapter\\Adapter([ 'dsn' => 'ibm:DB_NAME', // DB_NAME is from WRKRDBDIRE, may be serial # 'driver' => 'pdo', 'driver_options' => [ // PDO::ATTR_PERSISTENT => true, PDO::ATTR_AUTOCOMMIT => true, PDO::I5_ATTR_DBC_SYS_NAMING => true, PDO::I5_ATTR_DBC_CURLIB => '', PDO::I5_ATTR_DBC_LIBL => 'SCHEMA1 SCHEMA2 SCHEMA3', ], 'username' => '__USER__', 'password' => '__PASS__', 'platform' => 'IbmDb2', 'platform_options' => ['quote_identifiers' => false], ]); It is important to know that by using this style of adapter creation, the Adapter will attempt to create any dependencies that were not explicitly provided. A Driver object will be created from the configuration array provided in the constructor. A Platform object will be created based off the type of Driver class that was instantiated. And lastly, a default ResultSet object is created and utilized. Any of these objects can be injected, to do this, see the next section. The list of officially supported drivers: IbmDb2 : The ext/ibm_db2 driver Mysqli : The ext/mysqli driver Oci8 : The ext/oci8 driver Pgsql : The ext/pgsql driver Sqlsrv : The ext/sqlsrv driver (from Microsoft) Pdo_Mysql : MySQL via the PDO extension Pdo_Sqlite : SQLite via the PDO extension Pdo_Pgsql : PostgreSQL via the PDO extension Creating an adapter using dependency injection The more mezzio and explicit way of creating an adapter is by injecting all your dependencies up front. Laminas\\Db\\Adapter\\Adapter uses constructor injection, and all required dependencies are injected through the constructor, which has the following signature (in pseudo-code): use Laminas\\Db\\Adapter\\Platform\\PlatformInterface; use Laminas\\Db\\ResultSet\\ResultSet; class Laminas\\Db\\Adapter\\Adapter { public function __construct( $driver, PlatformInterface $platform = null, ResultSet $queryResultSetPrototype = null ); } What can be injected: $driver : an array of connection parameters (see above) or an instance of Laminas\\Db\\Adapter\\Driver\\DriverInterface . $platform (optional): an instance of Laminas\\Db\\Platform\\PlatformInterface ; the default will be created based off the driver implementation. $queryResultSetPrototype (optional): an instance of Laminas\\Db\\ResultSet\\ResultSet ; to understand this object's role, see the section below on querying. Query Preparation By default, Laminas\\Db\\Adapter\\Adapter::query() prefers that you use \"preparation\" as a means for processing SQL statements. This generally means that you will supply a SQL statement containing placeholders for the values, and separately provide substitutions for those placeholders. As an example: $adapter->query('SELECT * FROM `artist` WHERE `id` = ?', [5]); The above example will go through the following steps: create a new Statement object. prepare the array [5] into a ParameterContainer if necessary. inject the ParameterContainer into the Statement object. execute the Statement object, producing a Result object. check the Result object to check if the supplied SQL was a result set producing statement: if the query produced a result set, clone the ResultSet prototype, inject the Result as its datasource, and return the new ResultSet instance. otherwise, return the Result . Query Execution In some cases, you have to execute statements directly without preparation. One possible reason for doing so would be to execute a DDL statement, as most extensions and RDBMS systems are incapable of preparing such statements. To execute a query without the preparation step, you will need to pass a flag as the second argument indicating execution is required: $adapter->query( 'ALTER TABLE ADD INDEX(`foo_index`) ON (`foo_column`)', Adapter::QUERY_MODE_EXECUTE ); The primary difference to notice is that you must provide the Adapter::QUERY_MODE_EXECUTE (execute) flag as the second parameter. Creating Statements While query() is highly useful for one-off and quick querying of a database via the Adapter , it generally makes more sense to create a statement and interact with it directly, so that you have greater control over the prepare-then-execute workflow. To do this, Adapter gives you a routine called createStatement() that allows you to create a Driver specific Statement to use so you can manage your own prepare-then-execute workflow. // with optional parameters to bind up-front: $statement = $adapter->createStatement($sql, $optionalParameters); $result = $statement->execute(); Using the Driver Object The Driver object is the primary place where Laminas\\Db\\Adapter\\Adapter implements the connection level abstraction specific to a given extension. To make this possible, each driver is composed of 3 objects: A connection: Laminas\\Db\\Adapter\\Driver\\ConnectionInterface A statement: Laminas\\Db\\Adapter\\Driver\\StatementInterface A result: Laminas\\Db\\Adapter\\Driver\\ResultInterface Each of the built-in drivers practice \"prototyping\" as a means of creating objects when new instances are requested. The workflow looks like this: An adapter is created with a set of connection parameters. The adapter chooses the proper driver to instantiate (for example, Laminas\\Db\\Adapter\\Driver\\Mysqli ) That driver class is instantiated. If no connection, statement, or result objects are injected, defaults are instantiated. This driver is now ready to be called on when particular workflows are requested. Here is what the Driver API looks like: namespace Laminas\\Db\\Adapter\\Driver; interface DriverInterface { const PARAMETERIZATION_POSITIONAL = 'positional'; const PARAMETERIZATION_NAMED = 'named'; const NAME_FORMAT_CAMELCASE = 'camelCase'; const NAME_FORMAT_NATURAL = 'natural'; public function getDatabasePlatformName(string $nameFormat = self::NAME_FORMAT_CAMELCASE) : string; public function checkEnvironment() : bool; public function getConnection() : ConnectionInterface; public function createStatement(string|resource $sqlOrResource = null) : StatementInterface; public function createResult(resource $resource) : ResultInterface; public function getPrepareType() :string; public function formatParameterName(string $name, $type = null) : string; public function getLastGeneratedValue() : mixed; } From this DriverInterface , you can Determine the name of the platform this driver supports (useful for choosing the proper platform object). Check that the environment can support this driver. Return the Connection instance. Create a Statement instance which is optionally seeded by an SQL statement (this will generally be a clone of a prototypical statement object). Create a Result object which is optionally seeded by a statement resource (this will generally be a clone of a prototypical result object) Format parameter names; this is important to distinguish the difference between the various ways parameters are named between extensions Retrieve the overall last generated value (such as an auto-increment value). Now let's turn to the Statement API: namespace Laminas\\Db\\Adapter\\Driver; interface StatementInterface extends StatementContainerInterface { public function getResource() : resource; public function prepare($sql = null) : void; public function isPrepared() : bool; public function execute(null|array|ParameterContainer $parameters = null) : ResultInterface; /** Inherited from StatementContainerInterface */ public function setSql(string $sql) : void; public function getSql() : string; public function setParameterContainer(ParameterContainer $parameterContainer) : void; public function getParameterContainer() : ParameterContainer; } And finally, the Result API: namespace Laminas\\Db\\Adapter\\Driver; use Countable; use Iterator; interface ResultInterface extends Countable, Iterator { public function buffer() : void; public function isQueryResult() : bool; public function getAffectedRows() : int; public function getGeneratedValue() : mixed; public function getResource() : resource; public function getFieldCount() : int; } Using The Platform Object The Platform object provides an API to assist in crafting queries in a way that is specific to the SQL implementation of a particular vendor. The object handles nuances such as how identifiers or values are quoted, or what the identifier separator character is. To get an idea of the capabilities, the interface for a platform object looks like this: namespace Laminas\\Db\\Adapter\\Platform; interface PlatformInterface { public function getName() : string; public function getQuoteIdentifierSymbol() : string; public function quoteIdentifier(string $identifier) : string; public function quoteIdentifierChain(string|string[] $identiferChain) : string; public function getQuoteValueSymbol() : string; public function quoteValue(string $value) : string; public function quoteTrustedValue(string $value) : string; public function quoteValueList(string|string[] $valueList) : string; public function getIdentifierSeparator() : string; public function quoteIdentifierInFragment(string $identifier, array $additionalSafeWords = []) : string; } While you can directly instantiate a Platform object, generally speaking, it is easier to get the proper Platform instance from the configured adapter (by default the Platform type will match the underlying driver implementation): $platform = $adapter->getPlatform(); // or $platform = $adapter->platform; // magic property access The following are examples of Platform usage: // $adapter is a Laminas\\Db\\Adapter\\Adapter instance; // $platform is a Laminas\\Db\\Adapter\\Platform\\Sql92 instance. $platform = $adapter->getPlatform(); // \"first_name\" echo $platform->quoteIdentifier('first_name'); // \" echo $platform->getQuoteIdentifierSymbol(); // \"schema\".\"mytable\" echo $platform->quoteIdentifierChain(['schema', 'mytable']); // ' echo $platform->getQuoteValueSymbol(); // 'myvalue' echo $platform->quoteValue('myvalue'); // 'value', 'Foo O\\\\'Bar' echo $platform->quoteValueList(['value', \"Foo O'Bar\"]); // . echo $platform->getIdentifierSeparator(); // \"foo\" as \"bar\" echo $platform->quoteIdentifierInFragment('foo as bar'); // additionally, with some safe words: // (\"foo\".\"bar\" = \"boo\".\"baz\") echo $platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', ['(', ')', '=']); Using The Parameter Container The ParameterContainer object is a container for the various parameters that need to be passed into a Statement object to fulfill all the various parameterized parts of the SQL statement. This object implements the ArrayAccess interface. Below is the ParameterContainer API: namespace Laminas\\Db\\Adapter; use ArrayAccess; use ArrayIterator; use Countable; use Iterator; class ParameterContainer implements Iterator, ArrayAccess, Countable { public function __construct(array $data = []) /** methods to interact with values */ public function offsetExists(string|int $name) : bool; public function offsetGet(string|int $name) : mixed; public function offsetSetReference(string|int $name, string|int $from) : void; public function offsetSet(string|int $name, mixed $value, mixed $errata = null, int $maxLength = null) : void; public function offsetUnset(string|int $name) : void; /** set values from array (will reset first) */ public function setFromArray(array $data) : ParameterContainer; /** methods to interact with value errata */ public function offsetSetErrata(string|int $name, mixed $errata) : void; public function offsetGetErrata(string|int $name) : mixed; public function offsetHasErrata(string|int $name) : bool; public function offsetUnsetErrata(string|int $name) : void; /** errata only iterator */ public function getErrataIterator() : ArrayIterator; /** get array with named keys */ public function getNamedArray() : array; /** get array with int keys, ordered by position */ public function getPositionalArray() : array; /** iterator: */ public function count() : int; public function current() : mixed; public function next() : mixed; public function key() : string|int; public function valid() : bool; public function rewind() : void; /** merge existing array of parameters with existing parameters */ public function merge(array $parameters) : ParameterContainer; } In addition to handling parameter names and values, the container will assist in tracking parameter types for PHP type to SQL type handling. For example, it might be important that: $container->offsetSet('limit', 5); be bound as an integer. To achieve this, pass in the ParameterContainer::TYPE_INTEGER constant as the 3rd parameter: $container->offsetSet('limit', 5, $container::TYPE_INTEGER); This will ensure that if the underlying driver supports typing of bound parameters, that this translated information will also be passed along to the actual php database driver. Examples Creating a Driver , a vendor-portable query, and preparing and iterating the result: $adapter = new Laminas\\Db\\Adapter\\Adapter($driverConfig); $qi = function ($name) use ($adapter) { return $adapter->platform->quoteIdentifier($name); }; $fp = function ($name) use ($adapter) { return $adapter->driver->formatParameterName($name); }; $sql = 'UPDATE ' . $qi('artist') . ' SET ' . $qi('name') . ' = ' . $fp('name') . ' WHERE ' . $qi('id') . ' = ' . $fp('id'); $statement = $adapter->query($sql); $parameters = [ 'name' => 'Updated Artist', 'id' => 1, ]; $statement->execute($parameters); // DATA INSERTED, NOW CHECK $statement = $adapter->query( 'SELECT * FROM ' . $qi('artist') . ' WHERE id = ' . $fp('id') ); $results = $statement->execute(['id' => 1]); $row = $results->current(); $name = $row['name'];","title":"Introduction"},{"location":"adapter/#adapters","text":"Laminas\\Db\\Adapter\\Adapter is the central object of the laminas-db component. It is responsible for adapting any code written in or for laminas-db to the targeted PHP extensions and vendor databases. In doing this, it creates an abstraction layer for the PHP extensions in the Driver subnamespace of Laminas\\Db\\Adapter . It also creates a lightweight \"Platform\" abstraction layer, for the various idiosyncrasies that each vendor-specific platform might have in its SQL/RDBMS implementation, separate from the driver implementations.","title":"Adapters"},{"location":"adapter/#creating-an-adapter-using-configuration","text":"Create an adapter by instantiating the Laminas\\Db\\Adapter\\Adapter class. The most common use case, while not the most explicit, is to pass an array of configuration to the Adapter : use Laminas\\Db\\Adapter\\Adapter; $adapter = new Adapter($configArray); This driver array is an abstraction for the extension level required parameters. Here is a table for the key-value pairs that should be in configuration array. Key Is Required? Value driver required Mysqli , Sqlsrv , Pdo_Sqlite , Pdo_Mysql , Pdo (= Other PDO Driver) database generally required the name of the database (schema) username generally required the connection username password generally required the connection password hostname not generally required the IP address or hostname to connect to port not generally required the port to connect to (if applicable) charset not generally required the character set to use","title":"Creating an adapter using configuration"},{"location":"adapter/#creating-an-adapter-using-dependency-injection","text":"The more mezzio and explicit way of creating an adapter is by injecting all your dependencies up front. Laminas\\Db\\Adapter\\Adapter uses constructor injection, and all required dependencies are injected through the constructor, which has the following signature (in pseudo-code): use Laminas\\Db\\Adapter\\Platform\\PlatformInterface; use Laminas\\Db\\ResultSet\\ResultSet; class Laminas\\Db\\Adapter\\Adapter { public function __construct( $driver, PlatformInterface $platform = null, ResultSet $queryResultSetPrototype = null ); } What can be injected: $driver : an array of connection parameters (see above) or an instance of Laminas\\Db\\Adapter\\Driver\\DriverInterface . $platform (optional): an instance of Laminas\\Db\\Platform\\PlatformInterface ; the default will be created based off the driver implementation. $queryResultSetPrototype (optional): an instance of Laminas\\Db\\ResultSet\\ResultSet ; to understand this object's role, see the section below on querying.","title":"Creating an adapter using dependency injection"},{"location":"adapter/#query-preparation","text":"By default, Laminas\\Db\\Adapter\\Adapter::query() prefers that you use \"preparation\" as a means for processing SQL statements. This generally means that you will supply a SQL statement containing placeholders for the values, and separately provide substitutions for those placeholders. As an example: $adapter->query('SELECT * FROM `artist` WHERE `id` = ?', [5]); The above example will go through the following steps: create a new Statement object. prepare the array [5] into a ParameterContainer if necessary. inject the ParameterContainer into the Statement object. execute the Statement object, producing a Result object. check the Result object to check if the supplied SQL was a result set producing statement: if the query produced a result set, clone the ResultSet prototype, inject the Result as its datasource, and return the new ResultSet instance. otherwise, return the Result .","title":"Query Preparation"},{"location":"adapter/#query-execution","text":"In some cases, you have to execute statements directly without preparation. One possible reason for doing so would be to execute a DDL statement, as most extensions and RDBMS systems are incapable of preparing such statements. To execute a query without the preparation step, you will need to pass a flag as the second argument indicating execution is required: $adapter->query( 'ALTER TABLE ADD INDEX(`foo_index`) ON (`foo_column`)', Adapter::QUERY_MODE_EXECUTE ); The primary difference to notice is that you must provide the Adapter::QUERY_MODE_EXECUTE (execute) flag as the second parameter.","title":"Query Execution"},{"location":"adapter/#creating-statements","text":"While query() is highly useful for one-off and quick querying of a database via the Adapter , it generally makes more sense to create a statement and interact with it directly, so that you have greater control over the prepare-then-execute workflow. To do this, Adapter gives you a routine called createStatement() that allows you to create a Driver specific Statement to use so you can manage your own prepare-then-execute workflow. // with optional parameters to bind up-front: $statement = $adapter->createStatement($sql, $optionalParameters); $result = $statement->execute();","title":"Creating Statements"},{"location":"adapter/#using-the-driver-object","text":"The Driver object is the primary place where Laminas\\Db\\Adapter\\Adapter implements the connection level abstraction specific to a given extension. To make this possible, each driver is composed of 3 objects: A connection: Laminas\\Db\\Adapter\\Driver\\ConnectionInterface A statement: Laminas\\Db\\Adapter\\Driver\\StatementInterface A result: Laminas\\Db\\Adapter\\Driver\\ResultInterface Each of the built-in drivers practice \"prototyping\" as a means of creating objects when new instances are requested. The workflow looks like this: An adapter is created with a set of connection parameters. The adapter chooses the proper driver to instantiate (for example, Laminas\\Db\\Adapter\\Driver\\Mysqli ) That driver class is instantiated. If no connection, statement, or result objects are injected, defaults are instantiated. This driver is now ready to be called on when particular workflows are requested. Here is what the Driver API looks like: namespace Laminas\\Db\\Adapter\\Driver; interface DriverInterface { const PARAMETERIZATION_POSITIONAL = 'positional'; const PARAMETERIZATION_NAMED = 'named'; const NAME_FORMAT_CAMELCASE = 'camelCase'; const NAME_FORMAT_NATURAL = 'natural'; public function getDatabasePlatformName(string $nameFormat = self::NAME_FORMAT_CAMELCASE) : string; public function checkEnvironment() : bool; public function getConnection() : ConnectionInterface; public function createStatement(string|resource $sqlOrResource = null) : StatementInterface; public function createResult(resource $resource) : ResultInterface; public function getPrepareType() :string; public function formatParameterName(string $name, $type = null) : string; public function getLastGeneratedValue() : mixed; } From this DriverInterface , you can Determine the name of the platform this driver supports (useful for choosing the proper platform object). Check that the environment can support this driver. Return the Connection instance. Create a Statement instance which is optionally seeded by an SQL statement (this will generally be a clone of a prototypical statement object). Create a Result object which is optionally seeded by a statement resource (this will generally be a clone of a prototypical result object) Format parameter names; this is important to distinguish the difference between the various ways parameters are named between extensions Retrieve the overall last generated value (such as an auto-increment value). Now let's turn to the Statement API: namespace Laminas\\Db\\Adapter\\Driver; interface StatementInterface extends StatementContainerInterface { public function getResource() : resource; public function prepare($sql = null) : void; public function isPrepared() : bool; public function execute(null|array|ParameterContainer $parameters = null) : ResultInterface; /** Inherited from StatementContainerInterface */ public function setSql(string $sql) : void; public function getSql() : string; public function setParameterContainer(ParameterContainer $parameterContainer) : void; public function getParameterContainer() : ParameterContainer; } And finally, the Result API: namespace Laminas\\Db\\Adapter\\Driver; use Countable; use Iterator; interface ResultInterface extends Countable, Iterator { public function buffer() : void; public function isQueryResult() : bool; public function getAffectedRows() : int; public function getGeneratedValue() : mixed; public function getResource() : resource; public function getFieldCount() : int; }","title":"Using the Driver Object"},{"location":"adapter/#using-the-platform-object","text":"The Platform object provides an API to assist in crafting queries in a way that is specific to the SQL implementation of a particular vendor. The object handles nuances such as how identifiers or values are quoted, or what the identifier separator character is. To get an idea of the capabilities, the interface for a platform object looks like this: namespace Laminas\\Db\\Adapter\\Platform; interface PlatformInterface { public function getName() : string; public function getQuoteIdentifierSymbol() : string; public function quoteIdentifier(string $identifier) : string; public function quoteIdentifierChain(string|string[] $identiferChain) : string; public function getQuoteValueSymbol() : string; public function quoteValue(string $value) : string; public function quoteTrustedValue(string $value) : string; public function quoteValueList(string|string[] $valueList) : string; public function getIdentifierSeparator() : string; public function quoteIdentifierInFragment(string $identifier, array $additionalSafeWords = []) : string; } While you can directly instantiate a Platform object, generally speaking, it is easier to get the proper Platform instance from the configured adapter (by default the Platform type will match the underlying driver implementation): $platform = $adapter->getPlatform(); // or $platform = $adapter->platform; // magic property access The following are examples of Platform usage: // $adapter is a Laminas\\Db\\Adapter\\Adapter instance; // $platform is a Laminas\\Db\\Adapter\\Platform\\Sql92 instance. $platform = $adapter->getPlatform(); // \"first_name\" echo $platform->quoteIdentifier('first_name'); // \" echo $platform->getQuoteIdentifierSymbol(); // \"schema\".\"mytable\" echo $platform->quoteIdentifierChain(['schema', 'mytable']); // ' echo $platform->getQuoteValueSymbol(); // 'myvalue' echo $platform->quoteValue('myvalue'); // 'value', 'Foo O\\\\'Bar' echo $platform->quoteValueList(['value', \"Foo O'Bar\"]); // . echo $platform->getIdentifierSeparator(); // \"foo\" as \"bar\" echo $platform->quoteIdentifierInFragment('foo as bar'); // additionally, with some safe words: // (\"foo\".\"bar\" = \"boo\".\"baz\") echo $platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', ['(', ')', '=']);","title":"Using The Platform Object"},{"location":"adapter/#using-the-parameter-container","text":"The ParameterContainer object is a container for the various parameters that need to be passed into a Statement object to fulfill all the various parameterized parts of the SQL statement. This object implements the ArrayAccess interface. Below is the ParameterContainer API: namespace Laminas\\Db\\Adapter; use ArrayAccess; use ArrayIterator; use Countable; use Iterator; class ParameterContainer implements Iterator, ArrayAccess, Countable { public function __construct(array $data = []) /** methods to interact with values */ public function offsetExists(string|int $name) : bool; public function offsetGet(string|int $name) : mixed; public function offsetSetReference(string|int $name, string|int $from) : void; public function offsetSet(string|int $name, mixed $value, mixed $errata = null, int $maxLength = null) : void; public function offsetUnset(string|int $name) : void; /** set values from array (will reset first) */ public function setFromArray(array $data) : ParameterContainer; /** methods to interact with value errata */ public function offsetSetErrata(string|int $name, mixed $errata) : void; public function offsetGetErrata(string|int $name) : mixed; public function offsetHasErrata(string|int $name) : bool; public function offsetUnsetErrata(string|int $name) : void; /** errata only iterator */ public function getErrataIterator() : ArrayIterator; /** get array with named keys */ public function getNamedArray() : array; /** get array with int keys, ordered by position */ public function getPositionalArray() : array; /** iterator: */ public function count() : int; public function current() : mixed; public function next() : mixed; public function key() : string|int; public function valid() : bool; public function rewind() : void; /** merge existing array of parameters with existing parameters */ public function merge(array $parameters) : ParameterContainer; } In addition to handling parameter names and values, the container will assist in tracking parameter types for PHP type to SQL type handling. For example, it might be important that: $container->offsetSet('limit', 5); be bound as an integer. To achieve this, pass in the ParameterContainer::TYPE_INTEGER constant as the 3rd parameter: $container->offsetSet('limit', 5, $container::TYPE_INTEGER); This will ensure that if the underlying driver supports typing of bound parameters, that this translated information will also be passed along to the actual php database driver.","title":"Using The Parameter Container"},{"location":"adapter/#examples","text":"Creating a Driver , a vendor-portable query, and preparing and iterating the result: $adapter = new Laminas\\Db\\Adapter\\Adapter($driverConfig); $qi = function ($name) use ($adapter) { return $adapter->platform->quoteIdentifier($name); }; $fp = function ($name) use ($adapter) { return $adapter->driver->formatParameterName($name); }; $sql = 'UPDATE ' . $qi('artist') . ' SET ' . $qi('name') . ' = ' . $fp('name') . ' WHERE ' . $qi('id') . ' = ' . $fp('id'); $statement = $adapter->query($sql); $parameters = [ 'name' => 'Updated Artist', 'id' => 1, ]; $statement->execute($parameters); // DATA INSERTED, NOW CHECK $statement = $adapter->query( 'SELECT * FROM ' . $qi('artist') . ' WHERE id = ' . $fp('id') ); $results = $statement->execute(['id' => 1]); $row = $results->current(); $name = $row['name'];","title":"Examples"},{"location":"metadata/","text":"RDBMS Metadata Laminas\\Db\\Metadata is as sub-component of laminas-db that makes it possible to get metadata information about tables, columns, constraints, triggers, and other information from a database in a standardized way. The primary interface for Metadata is: namespace Laminas\\Db\\Metadata; interface MetadataInterface { public function getSchemas(); public function getTableNames(string $schema = null, bool $includeViews = false) : string[]; public function getTables(string $schema = null, bool $includeViews = false) : Object\\TableObject[]; public function getTable(string $tableName, string $schema = null) : Object\\TableObject; public function getViewNames(string $schema = null) : string[]; public function getViews(string $schema = null) : Object\\ViewObject[]; public function getView(string $viewName, string $schema = null) : Object\\ViewObject; public function getColumnNames(string string $table, $schema = null) : string[]; public function getColumns(string $table, string $schema = null) : Object\\ColumnObject[]; public function getColumn(string $columnName, string $table, string $schema = null) Object\\ColumnObject; public function getConstraints(string $table, $string schema = null) : Object\\ConstraintObject[]; public function getConstraint(string $constraintName, string $table, string $schema = null) : Object\\ConstraintObject; public function getConstraintKeys(string $constraint, string $table, string $schema = null) : Object\\ConstraintKeyObject[]; public function getTriggerNames(string $schema = null) : string[]; public function getTriggers(string $schema = null) : Object\\TriggerObject[]; public function getTrigger(string $triggerName, string $schema = null) : Object\\TriggerObject; } Basic Usage Usage of Laminas\\Db\\Metadata involves: Constructing a Laminas\\Db\\Metadata\\Metadata instance with an Adapter . Choosing a strategy for retrieving metadata, based on the database platform used. In most cases, information will come from querying the INFORMATION_SCHEMA tables for the currently accessible schema. The Metadata::get*Names() methods will return arrays of strings, while the other methods will return value objects specific to the type queried. $metadata = new Laminas\\Db\\Metadata\\Metadata($adapter); // get the table names $tableNames = $metadata->getTableNames(); foreach ($tableNames as $tableName) { echo 'In Table ' . $tableName . PHP_EOL; $table = $metadata->getTable($tableName); echo ' With columns: ' . PHP_EOL; foreach ($table->getColumns() as $column) { echo ' ' . $column->getName() . ' -> ' . $column->getDataType() . PHP_EOL; } echo PHP_EOL; echo ' With constraints: ' . PHP_EOL; foreach ($metadata->getConstraints($tableName) as $constraint) { echo ' ' . $constraint->getName() . ' -> ' . $constraint->getType() . PHP_EOL; if (! $constraint->hasColumns()) { continue; } echo ' column: ' . implode(', ', $constraint->getColumns()); if ($constraint->isForeignKey()) { $fkCols = []; foreach ($constraint->getReferencedColumns() as $refColumn) { $fkCols[] = $constraint->getReferencedTableName() . '.' . $refColumn; } echo ' => ' . implode(', ', $fkCols); } echo PHP_EOL; } echo '----' . PHP_EOL; } Metadata value objects Metadata returns value objects that provide an interface to help developers better explore the metadata. Below is the API for the various value objects: TableObject class Laminas\\Db\\Metadata\\Object\\TableObject { public function __construct($name); public function setColumns(array $columns); public function getColumns(); public function setConstraints($constraints); public function getConstraints(); public function setName($name); public function getName(); } ColumnObject class Laminas\\Db\\Metadata\\Object\\ColumnObject { public function __construct($name, $tableName, $schemaName = null); public function setName($name); public function getName(); public function getTableName(); public function setTableName($tableName); public function setSchemaName($schemaName); public function getSchemaName(); public function getOrdinalPosition(); public function setOrdinalPosition($ordinalPosition); public function getColumnDefault(); public function setColumnDefault($columnDefault); public function getIsNullable(); public function setIsNullable($isNullable); public function isNullable(); public function getDataType(); public function setDataType($dataType); public function getCharacterMaximumLength(); public function setCharacterMaximumLength($characterMaximumLength); public function getCharacterOctetLength(); public function setCharacterOctetLength($characterOctetLength); public function getNumericPrecision(); public function setNumericPrecision($numericPrecision); public function getNumericScale(); public function setNumericScale($numericScale); public function getNumericUnsigned(); public function setNumericUnsigned($numericUnsigned); public function isNumericUnsigned(); public function getErratas(); public function setErratas(array $erratas); public function getErrata($errataName); public function setErrata($errataName, $errataValue); } ConstraintObject class Laminas\\Db\\Metadata\\Object\\ConstraintObject { public function __construct($name, $tableName, $schemaName = null); public function setName($name); public function getName(); public function setSchemaName($schemaName); public function getSchemaName(); public function getTableName(); public function setTableName($tableName); public function setType($type); public function getType(); public function hasColumns(); public function getColumns(); public function setColumns(array $columns); public function getReferencedTableSchema(); public function setReferencedTableSchema($referencedTableSchema); public function getReferencedTableName(); public function setReferencedTableName($referencedTableName); public function getReferencedColumns(); public function setReferencedColumns(array $referencedColumns); public function getMatchOption(); public function setMatchOption($matchOption); public function getUpdateRule(); public function setUpdateRule($updateRule); public function getDeleteRule(); public function setDeleteRule($deleteRule); public function getCheckClause(); public function setCheckClause($checkClause); public function isPrimaryKey(); public function isUnique(); public function isForeignKey(); public function isCheck(); } TriggerObject class Laminas\\Db\\Metadata\\Object\\TriggerObject { public function getName(); public function setName($name); public function getEventManipulation(); public function setEventManipulation($eventManipulation); public function getEventObjectCatalog(); public function setEventObjectCatalog($eventObjectCatalog); public function getEventObjectSchema(); public function setEventObjectSchema($eventObjectSchema); public function getEventObjectTable(); public function setEventObjectTable($eventObjectTable); public function getActionOrder(); public function setActionOrder($actionOrder); public function getActionCondition(); public function setActionCondition($actionCondition); public function getActionStatement(); public function setActionStatement($actionStatement); public function getActionOrientation(); public function setActionOrientation($actionOrientation); public function getActionTiming(); public function setActionTiming($actionTiming); public function getActionReferenceOldTable(); public function setActionReferenceOldTable($actionReferenceOldTable); public function getActionReferenceNewTable(); public function setActionReferenceNewTable($actionReferenceNewTable); public function getActionReferenceOldRow(); public function setActionReferenceOldRow($actionReferenceOldRow); public function getActionReferenceNewRow(); public function setActionReferenceNewRow($actionReferenceNewRow); public function getCreated(); public function setCreated($created); }","title":"RDBMS Metadata"},{"location":"metadata/#rdbms-metadata","text":"Laminas\\Db\\Metadata is as sub-component of laminas-db that makes it possible to get metadata information about tables, columns, constraints, triggers, and other information from a database in a standardized way. The primary interface for Metadata is: namespace Laminas\\Db\\Metadata; interface MetadataInterface { public function getSchemas(); public function getTableNames(string $schema = null, bool $includeViews = false) : string[]; public function getTables(string $schema = null, bool $includeViews = false) : Object\\TableObject[]; public function getTable(string $tableName, string $schema = null) : Object\\TableObject; public function getViewNames(string $schema = null) : string[]; public function getViews(string $schema = null) : Object\\ViewObject[]; public function getView(string $viewName, string $schema = null) : Object\\ViewObject; public function getColumnNames(string string $table, $schema = null) : string[]; public function getColumns(string $table, string $schema = null) : Object\\ColumnObject[]; public function getColumn(string $columnName, string $table, string $schema = null) Object\\ColumnObject; public function getConstraints(string $table, $string schema = null) : Object\\ConstraintObject[]; public function getConstraint(string $constraintName, string $table, string $schema = null) : Object\\ConstraintObject; public function getConstraintKeys(string $constraint, string $table, string $schema = null) : Object\\ConstraintKeyObject[]; public function getTriggerNames(string $schema = null) : string[]; public function getTriggers(string $schema = null) : Object\\TriggerObject[]; public function getTrigger(string $triggerName, string $schema = null) : Object\\TriggerObject; }","title":"RDBMS Metadata"},{"location":"metadata/#basic-usage","text":"Usage of Laminas\\Db\\Metadata involves: Constructing a Laminas\\Db\\Metadata\\Metadata instance with an Adapter . Choosing a strategy for retrieving metadata, based on the database platform used. In most cases, information will come from querying the INFORMATION_SCHEMA tables for the currently accessible schema. The Metadata::get*Names() methods will return arrays of strings, while the other methods will return value objects specific to the type queried. $metadata = new Laminas\\Db\\Metadata\\Metadata($adapter); // get the table names $tableNames = $metadata->getTableNames(); foreach ($tableNames as $tableName) { echo 'In Table ' . $tableName . PHP_EOL; $table = $metadata->getTable($tableName); echo ' With columns: ' . PHP_EOL; foreach ($table->getColumns() as $column) { echo ' ' . $column->getName() . ' -> ' . $column->getDataType() . PHP_EOL; } echo PHP_EOL; echo ' With constraints: ' . PHP_EOL; foreach ($metadata->getConstraints($tableName) as $constraint) { echo ' ' . $constraint->getName() . ' -> ' . $constraint->getType() . PHP_EOL; if (! $constraint->hasColumns()) { continue; } echo ' column: ' . implode(', ', $constraint->getColumns()); if ($constraint->isForeignKey()) { $fkCols = []; foreach ($constraint->getReferencedColumns() as $refColumn) { $fkCols[] = $constraint->getReferencedTableName() . '.' . $refColumn; } echo ' => ' . implode(', ', $fkCols); } echo PHP_EOL; } echo '----' . PHP_EOL; }","title":"Basic Usage"},{"location":"metadata/#metadata-value-objects","text":"Metadata returns value objects that provide an interface to help developers better explore the metadata. Below is the API for the various value objects:","title":"Metadata value objects"},{"location":"result-set/","text":"Result Sets Laminas\\Db\\ResultSet is a sub-component of laminas-db for abstracting the iteration of results returned from queries producing rowsets. While data sources for this can be anything that is iterable, generally these will be populated from Laminas\\Db\\Adapter\\Driver\\ResultInterface instances. Result sets must implement the Laminas\\Db\\ResultSet\\ResultSetInterface , and all sub-components of laminas-db that return a result set as part of their API will assume an instance of a ResultSetInterface should be returned. In most cases, the prototype pattern will be used by consuming object to clone a prototype of a ResultSet and return a specialized ResultSet with a specific data source injected. ResultSetInterface is defined as follows: use Countable; use Traversable; interface ResultSetInterface extends Traversable, Countable { public function initialize(mixed $dataSource) : void; public function getFieldCount() : int; } Quick start Laminas\\Db\\ResultSet\\ResultSet is the most basic form of a ResultSet object that will expose each row as either an ArrayObject -like object or an array of row data. By default, Laminas\\Db\\Adapter\\Adapter will use a prototypical Laminas\\Db\\ResultSet\\ResultSet object for iterating when using the Laminas\\Db\\Adapter\\Adapter::query() method. The following is an example workflow similar to what one might find inside Laminas\\Db\\Adapter\\Adapter::query() : use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\ResultSet\\ResultSet; $statement = $driver->createStatement('SELECT * FROM users'); $statement->prepare(); $result = $statement->execute($parameters); if ($result instanceof ResultInterface && $result->isQueryResult()) { $resultSet = new ResultSet; $resultSet->initialize($result); foreach ($resultSet as $row) { echo $row->my_column . PHP_EOL; } } Laminas\\Db\\ResultSet\\ResultSet and Laminas\\Db\\ResultSet\\AbstractResultSet For most purposes, either an instance of Laminas\\Db\\ResultSet\\ResultSet or a derivative of Laminas\\Db\\ResultSet\\AbstractResultSet will be used. The implementation of the AbstractResultSet offers the following core functionality: namespace Laminas\\Db\\ResultSet; use Iterator; abstract class AbstractResultSet implements Iterator, ResultSetInterface { public function initialize(array|Iterator|IteratorAggregate|ResultInterface $dataSource) : self; public function getDataSource() : Iterator|IteratorAggregate|ResultInterface; public function getFieldCount() : int; /** Iterator */ public function next() : mixed; public function key() : string|int; public function current() : mixed; public function valid() : bool; public function rewind() : void; /** countable */ public function count() : int; /** get rows as array */ public function toArray() : array; } Laminas\\Db\\ResultSet\\HydratingResultSet Laminas\\Db\\ResultSet\\HydratingResultSet is a more flexible ResultSet object that allows the developer to choose an appropriate \"hydration strategy\" for getting row data into a target object. While iterating over results, HydratingResultSet will take a prototype of a target object and clone it once for each row. The HydratingResultSet will then hydrate that clone with the row data. The HydratingResultSet depends on laminas-hydrator , which you will need to install: $ composer require laminas/laminas-hydrator In the example below, rows from the database will be iterated, and during iteration, HydratingResultSet will use the Reflection based hydrator to inject the row data directly into the protected members of the cloned UserEntity object: use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\ResultSet\\HydratingResultSet; use Laminas\\Hydrator\\Reflection as ReflectionHydrator; class UserEntity { protected $first_name; protected $last_name; public function getFirstName() { return $this->first_name; } public function getLastName() { return $this->last_name; } public function setFirstName($firstName) { $this->first_name = $firstName; } public function setLastName($lastName) { $this->last_name = $lastName; } } $statement = $driver->createStatement($sql); $statement->prepare($parameters); $result = $statement->execute(); if ($result instanceof ResultInterface && $result->isQueryResult()) { $resultSet = new HydratingResultSet(new ReflectionHydrator, new UserEntity); $resultSet->initialize($result); foreach ($resultSet as $user) { echo $user->getFirstName() . ' ' . $user->getLastName() . PHP_EOL; } } For more information, see the laminas-hydrator documentation to get a better sense of the different strategies that can be employed in order to populate a target object.","title":"Result Sets"},{"location":"result-set/#result-sets","text":"Laminas\\Db\\ResultSet is a sub-component of laminas-db for abstracting the iteration of results returned from queries producing rowsets. While data sources for this can be anything that is iterable, generally these will be populated from Laminas\\Db\\Adapter\\Driver\\ResultInterface instances. Result sets must implement the Laminas\\Db\\ResultSet\\ResultSetInterface , and all sub-components of laminas-db that return a result set as part of their API will assume an instance of a ResultSetInterface should be returned. In most cases, the prototype pattern will be used by consuming object to clone a prototype of a ResultSet and return a specialized ResultSet with a specific data source injected. ResultSetInterface is defined as follows: use Countable; use Traversable; interface ResultSetInterface extends Traversable, Countable { public function initialize(mixed $dataSource) : void; public function getFieldCount() : int; }","title":"Result Sets"},{"location":"result-set/#quick-start","text":"Laminas\\Db\\ResultSet\\ResultSet is the most basic form of a ResultSet object that will expose each row as either an ArrayObject -like object or an array of row data. By default, Laminas\\Db\\Adapter\\Adapter will use a prototypical Laminas\\Db\\ResultSet\\ResultSet object for iterating when using the Laminas\\Db\\Adapter\\Adapter::query() method. The following is an example workflow similar to what one might find inside Laminas\\Db\\Adapter\\Adapter::query() : use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\ResultSet\\ResultSet; $statement = $driver->createStatement('SELECT * FROM users'); $statement->prepare(); $result = $statement->execute($parameters); if ($result instanceof ResultInterface && $result->isQueryResult()) { $resultSet = new ResultSet; $resultSet->initialize($result); foreach ($resultSet as $row) { echo $row->my_column . PHP_EOL; } }","title":"Quick start"},{"location":"result-set/#laminasdbresultsetresultset-and-laminasdbresultsetabstractresultset","text":"For most purposes, either an instance of Laminas\\Db\\ResultSet\\ResultSet or a derivative of Laminas\\Db\\ResultSet\\AbstractResultSet will be used. The implementation of the AbstractResultSet offers the following core functionality: namespace Laminas\\Db\\ResultSet; use Iterator; abstract class AbstractResultSet implements Iterator, ResultSetInterface { public function initialize(array|Iterator|IteratorAggregate|ResultInterface $dataSource) : self; public function getDataSource() : Iterator|IteratorAggregate|ResultInterface; public function getFieldCount() : int; /** Iterator */ public function next() : mixed; public function key() : string|int; public function current() : mixed; public function valid() : bool; public function rewind() : void; /** countable */ public function count() : int; /** get rows as array */ public function toArray() : array; }","title":"Laminas\\Db\\ResultSet\\ResultSet and Laminas\\Db\\ResultSet\\AbstractResultSet"},{"location":"result-set/#laminasdbresultsethydratingresultset","text":"Laminas\\Db\\ResultSet\\HydratingResultSet is a more flexible ResultSet object that allows the developer to choose an appropriate \"hydration strategy\" for getting row data into a target object. While iterating over results, HydratingResultSet will take a prototype of a target object and clone it once for each row. The HydratingResultSet will then hydrate that clone with the row data. The HydratingResultSet depends on laminas-hydrator , which you will need to install: $ composer require laminas/laminas-hydrator In the example below, rows from the database will be iterated, and during iteration, HydratingResultSet will use the Reflection based hydrator to inject the row data directly into the protected members of the cloned UserEntity object: use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\ResultSet\\HydratingResultSet; use Laminas\\Hydrator\\Reflection as ReflectionHydrator; class UserEntity { protected $first_name; protected $last_name; public function getFirstName() { return $this->first_name; } public function getLastName() { return $this->last_name; } public function setFirstName($firstName) { $this->first_name = $firstName; } public function setLastName($lastName) { $this->last_name = $lastName; } } $statement = $driver->createStatement($sql); $statement->prepare($parameters); $result = $statement->execute(); if ($result instanceof ResultInterface && $result->isQueryResult()) { $resultSet = new HydratingResultSet(new ReflectionHydrator, new UserEntity); $resultSet->initialize($result); foreach ($resultSet as $user) { echo $user->getFirstName() . ' ' . $user->getLastName() . PHP_EOL; } } For more information, see the laminas-hydrator documentation to get a better sense of the different strategies that can be employed in order to populate a target object.","title":"Laminas\\Db\\ResultSet\\HydratingResultSet"},{"location":"row-gateway/","text":"Row Gateways Laminas\\Db\\RowGateway is a sub-component of laminas-db that implements the Row Data Gateway pattern described in the book Patterns of Enterprise Application Architecture . Row Data Gateways model individual rows of a database table, and provide methods such as save() and delete() that persist the row to the database. Likewise, after a row from the database is retrieved, it can then be manipulated and save() 'd back to the database in the same position (row), or it can be delete() 'd from the table. RowGatewayInterface defines the methods save() and delete() : namespace Laminas\\Db\\RowGateway; interface RowGatewayInterface { public function save(); public function delete(); } Quick start RowGateway is generally used in conjunction with objects that produce Laminas\\Db\\ResultSet s, though it may also be used standalone. To use it standalone, you need an Adapter instance and a set of data to work with. The following demonstrates a basic use case. use Laminas\\Db\\RowGateway\\RowGateway; // Query the database: $resultSet = $adapter->query('SELECT * FROM `user` WHERE `id` = ?', [2]); // Get array of data: $rowData = $resultSet->current()->getArrayCopy(); // Create a row gateway: $rowGateway = new RowGateway('id', 'my_table', $adapter); $rowGateway->populate($rowData, true); // Manipulate the row and persist it: $rowGateway->first_name = 'New Name'; $rowGateway->save(); // Or delete this row: $rowGateway->delete(); The workflow described above is greatly simplified when RowGateway is used in conjunction with the TableGateway RowGatewayFeature . In that paradigm, select() operations will produce a ResultSet that iterates RowGateway instances. As an example: use Laminas\\Db\\TableGateway\\Feature\\RowGatewayFeature; use Laminas\\Db\\TableGateway\\TableGateway; $table = new TableGateway('artist', $adapter, new RowGatewayFeature('id')); $results = $table->select(['id' => 2]); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save(); ActiveRecord Style Objects If you wish to have custom behaviour in your RowGateway objects — essentially making them behave similarly to the ActiveRecord pattern), pass a prototype object implementing the RowGatewayInterface to the RowGatewayFeature constructor instead of a primary key: use Laminas\\Db\\TableGateway\\Feature\\RowGatewayFeature; use Laminas\\Db\\TableGateway\\TableGateway; use Laminas\\Db\\RowGateway\\RowGatewayInterface; class Artist implements RowGatewayInterface { protected $adapter; public function __construct($adapter) { $this->adapter = $adapter; } // ... save() and delete() implementations } $table = new TableGateway('artist', $adapter, new RowGatewayFeature(new Artist($adapter)));","title":"Row Gateways"},{"location":"row-gateway/#row-gateways","text":"Laminas\\Db\\RowGateway is a sub-component of laminas-db that implements the Row Data Gateway pattern described in the book Patterns of Enterprise Application Architecture . Row Data Gateways model individual rows of a database table, and provide methods such as save() and delete() that persist the row to the database. Likewise, after a row from the database is retrieved, it can then be manipulated and save() 'd back to the database in the same position (row), or it can be delete() 'd from the table. RowGatewayInterface defines the methods save() and delete() : namespace Laminas\\Db\\RowGateway; interface RowGatewayInterface { public function save(); public function delete(); }","title":"Row Gateways"},{"location":"row-gateway/#quick-start","text":"RowGateway is generally used in conjunction with objects that produce Laminas\\Db\\ResultSet s, though it may also be used standalone. To use it standalone, you need an Adapter instance and a set of data to work with. The following demonstrates a basic use case. use Laminas\\Db\\RowGateway\\RowGateway; // Query the database: $resultSet = $adapter->query('SELECT * FROM `user` WHERE `id` = ?', [2]); // Get array of data: $rowData = $resultSet->current()->getArrayCopy(); // Create a row gateway: $rowGateway = new RowGateway('id', 'my_table', $adapter); $rowGateway->populate($rowData, true); // Manipulate the row and persist it: $rowGateway->first_name = 'New Name'; $rowGateway->save(); // Or delete this row: $rowGateway->delete(); The workflow described above is greatly simplified when RowGateway is used in conjunction with the TableGateway RowGatewayFeature . In that paradigm, select() operations will produce a ResultSet that iterates RowGateway instances. As an example: use Laminas\\Db\\TableGateway\\Feature\\RowGatewayFeature; use Laminas\\Db\\TableGateway\\TableGateway; $table = new TableGateway('artist', $adapter, new RowGatewayFeature('id')); $results = $table->select(['id' => 2]); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save();","title":"Quick start"},{"location":"row-gateway/#activerecord-style-objects","text":"If you wish to have custom behaviour in your RowGateway objects — essentially making them behave similarly to the ActiveRecord pattern), pass a prototype object implementing the RowGatewayInterface to the RowGatewayFeature constructor instead of a primary key: use Laminas\\Db\\TableGateway\\Feature\\RowGatewayFeature; use Laminas\\Db\\TableGateway\\TableGateway; use Laminas\\Db\\RowGateway\\RowGatewayInterface; class Artist implements RowGatewayInterface { protected $adapter; public function __construct($adapter) { $this->adapter = $adapter; } // ... save() and delete() implementations } $table = new TableGateway('artist', $adapter, new RowGatewayFeature(new Artist($adapter)));","title":"ActiveRecord Style Objects"},{"location":"sql-ddl/","text":"DDL Abstraction Laminas\\Db\\Sql\\Ddl is a sub-component of Laminas\\Db\\Sql allowing creation of DDL (Data Definition Language) SQL statements. When combined with a platform specific Laminas\\Db\\Sql\\Sql object, DDL objects are capable of producing platform-specific CREATE TABLE statements, with specialized data types, constraints, and indexes for a database/schema. The following platforms have platform specializations for DDL: MySQL All databases compatible with ANSI SQL92 Creating Tables Like Laminas\\Db\\Sql objects, each statement type is represented by a class. For example, CREATE TABLE is modeled by the CreateTable class; this is likewise the same for ALTER TABLE (as AlterTable ), and DROP TABLE (as DropTable ). You can create instances using a number of approaches: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; $table = new Ddl\\CreateTable(); // With a table name: $table = new Ddl\\CreateTable('bar'); // With a schema name \"foo\": $table = new Ddl\\CreateTable(new TableIdentifier('bar', 'foo')); // Optionally, as a temporary table: $table = new Ddl\\CreateTable('bar', true); You can also set the table after instantiation: $table->setTable('bar'); Currently, columns are added by creating a column object (described in the data type table below ): use Laminas\\Db\\Sql\\Ddl\\Column; $table->addColumn(new Column\\Integer('id')); $table->addColumn(new Column\\Varchar('name', 255)); Beyond adding columns to a table, you may also add constraints: use Laminas\\Db\\Sql\\Ddl\\Constraint; $table->addConstraint(new Constraint\\PrimaryKey('id')); $table->addConstraint( new Constraint\\UniqueKey(['name', 'foo'], 'my_unique_key') ); You can also use the AUTO_INCREMENT attribute for MySQL: use Laminas\\Db\\Sql\\Ddl\\Column; $column = new Column\\Integer('id'); $column->setOption('AUTO_INCREMENT', true); Altering Tables Similar to CreateTable , you may also use AlterTable instances: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; $table = new Ddl\\AlterTable(); // With a table name: $table = new Ddl\\AlterTable('bar'); // With a schema name \"foo\": $table = new Ddl\\AlterTable(new TableIdentifier('bar', 'foo')); // Optionally, as a temporary table: $table = new Ddl\\AlterTable('bar', true); The primary difference between a CreateTable and AlterTable is that the AlterTable takes into account that the table and its assets already exist. Therefore, while you still have addColumn() and addConstraint() , you will also have the ability to alter existing columns: use Laminas\\Db\\Sql\\Ddl\\Column; $table->changeColumn('name', Column\\Varchar('new_name', 50)); You may also drop existing columns or constraints: $table->dropColumn('foo'); $table->dropConstraint('my_index'); Dropping Tables To drop a table, create a DropTable instance: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; // With a table name: $drop = new Ddl\\DropTable('bar'); // With a schema name \"foo\": $drop = new Ddl\\DropTable(new TableIdentifier('bar', 'foo')); Executing DDL Statements After a DDL statement object has been created and configured, at some point you will need to execute the statement. This requires an Adapter instance and a properly seeded Sql instance. The workflow looks something like this, with $ddl being a CreateTable , AlterTable , or DropTable instance: use Laminas\\Db\\Sql\\Sql; // Existence of $adapter is assumed. $sql = new Sql($adapter); $adapter->query( $sql->buildSqlString($ddl), $adapter::QUERY_MODE_EXECUTE ); By passing the $ddl object through the $sql instance's getSqlStringForSqlObject() method, we ensure that any platform specific specializations/modifications are utilized to create a platform specific SQL statement. Next, using the constant Laminas\\Db\\Adapter\\Adapter::QUERY_MODE_EXECUTE ensures that the SQL statement is not prepared, as most DDL statements on most platforms cannot be prepared, only executed. Currently Supported Data Types These types exist in the Laminas\\Db\\Sql\\Ddl\\Column namespace. Data types must implement Laminas\\Db\\Sql\\Ddl\\Column\\ColumnInterface . In alphabetical order: Type Arguments For Construction BigInteger $name , $nullable = false , $default = null , array $options = array() Binary $name , $length , nullable = false , $default = null , array $options = array() Blob $name , $length , nullable = false , $default = null , array $options = array() Boolean $name Char $name , length Column (generic) $name = null Date $name DateTime $name Decimal $name , $precision , $scale = null Float $name , $digits , $decimal (Note: this class is deprecated as of 2.4.0; use Floating instead) Floating $name , $digits , $decimal Integer $name , $nullable = false , default = null , array $options = array() Text $name , $length , nullable = false , $default = null , array $options = array() Time $name Timestamp $name Varbinary $name , $length Varchar $name , $length Each of the above types can be utilized in any place that accepts a Column\\ColumnInterface instance. Currently, this is primarily in CreateTable::addColumn() and AlterTable 's addColumn() and changeColumn() methods. Currently Supported Constraint Types These types exist in the Laminas\\Db\\Sql\\Ddl\\Constraint namespace. Data types must implement Laminas\\Db\\Sql\\Ddl\\Constraint\\ConstraintInterface . In alphabetical order: Type Arguments For Construction Check $expression , $name ForeignKey $name , $column , $referenceTable , $referenceColumn , $onDeleteRule = null , $onUpdateRule = null PrimaryKey $columns UniqueKey $column , $name = null Each of the above types can be utilized in any place that accepts a Column\\ConstraintInterface instance. Currently, this is primarily in CreateTable::addConstraint() and AlterTable::addConstraint() .","title":"DDL Abstraction"},{"location":"sql-ddl/#ddl-abstraction","text":"Laminas\\Db\\Sql\\Ddl is a sub-component of Laminas\\Db\\Sql allowing creation of DDL (Data Definition Language) SQL statements. When combined with a platform specific Laminas\\Db\\Sql\\Sql object, DDL objects are capable of producing platform-specific CREATE TABLE statements, with specialized data types, constraints, and indexes for a database/schema. The following platforms have platform specializations for DDL: MySQL All databases compatible with ANSI SQL92","title":"DDL Abstraction"},{"location":"sql-ddl/#creating-tables","text":"Like Laminas\\Db\\Sql objects, each statement type is represented by a class. For example, CREATE TABLE is modeled by the CreateTable class; this is likewise the same for ALTER TABLE (as AlterTable ), and DROP TABLE (as DropTable ). You can create instances using a number of approaches: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; $table = new Ddl\\CreateTable(); // With a table name: $table = new Ddl\\CreateTable('bar'); // With a schema name \"foo\": $table = new Ddl\\CreateTable(new TableIdentifier('bar', 'foo')); // Optionally, as a temporary table: $table = new Ddl\\CreateTable('bar', true); You can also set the table after instantiation: $table->setTable('bar'); Currently, columns are added by creating a column object (described in the data type table below ): use Laminas\\Db\\Sql\\Ddl\\Column; $table->addColumn(new Column\\Integer('id')); $table->addColumn(new Column\\Varchar('name', 255)); Beyond adding columns to a table, you may also add constraints: use Laminas\\Db\\Sql\\Ddl\\Constraint; $table->addConstraint(new Constraint\\PrimaryKey('id')); $table->addConstraint( new Constraint\\UniqueKey(['name', 'foo'], 'my_unique_key') ); You can also use the AUTO_INCREMENT attribute for MySQL: use Laminas\\Db\\Sql\\Ddl\\Column; $column = new Column\\Integer('id'); $column->setOption('AUTO_INCREMENT', true);","title":"Creating Tables"},{"location":"sql-ddl/#altering-tables","text":"Similar to CreateTable , you may also use AlterTable instances: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; $table = new Ddl\\AlterTable(); // With a table name: $table = new Ddl\\AlterTable('bar'); // With a schema name \"foo\": $table = new Ddl\\AlterTable(new TableIdentifier('bar', 'foo')); // Optionally, as a temporary table: $table = new Ddl\\AlterTable('bar', true); The primary difference between a CreateTable and AlterTable is that the AlterTable takes into account that the table and its assets already exist. Therefore, while you still have addColumn() and addConstraint() , you will also have the ability to alter existing columns: use Laminas\\Db\\Sql\\Ddl\\Column; $table->changeColumn('name', Column\\Varchar('new_name', 50)); You may also drop existing columns or constraints: $table->dropColumn('foo'); $table->dropConstraint('my_index');","title":"Altering Tables"},{"location":"sql-ddl/#dropping-tables","text":"To drop a table, create a DropTable instance: use Laminas\\Db\\Sql\\Ddl; use Laminas\\Db\\Sql\\TableIdentifier; // With a table name: $drop = new Ddl\\DropTable('bar'); // With a schema name \"foo\": $drop = new Ddl\\DropTable(new TableIdentifier('bar', 'foo'));","title":"Dropping Tables"},{"location":"sql-ddl/#executing-ddl-statements","text":"After a DDL statement object has been created and configured, at some point you will need to execute the statement. This requires an Adapter instance and a properly seeded Sql instance. The workflow looks something like this, with $ddl being a CreateTable , AlterTable , or DropTable instance: use Laminas\\Db\\Sql\\Sql; // Existence of $adapter is assumed. $sql = new Sql($adapter); $adapter->query( $sql->buildSqlString($ddl), $adapter::QUERY_MODE_EXECUTE ); By passing the $ddl object through the $sql instance's getSqlStringForSqlObject() method, we ensure that any platform specific specializations/modifications are utilized to create a platform specific SQL statement. Next, using the constant Laminas\\Db\\Adapter\\Adapter::QUERY_MODE_EXECUTE ensures that the SQL statement is not prepared, as most DDL statements on most platforms cannot be prepared, only executed.","title":"Executing DDL Statements"},{"location":"sql-ddl/#currently-supported-data-types","text":"These types exist in the Laminas\\Db\\Sql\\Ddl\\Column namespace. Data types must implement Laminas\\Db\\Sql\\Ddl\\Column\\ColumnInterface . In alphabetical order: Type Arguments For Construction BigInteger $name , $nullable = false , $default = null , array $options = array() Binary $name , $length , nullable = false , $default = null , array $options = array() Blob $name , $length , nullable = false , $default = null , array $options = array() Boolean $name Char $name , length Column (generic) $name = null Date $name DateTime $name Decimal $name , $precision , $scale = null Float $name , $digits , $decimal (Note: this class is deprecated as of 2.4.0; use Floating instead) Floating $name , $digits , $decimal Integer $name , $nullable = false , default = null , array $options = array() Text $name , $length , nullable = false , $default = null , array $options = array() Time $name Timestamp $name Varbinary $name , $length Varchar $name , $length Each of the above types can be utilized in any place that accepts a Column\\ColumnInterface instance. Currently, this is primarily in CreateTable::addColumn() and AlterTable 's addColumn() and changeColumn() methods.","title":"Currently Supported Data Types"},{"location":"sql-ddl/#currently-supported-constraint-types","text":"These types exist in the Laminas\\Db\\Sql\\Ddl\\Constraint namespace. Data types must implement Laminas\\Db\\Sql\\Ddl\\Constraint\\ConstraintInterface . In alphabetical order: Type Arguments For Construction Check $expression , $name ForeignKey $name , $column , $referenceTable , $referenceColumn , $onDeleteRule = null , $onUpdateRule = null PrimaryKey $columns UniqueKey $column , $name = null Each of the above types can be utilized in any place that accepts a Column\\ConstraintInterface instance. Currently, this is primarily in CreateTable::addConstraint() and AlterTable::addConstraint() .","title":"Currently Supported Constraint Types"},{"location":"sql/","text":"SQL Abstraction Laminas\\Db\\Sql is a SQL abstraction layer for building platform-specific SQL queries via an object-oriented API. The end result of a Laminas\\Db\\Sql object will be to either produce a Statement and ParameterContainer that represents the target query, or a full string that can be directly executed against the database platform. To achieve this, Laminas\\Db\\Sql objects require a Laminas\\Db\\Adapter\\Adapter object in order to produce the desired results. Quick start There are four primary tasks associated with interacting with a database defined by Data Manipulation Language (DML): selecting, inserting, updating, and deleting. As such, there are four primary classes that developers can interact with in order to build queries in the Laminas\\Db\\Sql namespace: Select , Insert , Update , and Delete . Since these four tasks are so closely related and generally used together within the same application, the Laminas\\Db\\Sql\\Sql class helps you create them and produce the result you are attempting to achieve. use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); // returns a Laminas\\Db\\Sql\\Select instance $insert = $sql->insert(); // returns a Laminas\\Db\\Sql\\Insert instance $update = $sql->update(); // returns a Laminas\\Db\\Sql\\Update instance $delete = $sql->delete(); // returns a Laminas\\Db\\Sql\\Delete instance As a developer, you can now interact with these objects, as described in the sections below, to customize each query. Once they have been populated with values, they are ready to either be prepared or executed. To prepare (using a Select object): use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(['id' => 2]); $statement = $sql->prepareStatementForSqlObject($select); $results = $statement->execute(); To execute (using a Select object) use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(['id' => 2]); $selectString = $sql->buildSqlString($select); $results = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE); Laminas\\\\Db\\\\Sql\\\\Sql objects can also be bound to a particular table so that in obtaining a Select , Insert , Update , or Delete instance, the object will be seeded with the table: use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter, 'foo'); $select = $sql->select(); $select->where(['id' => 2]); // $select already has from('foo') applied Common interfaces for SQL implementations Each of these objects implements the following two interfaces: interface PreparableSqlInterface { public function prepareStatement(Adapter $adapter, StatementInterface $statement) : void; } interface SqlInterface { public function getSqlString(PlatformInterface $adapterPlatform = null) : string; } Use these functions to produce either (a) a prepared statement, or (b) a string to execute. Select Laminas\\Db\\Sql\\Select presents a unified API for building platform-specific SQL SELECT queries. Instances may be created and consumed without Laminas\\Db\\Sql\\Sql : use Laminas\\Db\\Sql\\Select; $select = new Select(); // or, to produce a $select bound to a specific table $select = new Select('foo'); If a table is provided to the Select object, then from() cannot be called later to change the name of the table. Once you have a valid Select object, the following API can be used to further specify various select statement parts: class Select extends AbstractSql implements SqlInterface, PreparableSqlInterface { const JOIN_INNER = 'inner'; const JOIN_OUTER = 'outer'; const JOIN_FULL_OUTER = 'full outer'; const JOIN_LEFT = 'left'; const JOIN_RIGHT = 'right'; const SQL_STAR = '*'; const ORDER_ASCENDING = 'ASC'; const ORDER_DESCENDING = 'DESC'; public $where; // @param Where $where public function __construct(string|array|TableIdentifier $table = null); public function from(string|array|TableIdentifier $table) : self; public function columns(array $columns, bool $prefixColumnsWithTable = true) : self; public function join(string|array|TableIdentifier $name, string $on, string|array $columns = self::SQL_STAR, string $type = self::JOIN_INNER) : self; public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; public function group(string|array $group); public function having(Having|callable|string|array $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; public function order(string|array $order) : self; public function limit(int $limit) : self; public function offset(int $offset) : self; } from() // As a string: $select->from('foo'); // As an array to specify an alias // (produces SELECT \"t\".* FROM \"table\" AS \"t\") $select->from(['t' => 'table']); // Using a Sql\\TableIdentifier: // (same output as above) $select->from(['t' => new TableIdentifier('table')]); columns() // As an array of names $select->columns(['foo', 'bar']); // As an associative array with aliases as the keys // (produces 'bar' AS 'foo', 'bax' AS 'baz') $select->columns([ 'foo' => 'bar', 'baz' => 'bax' ]); // Sql function call on the column // (produces CONCAT_WS('/', 'bar', 'bax') AS 'foo') $select->columns([ 'foo' => new \\Laminas\\Db\\Sql\\Expression(\"CONCAT_WS('/', 'bar', 'bax')\") ]); join() $select->join( 'foo', // table name 'id = bar.id', // expression to join on (will be quoted by platform object before insertion), ['bar', 'baz'], // (optional) list of columns, same requirements as columns() above $select::JOIN_OUTER // (optional), one of inner, outer, full outer, left, right also represented by constants in the API ); $select ->from(['f' => 'foo']) // base table ->join( ['b' => 'bar'], // join table with alias 'f.foo_id = b.foo_id' // join expression ); where(), having() Laminas\\Db\\Sql\\Select provides bit of flexibility as it regards to what kind of parameters are acceptable when calling where() or having() . The method signature is listed as: /** * Create where clause * * @param Where|callable|string|array $predicate * @param string $combination One of the OP_* constants from Predicate\\PredicateSet * @return Select */ public function where($predicate, $combination = Predicate\\PredicateSet::OP_AND); If you provide a Laminas\\Db\\Sql\\Where instance to where() or a Laminas\\Db\\Sql\\Having instance to having() , any previous internal instances will be replaced completely. When either instance is processed, this object will be iterated to produce the WHERE or HAVING section of the SELECT statement. If you provide a PHP callable to where() or having() , this function will be called with the Select 's Where / Having instance as the only parameter. This enables code like the following: $select->where(function (Where $where) { $where->like('username', 'ralph%'); }); If you provide a string , this string will be used to create a Laminas\\Db\\Sql\\Predicate\\Expression instance, and its contents will be applied as-is, with no quoting: // SELECT \"foo\".* FROM \"foo\" WHERE x = 5 $select->from('foo')->where('x = 5'); If you provide an array with integer indices, the value can be one of: a string; this will be used to build a Predicate\\Expression . any object implementing Predicate\\PredicateInterface . In either case, the instances are pushed onto the Where stack with the $combination provided (defaulting to AND ). As an example: // SELECT \"foo\".* FROM \"foo\" WHERE x = 5 AND y = z $select->from('foo')->where(['x = 5', 'y = z']); If you provide an associative array with string keys, any value with a string key will be cast as follows: PHP value Predicate type null Predicate\\IsNull array Predicate\\In string Predicate\\Operator , where the key is the identifier. As an example: // SELECT \"foo\".* FROM \"foo\" WHERE \"c1\" IS NULL AND \"c2\" IN (?, ?, ?) AND \"c3\" IS NOT NULL $select->from('foo')->where([ 'c1' => null, 'c2' => [1, 2, 3], new \\Laminas\\Db\\Sql\\Predicate\\IsNotNull('c3'), ]); As another example of complex queries with nested conditions e.g. SELECT * WHERE (column1 is null or column1 = 2) AND (column2 = 3) you need to use the nest() and unnest() methods, as follows: $select->where->nest() // bracket opened ->isNull('column1') ->or ->equalTo('column1', '2') ->unnest(); // bracket closed ->equalTo('column2', '3'); order() $select = new Select; $select->order('id DESC'); // produces 'id' DESC $select = new Select; $select ->order('id DESC') ->order('name ASC, age DESC'); // produces 'id' DESC, 'name' ASC, 'age' DESC $select = new Select; $select->order(['name ASC', 'age DESC']); // produces 'name' ASC, 'age' DESC limit() and offset() $select = new Select; $select->limit(5); // always takes an integer/numeric $select->offset(10); // similarly takes an integer/numeric Insert The Insert API: class Insert implements SqlInterface, PreparableSqlInterface { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public function __construct(string|TableIdentifier $table = null); public function into(string|TableIdentifier $table) : self; public function columns(array $columns) : self; public function values(array $values, string $flag = self::VALUES_SET) : self; } As with Select , the table may be provided during instantiation or via the into() method. columns() $insert->columns(['foo', 'bar']); // set the valid columns values() The default behavior of values is to set the values. Successive calls will not preserve values from previous calls. $insert->values([ 'col_1' => 'value1', 'col_2' => 'value2', ]); To merge values with previous calls, provide the appropriate flag: Laminas\\Db\\Sql\\Insert::VALUES_MERGE $insert->values(['col_2' => 'value2'], $insert::VALUES_MERGE); Update class Update { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public $where; // @param Where $where public function __construct(string|TableIdentifier $table = null); public function table(string|TableIdentifier $table) : self; public function set(array $values, string $flag = self::VALUES_SET) : self; public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; } set() $update->set(['foo' => 'bar', 'baz' => 'bax']); where() See the section on Where and Having . Delete class Delete { public $where; // @param Where $where public function __construct(string|TableIdentifier $table = null); public function from(string|TableIdentifier $table); public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; } where() See the section on Where and Having . Where and Having In the following, we will talk about Where ; note, however, that Having utilizes the same API. Effectively, Where and Having extend from the same base object, a Predicate (and PredicateSet ). All of the parts that make up a WHERE or HAVING clause that are AND'ed or OR'd together are called predicates . The full set of predicates is called a PredicateSet . A Predicate generally contains the values (and identifiers) separate from the fragment they belong to until the last possible moment when the statement is either prepared (parameteritized) or executed. In parameterization, the parameters will be replaced with their proper placeholder (a named or positional parameter), and the values stored inside an Adapter\\ParameterContainer . When executed, the values will be interpolated into the fragments they belong to and properly quoted. In the Where / Having API, a distinction is made between what elements are considered identifiers ( TYPE_IDENTIFIER ) and which are values ( TYPE_VALUE ). There is also a special use case type for literal values ( TYPE_LITERAL ). All element types are expressed via the Laminas\\Db\\Sql\\ExpressionInterface interface. Literals In Laminas 2.1, an actual Literal type was added. Laminas\\Db\\Sql now makes the distinction that literals will not have any parameters that need interpolating, while Expression objects might have parameters that need interpolating. In cases where there are parameters in an Expression , Laminas\\Db\\Sql\\AbstractSql will do its best to identify placeholders when the Expression is processed during statement creation. In short, if you don't have parameters, use Literal objects. The Where and Having API is that of Predicate and PredicateSet : // Where & Having extend Predicate: class Predicate extends PredicateSet { public $and; public $or; public $AND; public $OR; public $NEST; public $UNNEST; public function nest() : Predicate; public function setUnnest(Predicate $predicate) : void; public function unnest() : Predicate; public function equalTo( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function notEqualTo( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function lessThan( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function greaterThan( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function lessThanOrEqualTo( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function greaterThanOrEqualTo( int|float|bool|string $left, int|float|bool|string $right, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ) : self; public function like(string $identifier, string $like) : self; public function notLike(string $identifier, string $notLike) : self; public function literal(string $literal) : self; public function expression(string $expression, array $parameters = null) : self; public function isNull(string $identifier) : self; public function isNotNull(string $identifier) : self; public function in(string $identifier, array $valueSet = []) : self; public function notIn(string $identifier, array $valueSet = []) : self; public function between( string $identifier, int|float|string $minValue, int|float|string $maxValue ) : self; public function notBetween( string $identifier, int|float|string $minValue, int|float|string $maxValue ) : self; public function predicate(PredicateInterface $predicate) : self; // Inherited From PredicateSet public function addPredicate(PredicateInterface $predicate, $combination = null) : self; public function getPredicates() PredicateInterface[]; public function orPredicate(PredicateInterface $predicate) : self; public function andPredicate(PredicateInterface $predicate) : self; public function getExpressionData() : array; public function count() : int; } Each method in the API will produce a corresponding Predicate object of a similarly named type, as described below. equalTo(), lessThan(), greaterThan(), lessThanOrEqualTo(), greaterThanOrEqualTo() $where->equalTo('id', 5); // The above is equivalent to: $where->addPredicate( new Predicate\\Operator($left, Operator::OPERATOR_EQUAL_TO, $right, $leftType, $rightType) ); Operators use the following API: class Operator implements PredicateInterface { const OPERATOR_EQUAL_TO = '='; const OP_EQ = '='; const OPERATOR_NOT_EQUAL_TO = '!='; const OP_NE = '!='; const OPERATOR_LESS_THAN = '<'; const OP_LT = '<'; const OPERATOR_LESS_THAN_OR_EQUAL_TO = '<='; const OP_LTE = '<='; const OPERATOR_GREATER_THAN = '>'; const OP_GT = '>'; const OPERATOR_GREATER_THAN_OR_EQUAL_TO = '>='; const OP_GTE = '>='; public function __construct( int|float|bool|string $left = null, string $operator = self::OPERATOR_EQUAL_TO, int|float|bool|string $right = null, string $leftType = self::TYPE_IDENTIFIER, string $rightType = self::TYPE_VALUE ); public function setLeft(int|float|bool|string $left); public function getLeft() : int|float|bool|string; public function setLeftType(string $type) : self; public function getLeftType() : string; public function setOperator(string $operator); public function getOperator() : string; public function setRight(int|float|bool|string $value) : self; public function getRight() : int|float|bool|string; public function setRightType(string $type) : self; public function getRightType() : string; public function getExpressionData() : array; } like($identifier, $like), notLike($identifier, $notLike) $where->like($identifier, $like): // The above is equivalent to: $where->addPredicate( new Predicate\\Like($identifier, $like) ); The following is the Like API: class Like implements PredicateInterface { public function __construct(string $identifier = null, string $like = null); public function setIdentifier(string $identifier) : self; public function getIdentifier() : string; public function setLike(string $like) : self; public function getLike() : string; } literal($literal) $where->literal($literal); // The above is equivalent to: $where->addPredicate( new Predicate\\Literal($literal) ); The following is the Literal API: class Literal implements ExpressionInterface, PredicateInterface { const PLACEHOLDER = '?'; public function __construct(string $literal = ''); public function setLiteral(string $literal) : self; public function getLiteral() : string; } expression($expression, $parameter) $where->expression($expression, $parameter); // The above is equivalent to: $where->addPredicate( new Predicate\\Expression($expression, $parameter) ); The following is the Expression API: class Expression implements ExpressionInterface, PredicateInterface { const PLACEHOLDER = '?'; public function __construct( string $expression = null, int|float|bool|string|array $valueParameter = null /* [, $valueParameter, ... ] */ ); public function setExpression(string $expression) : self; public function getExpression() : string; public function setParameters(int|float|bool|string|array $parameters) : self; public function getParameters() : array; } isNull($identifier) $where->isNull($identifier); // The above is equivalent to: $where->addPredicate( new Predicate\\IsNull($identifier) ); The following is the IsNull API: class IsNull implements PredicateInterface { public function __construct(string $identifier = null); public function setIdentifier(string $identifier) : self; public function getIdentifier() : string; } isNotNull($identifier) $where->isNotNull($identifier); // The above is equivalent to: $where->addPredicate( new Predicate\\IsNotNull($identifier) ); The following is the IsNotNull API: class IsNotNull implements PredicateInterface { public function __construct(string $identifier = null); public function setIdentifier(string $identifier) : self; public function getIdentifier() : string; } in($identifier, $valueSet), notIn($identifier, $valueSet) $where->in($identifier, $valueSet); // The above is equivalent to: $where->addPredicate( new Predicate\\In($identifier, $valueSet) ); The following is the In API: class In implements PredicateInterface { public function __construct( string|array $identifier = null, array|Select $valueSet = null ); public function setIdentifier(string|array $identifier) : self; public function getIdentifier() : string|array; public function setValueSet(array|Select $valueSet) : self; public function getValueSet() : array|Select; } between($identifier, $minValue, $maxValue), notBetween($identifier, $minValue, $maxValue) $where->between($identifier, $minValue, $maxValue); // The above is equivalent to: $where->addPredicate( new Predicate\\Between($identifier, $minValue, $maxValue) ); The following is the Between API: class Between implements PredicateInterface { public function __construct( string $identifier = null, int|float|string $minValue = null, int|float|string $maxValue = null ); public function setIdentifier(string $identifier) : self; public function getIdentifier() : string; public function setMinValue(int|float|string $minValue) : self; public function getMinValue() : int|float|string; public function setMaxValue(int|float|string $maxValue) : self; public function getMaxValue() : int|float|string; public function setSpecification(string $specification); }","title":"SQL Abstraction"},{"location":"sql/#sql-abstraction","text":"Laminas\\Db\\Sql is a SQL abstraction layer for building platform-specific SQL queries via an object-oriented API. The end result of a Laminas\\Db\\Sql object will be to either produce a Statement and ParameterContainer that represents the target query, or a full string that can be directly executed against the database platform. To achieve this, Laminas\\Db\\Sql objects require a Laminas\\Db\\Adapter\\Adapter object in order to produce the desired results.","title":"SQL Abstraction"},{"location":"sql/#quick-start","text":"There are four primary tasks associated with interacting with a database defined by Data Manipulation Language (DML): selecting, inserting, updating, and deleting. As such, there are four primary classes that developers can interact with in order to build queries in the Laminas\\Db\\Sql namespace: Select , Insert , Update , and Delete . Since these four tasks are so closely related and generally used together within the same application, the Laminas\\Db\\Sql\\Sql class helps you create them and produce the result you are attempting to achieve. use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); // returns a Laminas\\Db\\Sql\\Select instance $insert = $sql->insert(); // returns a Laminas\\Db\\Sql\\Insert instance $update = $sql->update(); // returns a Laminas\\Db\\Sql\\Update instance $delete = $sql->delete(); // returns a Laminas\\Db\\Sql\\Delete instance As a developer, you can now interact with these objects, as described in the sections below, to customize each query. Once they have been populated with values, they are ready to either be prepared or executed. To prepare (using a Select object): use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(['id' => 2]); $statement = $sql->prepareStatementForSqlObject($select); $results = $statement->execute(); To execute (using a Select object) use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(['id' => 2]); $selectString = $sql->buildSqlString($select); $results = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE); Laminas\\\\Db\\\\Sql\\\\Sql objects can also be bound to a particular table so that in obtaining a Select , Insert , Update , or Delete instance, the object will be seeded with the table: use Laminas\\Db\\Sql\\Sql; $sql = new Sql($adapter, 'foo'); $select = $sql->select(); $select->where(['id' => 2]); // $select already has from('foo') applied","title":"Quick start"},{"location":"sql/#common-interfaces-for-sql-implementations","text":"Each of these objects implements the following two interfaces: interface PreparableSqlInterface { public function prepareStatement(Adapter $adapter, StatementInterface $statement) : void; } interface SqlInterface { public function getSqlString(PlatformInterface $adapterPlatform = null) : string; } Use these functions to produce either (a) a prepared statement, or (b) a string to execute.","title":"Common interfaces for SQL implementations"},{"location":"sql/#select","text":"Laminas\\Db\\Sql\\Select presents a unified API for building platform-specific SQL SELECT queries. Instances may be created and consumed without Laminas\\Db\\Sql\\Sql : use Laminas\\Db\\Sql\\Select; $select = new Select(); // or, to produce a $select bound to a specific table $select = new Select('foo'); If a table is provided to the Select object, then from() cannot be called later to change the name of the table. Once you have a valid Select object, the following API can be used to further specify various select statement parts: class Select extends AbstractSql implements SqlInterface, PreparableSqlInterface { const JOIN_INNER = 'inner'; const JOIN_OUTER = 'outer'; const JOIN_FULL_OUTER = 'full outer'; const JOIN_LEFT = 'left'; const JOIN_RIGHT = 'right'; const SQL_STAR = '*'; const ORDER_ASCENDING = 'ASC'; const ORDER_DESCENDING = 'DESC'; public $where; // @param Where $where public function __construct(string|array|TableIdentifier $table = null); public function from(string|array|TableIdentifier $table) : self; public function columns(array $columns, bool $prefixColumnsWithTable = true) : self; public function join(string|array|TableIdentifier $name, string $on, string|array $columns = self::SQL_STAR, string $type = self::JOIN_INNER) : self; public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; public function group(string|array $group); public function having(Having|callable|string|array $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; public function order(string|array $order) : self; public function limit(int $limit) : self; public function offset(int $offset) : self; }","title":"Select"},{"location":"sql/#insert","text":"The Insert API: class Insert implements SqlInterface, PreparableSqlInterface { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public function __construct(string|TableIdentifier $table = null); public function into(string|TableIdentifier $table) : self; public function columns(array $columns) : self; public function values(array $values, string $flag = self::VALUES_SET) : self; } As with Select , the table may be provided during instantiation or via the into() method.","title":"Insert"},{"location":"sql/#update","text":"class Update { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public $where; // @param Where $where public function __construct(string|TableIdentifier $table = null); public function table(string|TableIdentifier $table) : self; public function set(array $values, string $flag = self::VALUES_SET) : self; public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; }","title":"Update"},{"location":"sql/#delete","text":"class Delete { public $where; // @param Where $where public function __construct(string|TableIdentifier $table = null); public function from(string|TableIdentifier $table); public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\\PredicateSet::OP_AND) : self; }","title":"Delete"},{"location":"sql/#where-and-having","text":"In the following, we will talk about Where ; note, however, that Having utilizes the same API. Effectively, Where and Having extend from the same base object, a Predicate (and PredicateSet ). All of the parts that make up a WHERE or HAVING clause that are AND'ed or OR'd together are called predicates . The full set of predicates is called a PredicateSet . A Predicate generally contains the values (and identifiers) separate from the fragment they belong to until the last possible moment when the statement is either prepared (parameteritized) or executed. In parameterization, the parameters will be replaced with their proper placeholder (a named or positional parameter), and the values stored inside an Adapter\\ParameterContainer . When executed, the values will be interpolated into the fragments they belong to and properly quoted. In the Where / Having API, a distinction is made between what elements are considered identifiers ( TYPE_IDENTIFIER ) and which are values ( TYPE_VALUE ). There is also a special use case type for literal values ( TYPE_LITERAL ). All element types are expressed via the Laminas\\Db\\Sql\\ExpressionInterface interface.","title":"Where and Having"},{"location":"table-gateway/","text":"Table Gateways The Table Gateway subcomponent provides an object-oriented representation of a database table; its methods mirror the most common table operations. In code, the interface resembles: namespace Laminas\\Db\\TableGateway; use Laminas\\Db\\ResultSet\\ResultSetInterface; use Laminas\\Db\\Sql\\Where; interface TableGatewayInterface { public function getTable() : string; public function select(Where|callable|string|array $where = null) : ResultSetInterface; public function insert(array $set) : int; public function update( array $set, Where|callable|string|array $where = null, array $joins = null ) : int; public function delete(Where|callable|string|array $where) : int; } There are two primary implementations of the TableGatewayInterface , AbstractTableGateway and TableGateway . The AbstractTableGateway is an abstract basic implementation that provides functionality for select() , insert() , update() , delete() , as well as an additional API for doing these same kinds of tasks with explicit Laminas\\Db\\Sql objects: selectWith() , insertWith() , updateWith() , and deleteWith() . In addition, AbstractTableGateway also implements a \"Feature\" API, that allows for expanding the behaviors of the base TableGateway implementation without having to extend the class with this new functionality. The TableGateway concrete implementation simply adds a sensible constructor to the AbstractTableGateway class so that out-of-the-box, TableGateway does not need to be extended in order to be consumed and utilized to its fullest. Quick start The following example uses Laminas\\Db\\TableGateway\\TableGateway , which defines the following API: namespace Laminas\\Db\\TableGateway; use Laminas\\Db\\Adapter\\AdapterInterface; use Laminas\\Db\\ResultSet\\ResultSet; use Laminas\\Db\\ResultSet\\ResultSetInterface; use Laminas\\Db\\Sql; use Laminas\\Db\\Sql\\TableIdentifier; class TableGateway extends AbstractTableGateway { public $lastInsertValue; public $table; public $adapter; public function __construct( string|TableIdentifier $table, AdapterInterface $adapter, Feature\\AbstractFeature|Feature\\FeatureSet|Feature\\AbstractFeature[] $features = null, ResultSetInterface $resultSetPrototype = null, Sql\\Sql $sql = null ); /** Inherited from AbstractTableGateway */ public function isInitialized() : bool; public function initialize() : void; public function getTable() : string; public function getAdapter() : AdapterInterface; public function getColumns() : array; public function getFeatureSet() Feature\\FeatureSet; public function getResultSetPrototype() : ResultSetInterface; public function getSql() | Sql\\Sql; public function select(Sql\\Where|callable|string|array $where = null) : ResultSetInterface; public function selectWith(Sql\\Select $select) : ResultSetInterface; public function insert(array $set) : int; public function insertWith(Sql\\Insert $insert) | int; public function update( array $set, Sql\\Where|callable|string|array $where = null, array $joins = null ) : int; public function updateWith(Sql\\Update $update) : int; public function delete(Sql\\Where|callable|string|array $where) : int; public function deleteWith(Sql\\Delete $delete) : int; public function getLastInsertValue() : int; } The concrete TableGateway object uses constructor injection for getting dependencies and options into the instance. The table name and an instance of an Adapter are all that is required to create an instance. Out of the box, this implementation makes no assumptions about table structure or metadata, and when select() is executed, a simple ResultSet object with the populated Adapter 's Result (the datasource) will be returned and ready for iteration. use Laminas\\Db\\TableGateway\\TableGateway; $projectTable = new TableGateway('project', $adapter); $rowset = $projectTable->select(['type' => 'PHP']); echo 'Projects of type PHP: ' . PHP_EOL; foreach ($rowset as $projectRow) { echo $projectRow['name'] . PHP_EOL; } // Or, when expecting a single row: $artistTable = new TableGateway('artist', $adapter); $rowset = $artistTable->select(['id' => 2]); $artistRow = $rowset->current(); var_dump($artistRow); The select() method takes the same arguments as Laminas\\Db\\Sql\\Select::where() ; arguments will be passed to the Select instance used to build the SELECT query. This means the following is possible: use Laminas\\Db\\TableGateway\\TableGateway; use Laminas\\Db\\Sql\\Select; $artistTable = new TableGateway('artist', $adapter); // Search for at most 2 artists who's name starts with Brit, ascending: $rowset = $artistTable->select(function (Select $select) { $select->where->like('name', 'Brit%'); $select->order('name ASC')->limit(2); }); TableGateway Features The Features API allows for extending the functionality of the base TableGateway object without having to polymorphically extend the base class. This allows for a wider array of possible mixing and matching of features to achieve a particular behavior that needs to be attained to make the base implementation of TableGateway useful for a particular problem. With the TableGateway object, features should be injected through the constructor. The constructor can take features in 3 different forms: as a single Feature instance as a FeatureSet instance as an array of Feature instances There are a number of features built-in and shipped with laminas-db: GlobalAdapterFeature : the ability to use a global/static adapter without needing to inject it into a TableGateway instance. This is only useful when you are extending the AbstractTableGateway implementation: use Laminas\\Db\\TableGateway\\AbstractTableGateway; use Laminas\\Db\\TableGateway\\Feature; class MyTableGateway extends AbstractTableGateway { public function __construct() { $this->table = 'my_table'; $this->featureSet = new Feature\\FeatureSet(); $this->featureSet->addFeature(new Feature\\GlobalAdapterFeature()); $this->initialize(); } } // elsewhere in code, in a bootstrap Laminas\\Db\\TableGateway\\Feature\\GlobalAdapterFeature::setStaticAdapter($adapter); // in a controller, or model somewhere $table = new MyTableGateway(); // adapter is statically loaded MasterSlaveFeature : the ability to use a master adapter for insert() , update() , and delete() , but switch to a slave adapter for all select() operations. $table = new TableGateway('artist', $adapter, new Feature\\MasterSlaveFeature($slaveAdapter)); MetadataFeature : the ability populate TableGateway with column information from a Metadata object. It will also store the primary key information in case the RowGatewayFeature needs to consume this information. $table = new TableGateway('artist', $adapter, new Feature\\MetadataFeature()); EventFeature : the ability to compose a laminas-eventmanager EventManager instance within your TableGateway instance, and attach listeners to the various events of its lifecycle. See the section on lifecycle events below for more information on available events and the parameters they compose. $table = new TableGateway('artist', $adapter, new Feature\\EventFeature($eventManagerInstance)); RowGatewayFeature : the ability for select() to return a ResultSet object that upon iteration will return a RowGateway instance for each row. $table = new TableGateway('artist', $adapter, new Feature\\RowGatewayFeature('id')); $results = $table->select(['id' => 2]); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save(); TableGateway LifeCycle Events When the EventFeature is enabled on the TableGateway instance, you may attach to any of the following events, which provide access to the parameters listed. preInitialize (no parameters) postInitialize (no parameters) preSelect , with the following parameters: select , with type Laminas\\Db\\Sql\\Select postSelect , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface resultSet , with type Laminas\\Db\\ResultSet\\ResultSetInterface preInsert , with the following parameters: insert , with type Laminas\\Db\\Sql\\Insert postInsert , with the following parameters: statement with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result with type Laminas\\Db\\Adapter\\Driver\\ResultInterface preUpdate , with the following parameters: update , with type Laminas\\Db\\Sql\\Update postUpdate , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface preDelete , with the following parameters: delete , with type Laminas\\Db\\Sql\\Delete postDelete , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface Listeners receive a Laminas\\Db\\TableGateway\\Feature\\EventFeature\\TableGatewayEvent instance as an argument. Within the listener, you can retrieve a parameter by name from the event using the following syntax: $parameter = $event->getParam($paramName); As an example, you might attach a listener on the postInsert event as follows: use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\TableGateway\\Feature\\EventFeature\\TableGatewayEvent; use Laminas\\EventManager\\EventManager; /** @var EventManager $eventManager */ $eventManager->attach('postInsert', function (TableGatewayEvent $event) { /** @var ResultInterface $result */ $result = $event->getParam('result'); $generatedId = $result->getGeneratedValue(); // do something with the generated identifier... });","title":"Table Gateways"},{"location":"table-gateway/#table-gateways","text":"The Table Gateway subcomponent provides an object-oriented representation of a database table; its methods mirror the most common table operations. In code, the interface resembles: namespace Laminas\\Db\\TableGateway; use Laminas\\Db\\ResultSet\\ResultSetInterface; use Laminas\\Db\\Sql\\Where; interface TableGatewayInterface { public function getTable() : string; public function select(Where|callable|string|array $where = null) : ResultSetInterface; public function insert(array $set) : int; public function update( array $set, Where|callable|string|array $where = null, array $joins = null ) : int; public function delete(Where|callable|string|array $where) : int; } There are two primary implementations of the TableGatewayInterface , AbstractTableGateway and TableGateway . The AbstractTableGateway is an abstract basic implementation that provides functionality for select() , insert() , update() , delete() , as well as an additional API for doing these same kinds of tasks with explicit Laminas\\Db\\Sql objects: selectWith() , insertWith() , updateWith() , and deleteWith() . In addition, AbstractTableGateway also implements a \"Feature\" API, that allows for expanding the behaviors of the base TableGateway implementation without having to extend the class with this new functionality. The TableGateway concrete implementation simply adds a sensible constructor to the AbstractTableGateway class so that out-of-the-box, TableGateway does not need to be extended in order to be consumed and utilized to its fullest.","title":"Table Gateways"},{"location":"table-gateway/#quick-start","text":"The following example uses Laminas\\Db\\TableGateway\\TableGateway , which defines the following API: namespace Laminas\\Db\\TableGateway; use Laminas\\Db\\Adapter\\AdapterInterface; use Laminas\\Db\\ResultSet\\ResultSet; use Laminas\\Db\\ResultSet\\ResultSetInterface; use Laminas\\Db\\Sql; use Laminas\\Db\\Sql\\TableIdentifier; class TableGateway extends AbstractTableGateway { public $lastInsertValue; public $table; public $adapter; public function __construct( string|TableIdentifier $table, AdapterInterface $adapter, Feature\\AbstractFeature|Feature\\FeatureSet|Feature\\AbstractFeature[] $features = null, ResultSetInterface $resultSetPrototype = null, Sql\\Sql $sql = null ); /** Inherited from AbstractTableGateway */ public function isInitialized() : bool; public function initialize() : void; public function getTable() : string; public function getAdapter() : AdapterInterface; public function getColumns() : array; public function getFeatureSet() Feature\\FeatureSet; public function getResultSetPrototype() : ResultSetInterface; public function getSql() | Sql\\Sql; public function select(Sql\\Where|callable|string|array $where = null) : ResultSetInterface; public function selectWith(Sql\\Select $select) : ResultSetInterface; public function insert(array $set) : int; public function insertWith(Sql\\Insert $insert) | int; public function update( array $set, Sql\\Where|callable|string|array $where = null, array $joins = null ) : int; public function updateWith(Sql\\Update $update) : int; public function delete(Sql\\Where|callable|string|array $where) : int; public function deleteWith(Sql\\Delete $delete) : int; public function getLastInsertValue() : int; } The concrete TableGateway object uses constructor injection for getting dependencies and options into the instance. The table name and an instance of an Adapter are all that is required to create an instance. Out of the box, this implementation makes no assumptions about table structure or metadata, and when select() is executed, a simple ResultSet object with the populated Adapter 's Result (the datasource) will be returned and ready for iteration. use Laminas\\Db\\TableGateway\\TableGateway; $projectTable = new TableGateway('project', $adapter); $rowset = $projectTable->select(['type' => 'PHP']); echo 'Projects of type PHP: ' . PHP_EOL; foreach ($rowset as $projectRow) { echo $projectRow['name'] . PHP_EOL; } // Or, when expecting a single row: $artistTable = new TableGateway('artist', $adapter); $rowset = $artistTable->select(['id' => 2]); $artistRow = $rowset->current(); var_dump($artistRow); The select() method takes the same arguments as Laminas\\Db\\Sql\\Select::where() ; arguments will be passed to the Select instance used to build the SELECT query. This means the following is possible: use Laminas\\Db\\TableGateway\\TableGateway; use Laminas\\Db\\Sql\\Select; $artistTable = new TableGateway('artist', $adapter); // Search for at most 2 artists who's name starts with Brit, ascending: $rowset = $artistTable->select(function (Select $select) { $select->where->like('name', 'Brit%'); $select->order('name ASC')->limit(2); });","title":"Quick start"},{"location":"table-gateway/#tablegateway-features","text":"The Features API allows for extending the functionality of the base TableGateway object without having to polymorphically extend the base class. This allows for a wider array of possible mixing and matching of features to achieve a particular behavior that needs to be attained to make the base implementation of TableGateway useful for a particular problem. With the TableGateway object, features should be injected through the constructor. The constructor can take features in 3 different forms: as a single Feature instance as a FeatureSet instance as an array of Feature instances There are a number of features built-in and shipped with laminas-db: GlobalAdapterFeature : the ability to use a global/static adapter without needing to inject it into a TableGateway instance. This is only useful when you are extending the AbstractTableGateway implementation: use Laminas\\Db\\TableGateway\\AbstractTableGateway; use Laminas\\Db\\TableGateway\\Feature; class MyTableGateway extends AbstractTableGateway { public function __construct() { $this->table = 'my_table'; $this->featureSet = new Feature\\FeatureSet(); $this->featureSet->addFeature(new Feature\\GlobalAdapterFeature()); $this->initialize(); } } // elsewhere in code, in a bootstrap Laminas\\Db\\TableGateway\\Feature\\GlobalAdapterFeature::setStaticAdapter($adapter); // in a controller, or model somewhere $table = new MyTableGateway(); // adapter is statically loaded MasterSlaveFeature : the ability to use a master adapter for insert() , update() , and delete() , but switch to a slave adapter for all select() operations. $table = new TableGateway('artist', $adapter, new Feature\\MasterSlaveFeature($slaveAdapter)); MetadataFeature : the ability populate TableGateway with column information from a Metadata object. It will also store the primary key information in case the RowGatewayFeature needs to consume this information. $table = new TableGateway('artist', $adapter, new Feature\\MetadataFeature()); EventFeature : the ability to compose a laminas-eventmanager EventManager instance within your TableGateway instance, and attach listeners to the various events of its lifecycle. See the section on lifecycle events below for more information on available events and the parameters they compose. $table = new TableGateway('artist', $adapter, new Feature\\EventFeature($eventManagerInstance)); RowGatewayFeature : the ability for select() to return a ResultSet object that upon iteration will return a RowGateway instance for each row. $table = new TableGateway('artist', $adapter, new Feature\\RowGatewayFeature('id')); $results = $table->select(['id' => 2]); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save();","title":"TableGateway Features"},{"location":"table-gateway/#tablegateway-lifecycle-events","text":"When the EventFeature is enabled on the TableGateway instance, you may attach to any of the following events, which provide access to the parameters listed. preInitialize (no parameters) postInitialize (no parameters) preSelect , with the following parameters: select , with type Laminas\\Db\\Sql\\Select postSelect , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface resultSet , with type Laminas\\Db\\ResultSet\\ResultSetInterface preInsert , with the following parameters: insert , with type Laminas\\Db\\Sql\\Insert postInsert , with the following parameters: statement with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result with type Laminas\\Db\\Adapter\\Driver\\ResultInterface preUpdate , with the following parameters: update , with type Laminas\\Db\\Sql\\Update postUpdate , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface preDelete , with the following parameters: delete , with type Laminas\\Db\\Sql\\Delete postDelete , with the following parameters: statement , with type Laminas\\Db\\Adapter\\Driver\\StatementInterface result , with type Laminas\\Db\\Adapter\\Driver\\ResultInterface Listeners receive a Laminas\\Db\\TableGateway\\Feature\\EventFeature\\TableGatewayEvent instance as an argument. Within the listener, you can retrieve a parameter by name from the event using the following syntax: $parameter = $event->getParam($paramName); As an example, you might attach a listener on the postInsert event as follows: use Laminas\\Db\\Adapter\\Driver\\ResultInterface; use Laminas\\Db\\TableGateway\\Feature\\EventFeature\\TableGatewayEvent; use Laminas\\EventManager\\EventManager; /** @var EventManager $eventManager */ $eventManager->attach('postInsert', function (TableGatewayEvent $event) { /** @var ResultInterface $result */ $result = $event->getParam('result'); $generatedId = $result->getGeneratedValue(); // do something with the generated identifier... });","title":"TableGateway LifeCycle Events"},{"location":"adapters/adapter-aware-trait/","text":"AdapterAwareTrait The trait Laminas\\Db\\Adapter\\AdapterAwareTrait , which provides implementation for Laminas\\Db\\Adapter\\AdapterAwareInterface , and allowed removal of duplicated implementations in several components of Laminas or in custom applications. The interface defines only the method setDbAdapter() with one parameter for an instance of Laminas\\Db\\Adapter\\Adapter : public function setDbAdapter(\\Laminas\\Db\\Adapter\\Adapter $adapter) : self; Basic Usage Create Class and Add Trait use Laminas\\Db\\Adapter\\AdapterAwareTrait; use Laminas\\Db\\Adapter\\AdapterAwareInterface; class Example implements AdapterAwareInterface { use AdapterAwareTrait; } Create and Set Adapter Create a database adapter and set the adapter to the instance of the Example class: $adapter = new Laminas\\Db\\Adapter\\Adapter([ 'driver' => 'Pdo_Sqlite', 'database' => 'path/to/sqlite.db', ]); $example = new Example(); $example->setAdapter($adapter); AdapterServiceDelegator The delegator Laminas\\Db\\Adapter\\AdapterServiceDelegator can be used to set a database adapter via the service manager of laminas-servicemanager . The delegator tries to fetch a database adapter via the name Laminas\\Db\\Adapter\\AdapterInterface from the service container and sets the adapter to the requested service. The adapter itself must be an instance of Laminas\\Db\\Adapter\\Adapter . Integration for Mezzio and laminas-mvc based Applications In a Mezzio or laminas-mvc based application the database adapter is already registered during the installation with the laminas-component-installer. Create Class and Use Trait Create a class and add the trait AdapterAwareTrait . use Laminas\\Db\\Adapter\\Adapter; use Laminas\\Db\\Adapter\\AdapterInterface; class Example implements AdapterAwareInterface { use AdapterAwareTrait; public function getAdapter() : ?Adapter { return $this->adapter; } } (A getter method is also added for demonstration.) Create and Configure Service Manager Create and configured the service manager : use Interop\\Container\\ContainerInterface; use Laminas\\Db\\Adapter\\AdapterInterface; use Laminas\\Db\\Adapter\\AdapterServiceDelegator; use Laminas\\Db\\Adapter\\AdapterAwareTrait; use Laminas\\Db\\Adapter\\AdapterAwareInterface; $serviceManager = new Laminas\\ServiceManager\\ServiceManager([ 'factories' => [ // Database adapter AdapterInterface::class => static function(ContainerInterface $container) { return new Laminas\\Db\\Adapter\\Adapter([ 'driver' => 'Pdo_Sqlite', 'database' => 'path/to/sqlite.db', ]); } ], 'invokables' => [ // Example class Example::class => Example::class, ], 'delegators' => [ // Delegator for Example class to set the adapter Example::class => [ AdapterServiceDelegator::class, ], ], ]); Get Instance of Class Retrieving an instance of the Example class with a database adapter: /** @var Example $example */ $example = $serviceManager->get(Example::class); var_dump($example->getAdapter() instanceof Laminas\\Db\\Adapter\\Adapter); // true Concrete Implementations The validators Db\\RecordExists and Db\\NoRecordExists implements the trait and the plugin manager of laminas-validator includes the delegator to set the database adapter for both validators.","title":"AdapterAwareTrait"},{"location":"adapters/adapter-aware-trait/#adapterawaretrait","text":"The trait Laminas\\Db\\Adapter\\AdapterAwareTrait , which provides implementation for Laminas\\Db\\Adapter\\AdapterAwareInterface , and allowed removal of duplicated implementations in several components of Laminas or in custom applications. The interface defines only the method setDbAdapter() with one parameter for an instance of Laminas\\Db\\Adapter\\Adapter : public function setDbAdapter(\\Laminas\\Db\\Adapter\\Adapter $adapter) : self;","title":"AdapterAwareTrait"},{"location":"adapters/adapter-aware-trait/#basic-usage","text":"","title":"Basic Usage"},{"location":"adapters/adapter-aware-trait/#adapterservicedelegator","text":"The delegator Laminas\\Db\\Adapter\\AdapterServiceDelegator can be used to set a database adapter via the service manager of laminas-servicemanager . The delegator tries to fetch a database adapter via the name Laminas\\Db\\Adapter\\AdapterInterface from the service container and sets the adapter to the requested service. The adapter itself must be an instance of Laminas\\Db\\Adapter\\Adapter .","title":"AdapterServiceDelegator"},{"location":"adapters/adapter-aware-trait/#concrete-implementations","text":"The validators Db\\RecordExists and Db\\NoRecordExists implements the trait and the plugin manager of laminas-validator includes the delegator to set the database adapter for both validators.","title":"Concrete Implementations"},{"location":"application-integration/usage-in-a-laminas-mvc-application/","text":"Usage in a laminas-mvc Application The minimal installation for a laminas-mvc based application doesn't include any database features. When installing the Laminas MVC Skeleton Application While Composer is installing the MVC Application , you can add the laminas-db package while prompted. Adding to an existing Laminas MVC Skeleton Application If the MVC application is already created, then use Composer to add the laminas-db package. The Abstract Factory Now that the laminas-db package is installed, the abstract factory Laminas\\Db\\Adapter\\AdapterAbstractServiceFactory is available to be used with the service configuration. Configuring the adapter The abstract factory expects the configuration key db in order to create a Laminas\\Db\\Adapter\\Adapter instance. Working with a Sqlite database Sqlite is a lightweight option to have the application working with a database. Here is an example of the configuration array for a sqlite database. Assuming the sqlite file path is data/sample.sqlite , the following configuration will produce the adapter: return [ 'db' => [ 'driver' => 'Pdo', 'adapters' => [ sqliteAdapter::class => [ 'driver' => 'Pdo', 'dsn' => 'sqlite:data/sample.sqlite', ], ], ], ]; The data/ filepath for the sqlite file is the default data/ directory from the Laminas MVC application. Working with a MySQL database Unlike a sqlite database, the MySQL database adapter requires a MySQL server. Here is an example of a configuration array for a MySQL database. return [ 'db' => [ 'driver' => 'Pdo', 'adapters' => [ mysqlAdapter::class => [ 'driver' => 'Pdo', 'dsn' => 'mysql:dbname=your_database_name;host=your_mysql_host;charset=utf8', 'username' => 'your_mysql_username', 'password' => 'your_mysql_password', 'driver_options' => [ PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \\'UTF8\\'' ], ], ], ], ]; Working with the adapter Once you have configured an adapter, as in the above examples, you now have a Laminas\\Db\\Adapter\\Adapter available to your application. A factory for a class that consumes an adapter can pull the adapter by the name used in configuration. As an example, for the sqlite database configured earlier, we could write the following: use sqliteAdapter ; $adapter = $container->get(sqliteAdapter::class) ; For the MySQL Database configured earlier: use mysqlAdapter ; $adapter = $container->get(mysqlAdapter::class) ; You can read more about the adapter in the adapter chapter of the documentation . Running with Docker When working with a MySQL database and when running the application with Docker, some files need to be added or adjusted. Adding the MySQL extension to the PHP container Change the Dockerfile to add the PDO MySQL extension to PHP. FROM php:7.3-apache RUN apt-get update \\ && apt-get install -y git zlib1g-dev libzip-dev \\ && docker-php-ext-install zip pdo_mysql \\ && a2enmod rewrite \\ && sed -i 's!/var/www/html!/var/www/public!g' /etc/apache2/sites-available/000-default.conf \\ && mv /var/www/html /var/www/public \\ && curl -sS https://getcomposer.org/installer \\ | php -- --install-dir=/usr/local/bin --filename=composer WORKDIR /var/www Adding the mysql container Change the docker-compose.yml file to add a new container for mysql. mysql: image: mysql ports: - 3306:3306 command: --default-authentication-plugin=mysql_native_password volumes: - ./.data/db:/var/lib/mysql - ./.docker/mysql/:/docker-entrypoint-initdb.d/ environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} Though it is not the topic to explain how to write a docker-compose.yml file, a few details need to be highlighted : The name of the container is mysql . MySQL database files will be stored in the directory /.data/db/ . SQL schemas will need to be added to the /.docker/mysql/ directory so that Docker will be able to build and populate the database(s). The mysql docker image is using the $MYSQL_ROOT_PASSWORD environment variable to set the mysql root password. Link the containers Now link the mysql container and the laminas container so that the application knows where to find the mysql server. laminas: build: context: . dockerfile: Dockerfile ports: - 8080:80 volumes: - .:/var/www links: - mysql:mysql Adding phpMyAdmin Optionnally, you can also add a container for phpMyAdmin. phpmyadmin: image: phpmyadmin/phpmyadmin ports: - 8081:80 environment: - PMA_HOST=${PMA_HOST} The image uses the $PMA_HOST environment variable to set the host of the mysql server. The expected value is the name of the mysql container. Putting everything together: version: \"2.1\" services: laminas: build: context: . dockerfile: Dockerfile ports: - 8080:80 volumes: - .:/var/www links: - mysql:mysql mysql: image: mysql ports: - 3306:3306 command: --default-authentication-plugin=mysql_native_password volumes: - ./.data/db:/var/lib/mysql - ./.docker/mysql/:/docker-entrypoint-initdb.d/ environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} phpmyadmin: image: phpmyadmin/phpmyadmin ports: - 8081:80 environment: - PMA_HOST=${PMA_HOST} Defining credentials The docker-compose.yml file uses ENV variables to define the credentials. Docker will read the ENV variables from a .env file. MYSQL_ROOT_PASSWORD=rootpassword PMA_HOST=mysql Initiating the database schemas At build, if the /.data/db directory is missing, Docker will create the mysql database with any .sql files found in the .docker/mysql/ directory. (These are the files with the CREATE DATABASE , USE (database) , and CREATE TABLE, INSERT INTO directives defined earlier in this document). If multiple .sql files are present, it is a good idea to safely order the list because Docker will read the files in ascending order.","title":"Integrating in a Laminas MVC application"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#usage-in-a-laminas-mvc-application","text":"The minimal installation for a laminas-mvc based application doesn't include any database features.","title":"Usage in a laminas-mvc Application"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#when-installing-the-laminas-mvc-skeleton-application","text":"While Composer is installing the MVC Application , you can add the laminas-db package while prompted.","title":"When installing the Laminas MVC Skeleton Application"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#adding-to-an-existing-laminas-mvc-skeleton-application","text":"If the MVC application is already created, then use Composer to add the laminas-db package.","title":"Adding to an existing Laminas MVC Skeleton Application"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#the-abstract-factory","text":"Now that the laminas-db package is installed, the abstract factory Laminas\\Db\\Adapter\\AdapterAbstractServiceFactory is available to be used with the service configuration.","title":"The Abstract Factory"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#working-with-the-adapter","text":"Once you have configured an adapter, as in the above examples, you now have a Laminas\\Db\\Adapter\\Adapter available to your application. A factory for a class that consumes an adapter can pull the adapter by the name used in configuration. As an example, for the sqlite database configured earlier, we could write the following: use sqliteAdapter ; $adapter = $container->get(sqliteAdapter::class) ; For the MySQL Database configured earlier: use mysqlAdapter ; $adapter = $container->get(mysqlAdapter::class) ; You can read more about the adapter in the adapter chapter of the documentation .","title":"Working with the adapter"},{"location":"application-integration/usage-in-a-laminas-mvc-application/#running-with-docker","text":"When working with a MySQL database and when running the application with Docker, some files need to be added or adjusted.","title":"Running with Docker"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index b9a8e9b3..629da71d 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,52 +2,52 @@ https://docs.laminas.dev/laminas-db/ - 2021-09-21 + 2024-02-01 daily https://docs.laminas.dev/laminas-db/adapter/ - 2021-09-21 + 2024-02-01 daily https://docs.laminas.dev/laminas-db/metadata/ - 2021-09-21 + 2024-02-01 daily https://docs.laminas.dev/laminas-db/result-set/ - 2021-09-21 + 2024-02-01 daily https://docs.laminas.dev/laminas-db/row-gateway/ - 2021-09-21 + 2024-02-01 daily https://docs.laminas.dev/laminas-db/sql-ddl/ - 2021-09-21 + 2024-02-01 daily https://docs.laminas.dev/laminas-db/sql/ - 2021-09-21 + 2024-02-01 daily https://docs.laminas.dev/laminas-db/table-gateway/ - 2021-09-21 + 2024-02-01 daily https://docs.laminas.dev/laminas-db/adapters/adapter-aware-trait/ - 2021-09-21 + 2024-02-01 daily https://docs.laminas.dev/laminas-db/application-integration/usage-in-a-laminas-mvc-application/ - 2021-09-21 + 2024-02-01 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 9bd2cb573861bda61a937d8cb89766c81f6ce5cb..b7635d2702fde723e171b3fdfe782bfd6c8d9f13 100644 GIT binary patch delta 293 zcmV+=0owkx0=5DOABzYGQ0cp6kq8`rwAx{t()6|`*dD+IFGV7dVmDdeexyyOoF`3U zzVKuHSRVpRbNK3AF;Zk3{Jz{)by<+t!C2qz%a8XrcrFj^rnyANBt<= znku$JJq}!j*eTYhG-0(QRb9Q5?WRaE7r3iiG%o0NuEME|37RX1z4geIp;0Y=8q85O zYId#{B1<1kyQ_CkQ177LCd-mr+4Kp0N1u_-twHOqjap^yMCu3Ww{U215Q=$2_9Tf@ zFmK98d~pKlj%CgnCg@OT!fW23e0E@r%N{asK*6J<|8d|;GvbE;oG=ndM4S1W!eMY$ rqof}QtQYFyO{)uIM=1jc4|hKlYFOF-eqXmCb*1(j9agTSDF*-mYE6m7 delta 292 zcmV+<0o(qz0<{7NABzYG{3}Xfkq8`rG^ce+)7ze4djJ=_6p28J-DG|H(KelOo-~R1 z!jJW1eF!k^;cIZkM3HUq`*K^=WkFsCV|~9bKi=Qqr95<-_7WYF6v^y)U!Fw9SEc58 zuGk6K%b+s$IO_AbO;Gyo(x}dvT6;5SL&|EnjtVga4O={79V2-L) zH|KgGvJAm=P2Fsv-a)fXmL<2c=@a^%J|mqwgVtSJwaPq*)DO~c;n3hH6!V50ND`-D z-jtE};snwi%bYXJ(4)|d*Stab?7$e8J!Ia1f=5UHHuE=y - + + + + + + + + @@ -303,8 +310,8 @@

    Search - - GitHub + + GitHub @@ -479,7 +486,7 @@

    Executing DDL Statements

    $sql = new Sql($adapter); $adapter->query( - $sql->getSqlStringForSqlObject($ddl), + $sql->buildSqlString($ddl), $adapter::QUERY_MODE_EXECUTE );

    By passing the $ddl object through the $sql instance's @@ -618,7 +625,9 @@

    Currently Supported Constraint Typ @@ -627,7 +636,9 @@

    Currently Supported Constraint Typ @@ -846,13 +857,13 @@

  • - +
  • - +
  • - +
  • @@ -868,7 +879,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -878,7 +889,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.

    diff --git a/sql/index.html b/sql/index.html index 07c00eb3..6fb71af1 100644 --- a/sql/index.html +++ b/sql/index.html @@ -5,7 +5,14 @@ - + + + + + + + + @@ -303,8 +310,8 @@

    Search - - GitHub + + GitHub @@ -963,7 +970,9 @@

  • @@ -972,7 +981,9 @@

    @@ -1191,13 +1202,13 @@

  • - +
  • - +
  • - +
  • @@ -1213,7 +1224,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -1223,7 +1234,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.

    diff --git a/table-gateway/index.html b/table-gateway/index.html index 1756fb93..ef45a531 100644 --- a/table-gateway/index.html +++ b/table-gateway/index.html @@ -5,7 +5,14 @@ - + + + + + + + + @@ -303,8 +310,8 @@

    Search - - GitHub + + GitHub @@ -617,7 +624,9 @@

    TableGateway LifeCycle Events

  • @@ -626,7 +635,9 @@

    TableGateway LifeCycle Events

    @@ -845,13 +856,13 @@
  • - +
  • - +
  • - +
  • @@ -867,7 +878,7 @@

    Code licensed under BSD 3-Clause. + href="https://github.com/laminas/laminas-db/blob/-/LICENSE.md">BSD 3-Clause.

    @@ -877,7 +888,7 @@

    - © 2021 Laminas Project a Series of LF Projects, LLC. + © 2024 Laminas Project a Series of LF Projects, LLC.