database.api.php

Same filename and directory in other branches
  1. 11.x core/lib/Drupal/Core/Database/database.api.php
  2. 10 core/lib/Drupal/Core/Database/database.api.php
  3. 9 core/lib/Drupal/Core/Database/database.api.php
  4. 8.9.x core/lib/Drupal/Core/Database/database.api.php

Hooks related to the Database system and the Schema API.

File

core/lib/Drupal/Core/Database/database.api.php

View source
<?php


/**
 * @file
 * Hooks related to the Database system and the Schema API.
 */

use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Database\SchemaDefinition\Column;
use Drupal\Core\Database\SchemaDefinition\ColumnSize;
use Drupal\Core\Database\SchemaDefinition\ForeignKey;
use Drupal\Core\Database\SchemaDefinition\Index;
use Drupal\Core\Database\SchemaDefinition\IntValue;
use Drupal\Core\Database\SchemaDefinition\PrimaryKey;
use Drupal\Core\Database\SchemaDefinition\Schema;
use Drupal\Core\Database\SchemaDefinition\SchemaDefinitionType;
use Drupal\Core\Database\SchemaDefinition\StringValue;
use Drupal\Core\Database\SchemaDefinition\Table;

/**
 * @defgroup database Database abstraction layer
 * @{
 * Allow the use of different database servers using the same code base.
 *
 * @section sec_intro Overview
 * Drupal's database abstraction layer provides a unified database query API
 * that can query different underlying databases. It is generally built upon
 * PHP's PDO (PHP Data Objects) database API, and inherits much of its syntax
 * and semantics. Besides providing a unified API for database queries, the
 * database abstraction layer also provides a structured way to construct
 * complex queries, and it protects the database by using good security
 * practices.
 *
 * Drupal provides 'database drivers', in the form of Drupal modules, for the
 * concrete implementation of its API towards a specific database engine.
 * MySql, PostgreSQL and SQLite are core implementations, built on PDO. Other
 * modules can provide implementations for additional database engines, like
 * MSSql or Oracle; or alternative low-level database connection clients like
 * mysqli or oci8.
 *
 * For more detailed information on the database abstraction layer, see
 * https://www.drupal.org/docs/drupal-apis/database-api/database-api-overview.
 *
 * @section sec_entity Querying entities
 * Any query on Drupal entities or fields should use the Entity Query API. See
 * the @link entity_api entity API topic @endlink for more information.
 *
 * @section sec_simple Simple SELECT database queries
 * For simple SELECT queries that do not involve entities, the Drupal database
 * abstraction layer provides the functions \Drupal::database()->query() and
 * \Drupal::database()->queryRange(), which execute SELECT queries (optionally
 * with range limits) and return result sets that you can iterate over using
 * foreach loops. (The result sets are objects implementing the
 * \Drupal\Core\Database\StatementInterface interface.)
 * You can use the simple query functions for query strings that are not
 * dynamic (except for placeholders, see below), and that you are certain will
 * work in any database engine. See @ref sec_dynamic below if you have a more
 * complex query, or a query whose syntax would be different in some databases.
 *
 * Note: \Drupal::database() is used here as a shorthand way to get a reference
 * to the database connection object. In most classes, you should use dependency
 * injection and inject the 'database' service to perform queries. See
 * @ref sec_connection below for details.
 *
 * To use the simple database query functions, you will need to make a couple of
 * modifications to your bare SQL query:
 * - Enclose your table name in {}. Drupal allows site builders to use
 *   database table name prefixes, so you cannot be sure what the actual
 *   name of the table will be. So, use the name that is in the hook_schema(),
 *   enclosed in {}, and Drupal will calculate the right name.
 * - Instead of putting values for conditions into the query, use placeholders.
 *   The placeholders are named and start with :, and they take the place of
 *   putting variables directly into the query, to protect against SQL
 *   injection attacks.
 * - LIMIT syntax differs between databases, so if you have a ranged query,
 *   use \Drupal::database()->queryRange() instead of
 *   \Drupal::database()->query().
 *
 * For example, if the query you want to run is:
 * @code
 * SELECT e.id, e.title, e.created FROM example e WHERE e.uid = $uid
 *   ORDER BY e.created DESC LIMIT 0, 10;
 * @endcode
 * you would do it like this:
 * @code
 * $result = \Drupal::database()->queryRange('SELECT e.id, e.title, e.created
 *   FROM {example} e
 *   WHERE e.uid = :uid
 *   ORDER BY e.created DESC',
 *   0, 10, [':uid' => $uid)];
 * foreach ($result as $record) {
 *   // Perform operations on $record->title, etc. here.
 * }
 * @endcode
 *
 * Note that if your query has a string condition, like:
 * @code
 * WHERE e.my_field = 'foo'
 * @endcode
 * when you convert it to placeholders, omit the quotes:
 * @code
 * WHERE e.my_field = :my_field
 * ... [':my_field' => 'foo'] ...
 * @endcode
 *
 * @section sec_dynamic Dynamic SELECT queries
 * For SELECT queries where the simple query API described in @ref sec_simple
 * will not work well, you need to use the dynamic query API. However, you
 * should still use the Entity Query API if your query involves entities or
 * fields (see the @link entity_api Entity API topic @endlink for more on
 * entity queries).
 *
 * Note: \Drupal::database() is used here as a shorthand way to get a reference
 * to the database connection object. In most classes, you should use dependency
 * injection and inject the 'database' service to perform queries. See
 * @ref sec_connection below for details.
 *
 * The dynamic query API lets you build up a query dynamically using method
 * calls. As an illustration, the query example from @ref sec_simple above
 * would be:
 * @code
 * $result = \Drupal::database()->select('example', 'e')
 *   ->fields('e', ['id', 'title', 'created'])
 *   ->condition('e.uid', $uid)
 *   ->orderBy('e.created', 'DESC')
 *   ->range(0, 10)
 *   ->execute();
 * @endcode
 *
 * There are also methods to join to other tables, add fields with aliases,
 * isNull() to query for NULL values, etc. See
 * https://www.drupal.org/docs/drupal-apis/database-api for many more details.
 *
 * One note on chaining: It is common in the dynamic database API to chain
 * method calls (as illustrated here), because most of the query methods modify
 * the query object and then return the modified query as their return
 * value. However, there are some important exceptions; these methods (and some
 * others) do not support chaining:
 * - join(), innerJoin(), etc.: These methods return the joined table alias.
 * - addField(): This method returns the field alias.
 * Check the documentation for the query method you are using to see if it
 * returns the query or something else, and only chain methods that return the
 * query.
 *
 * @section sec_insert INSERT, UPDATE, and DELETE queries
 * INSERT, UPDATE, and DELETE queries need special care in order to behave
 * consistently across databases; you should never use
 * \Drupal::database()->query() to run an INSERT, UPDATE, or DELETE query.
 * Instead, use functions \Drupal::database()->insert(),
 * \Drupal::database()->update(), and \Drupal::database()->delete() to obtain
 * a base query on your table, and then add dynamic conditions (as illustrated
 * in @ref sec_dynamic above).
 *
 * Note: \Drupal::database() is used here as a shorthand way to get a reference
 * to the database connection object. In most classes, you should use dependency
 * injection and inject the 'database' service to perform queries. See
 * @ref sec_connection below for details.
 *
 * For example, if your query is:
 * @code
 * INSERT INTO example (id, uid, path, name) VALUES (1, 2, 'path', 'Name');
 * @endcode
 * You can execute it via:
 * @code
 * $fields = ['id' => 1, 'uid' => 2, 'path' => 'path', 'name' => 'Name'];
 * \Drupal::database()->insert('example')
 *   ->fields($fields)
 *   ->execute();
 * @endcode
 *
 * @section sec_transaction Transactions
 * Drupal supports transactions. To start a new transaction, call
 * startTransaction(), like this:
 * @code
 * $transaction = \Drupal::database()->startTransaction();
 * @endcode
 * The transaction needs to be explicitly committed or rolled back once you
 * have completed the database operations requested. If your transaction is
 * nested inside of another then Drupal will track each transaction and only
 * commit the outer-most transaction when the last transaction object is
 * committed (when all relevant queries have completed successfully).
 *
 * Example:
 * @code
 * function my_transaction_function() {
 *   $connection = \Drupal::database();
 *
 *   try {
 *     // The transaction opens here.
 *     $transaction = $connection->startTransaction();
 *
 *     $id = $connection->insert('example')
 *       ->fields([
 *         'field1' => 'string',
 *         'field2' => 5,
 *       ])
 *       ->execute();
 *
 *     my_other_function($id);
 *
 *     // The transaction has completed, commit it here.
 *     $transaction->commitOrRelease();
 *
 *     return $id;
 *   }
 *   catch (Exception $e) {
 *     // Something went wrong somewhere. If the exception was thrown during
 *     // startTransaction(), then $transaction is NULL and there's nothing to
 *     // roll back. If the exception was thrown after a transaction was
 *     // successfully started, then it must be rolled back.
 *     if (isset($transaction)) {
 *       $transaction->rollBack();
 *     }
 *
 *     // Log the exception.
 *     Error::logException(\Drupal::logger('type'), $e);
 *   }
 *
 *   // $transaction goes out of scope here. Unless the transaction was rolled
 *   // back, it gets automatically committed here.
 * }
 *
 * function my_other_function($id) {
 *   $connection = \Drupal::database();
 *   // The transaction is still open here.
 *
 *   if ($id % 2 == 0) {
 *     $connection->update('example')
 *       ->condition('id', $id)
 *       ->fields(['field2' => 10])
 *       ->execute();
 *   }
 * }
 * @endcode
 *
 * @section sec_connection Database connection objects
 * The examples here all use functions like \Drupal::database()->select() and
 * \Drupal::database()->query(), which can be called from any Drupal method or
 * function code. In some classes, you may already have a database connection
 * object in a member variable, or it may be passed into a class constructor
 * via dependency injection. If that is the case, you can look at the code for
 * \Drupal::database()->select() and the other functions to see how to get a
 * query object from your connection variable. For example:
 * @code
 * $query = $connection->select('example', 'e');
 * @endcode
 * would be the equivalent of
 * @code
 * $query = \Drupal::database()->select('example', 'e');
 * @endcode
 * if you had a connection object variable $connection available to use. See
 * also the @link container Services and Dependency Injection topic. @endlink
 * In Object Oriented code:
 * - If possible, use dependency injection to use the "database" service.
 *   @code
 *   use Drupal\Core\Database\Connection;
 *
 *   class myClass {
 *
 *   public function __construct(protected Connection $database) {
 *     // ...
 *   }
 *   @endcode
 * - If it is not possible to use dependency injection, for example in a static
 *   method, use \Drupal::database().
 *   @code
 *   $connection = \Drupal::database();
 *   $query = $connection->query('...');
 *   @endcode
 * - If services are not yet available, use
 *   \Drupal\Core\Database\Database::getConnection() to get a database
 *   connection;
 *   @code
 *   use Drupal\Core\Database\Database;
 *
 *   // ...
 *
 *   $connection = Database::getConnection();
 *   $query = $connection->query('...');
 *   @endcode
 * - In unit tests, we do not have a booted kernel or a built container. Unit
 *   tests that need a database service should be converted to a kernel test.
 * - In kernel and functional test classes, use
 *   \Drupal\Core\Database\Database::getConnection() to get a database
 *   connection.
 *   @code
 *   use Drupal\Core\Database\Database;
 *
 *   // ...
 *
 *   $connection = Database::getConnection();
 *   $query = $connection->query('...');
 *   @endcode
 * In procedural code, such as *.module, *.inc or script files:
 * - Use \Drupal::database(); to get database connection.
 *   @code
 *   $connection = \Drupal::database();
 *   $query = $connection->query('...');
 *   @endcode
 *
 * @see https://www.drupal.org/docs/drupal-apis/database-api
 * @see entity_api
 * @see schemaapi
 *
 * @}
 */

/**
 * @defgroup schemaapi Schema API
 * @{
 * API to handle database schemas.
 *
 * A Drupal schema definition is an object representing one or more tables and
 * their related keys and indexes. A schema is defined by hook_schema(), which
 * usually lives in a modulename.install file, or dynamically in storage
 * handling classes.
 *
 * By implementing hook_schema() and specifying the tables your module
 * declares, you can easily create and drop these tables on all supported
 * database engines. A SchemaDefinition structure is immutable and database
 * abstract. This implies you do not have to deal with the different SQL
 * dialects for table creation and alteration of the supported database
 * engines.
 *
 * hook_schema() should return a Drupal\Core\Database\SchemaDefinition\Schema
 * object that holds public readonly properties for each table that the module
 * defines.
 *
 * For each Drupal\Core\Database\SchemaDefinition\Table object in the
 * definition, the following properties are defined:
 *   - 'name': A string identifying the table in Drupal.
 *   - 'description': A string in non-markup plain text describing this table
 *     and its purpose. References to other tables should be enclosed in curly
 *     brackets.
 *   - 'columns': An array of Drupal\Core\Database\SchemaDefinition\Column
 *     objects that describes the table's database columns. The following
 *     object properties are defined:
 *     - 'name': A string identifying the column in Drupal.
 *     - 'description': A string in non-markup plain text describing this column
 *       and its purpose. References to other tables should be enclosed in curly
 *       brackets. For example, the users_data table 'uid' column description
 *       might contain "The {users}.uid this record affects."
 *     - 'type': The column datatype, as a case of the
 *       Drupal\Core\Database\SchemaDefinition\ColumnType enumerator: ::Char,
 *       ::Varchar, ::Text, ::Blob, ::Int, ::Float, ::Numeric, ::Serial, etc.
 *       Most types just map to the according database engine specific data
 *       types. Use 'Column::serial' for auto incrementing columns. This will
 *       expand to 'INT auto_increment' on MySQL.
 *       A special ::VarcharAscii type is also available for limiting machine
 *       name column to US ASCII characters.
 *     - 'serialize': A boolean indicating whether the column will be stored as
 *       a serialized string.
 *     - 'size': The data size as a case of the
 *       Drupal\Core\Database\SchemaDefinition\ColumnSize enumerator: ::Tiny,
 *       ::Small, ::Medium, ::Normal, ::Big. This is a hint about the largest
 *       value the column will store and determines which of the database
 *       engine specific data types will be used (e.g. on MySQL, TINYINT vs.
 *       INT vs. BIGINT).
 *       ::Normal, the default, selects the base type (e.g. on MySQL, INT,
 *       VARCHAR, BLOB, etc.).
 *       Not all sizes are available for all data types.
 *     - 'notNull': If true, no NULL values will be allowed in this database
 *       column. Defaults to false.
 *     - 'default': The columns's default value, expressed as an object holding
 *       its type and the default value.
 *     - 'length': The maximal length of a type ::Char, ::Varchar or ::Text
 *       column. Ignored for other column types.
 *     - 'unsigned': A boolean indicating whether a type ::Int, ::Float and
 *       ::Numeric only is signed or unsigned. Defaults to FALSE. For ::Serial
 *       columns, it is forced to TRUE. Ignored for other column types.
 *     - 'precision', 'scale': For type ::Numeric columns, indicates the
 *       precision (total number of significant digits) and scale (decimal
 *       digits right of the decimal point). Both values are mandatory. Ignored
 *       for other column types.
 *     - 'binary': A boolean indicating that MySQL should force ::Char,
 *       ::Varchar or ::Text columns to use case-sensitive binary collation.
 *       This has no effect on other database types for which case sensitivity
 *       is already the default behavior.
 *     - 'generatedExpression': The expression of an object returned by
 *       Column::generated(). It holds the expression the database computes the
 *       column value from. A generated column cannot have a 'default' or a
 *       'not null' constraint, and cannot be part of the primary key.
 *     - 'generatedStorage': The storage strategy of a Column::generated(). It
 *       holds whether the generated value is stored on write or computed on
 *       read. Prefer stored over virtual for portability: PostgreSQL supports
 *       virtual columns only from version 18 and cannot index them.
 *     - 'dbSpecificExtra': If you need to use a column type not included in
 *       the officially supported list of types above, you can specify a type
 *       for each database backend. Specify this as an associative array having
 *       the database type ('mysql', 'sqlite', 'pgsql', 'oracle', etc.) as the
 *       key, and an array of extra information <string,mixed> as the value. If
 *       NULL, it is not specified.
 *       If you specify a database specific type, you can leave out the type
 *       parameter, but be advised that your schema will fail to load on
 *       backends that do not have a type specified. A possible solution can be
 *       to use the "text" type as a fallback.
 *     All parameters apart from 'type' are optional except that type
 *     'numeric' columns must specify 'precision' and 'scale', and type
 *     'varchar' must specify the 'length' parameter.
 *  - 'primary key': A Drupal\Core\Database\SchemaDefinition\PrimaryKey
 *    object that describes the table primary key with an array of one or more
 *    key column specifiers (see below).
 *  - 'unique keys': An array of Drupal\Core\Database\SchemaDefinition\UniqueKey
 *    objects that describes the table unique keys. Each specification has the
 *    key name and an array of one or more key column specifiers (see below)
 *    that form a unique key on the table.
 *  - 'foreign keys': An array of
 *    Drupal\Core\Database\SchemaDefinition\ForeignKey objects that describes
 *    the table foreign keys. Each object contains the name of the referenced
 *    table ('foreignTable'), and an array of column mappings
 *    ('foreignColumns'). Column mappings are defined by matching the 'columns'
 *    property with 'foreignColumns'. This property is for documentation
 *    purposes only; foreign keys are not created in the database, nor are they
 *    enforced by Drupal.
 *  - 'indexes': An array of Drupal\Core\Database\SchemaDefinition\Index objects
 *    that describes the table indexes. Each object is an array of one or more
 *    key column specifiers (see below) that form an index on the table.
 *
 * A key column specifier is either a string naming a column or an array of two
 * elements, column name and length, specifying a prefix of the named column.
 * Note that some DBMS drivers may opt to ignore the prefix length configuration
 * and still use the whole column value for the key. Code should therefore not
 * rely on this functionality.
 *
 * As an example, this is the schema definition for the 'users_data' table. It
 * shows five columns ('uid', 'module', 'name', 'value', and 'serialized'), the
 * primary key (on the 'uid', 'module', and 'name' columns), and two indexes
 * (the 'module' index on the 'module' column and the 'name' index on the 'name'
 * column).
 *
 * @code
 * function user_schema(): Schema {
 *   $tables[] = new Table(
 *     name: 'users_data',
 *     description: 'Stores module data as key/value pairs per user.',
 *     columns: [
 *       Column::int(
 *         name: 'uid',
 *         description: 'The {users}.uid this record affects.',
 *         unsigned: TRUE,
 *         notNull: TRUE,
 *         default: new IntValue(0),
 *       ),
 *       Column::varcharAscii(
 *         name: 'module',
 *         description: 'The name of the module declaring the variable.',
 *         length: DRUPAL_EXTENSION_NAME_MAX_LENGTH,
 *         notNull: TRUE,
 *         default: new StringValue(''),
 *       ),
 *       Column::varcharAscii(
 *         name: 'name',
 *         description: 'The identifier of the data.',
 *         length: 128,
 *         notNull: TRUE,
 *         default: new StringValue(''),
 *       ),
 *       Column::blob(
 *         name: 'value',
 *         description: 'The value.',
 *         size: ColumnSize::Big,
 *         notNull: FALSE,
 *       ),
 *       Column::int(
 *         name: 'serialized',
 *         description: 'Whether value is serialized.',
 *         size: ColumnSize::Tiny,
 *         unsigned: TRUE,
 *         default: new IntValue(0),
 *       ),
 *     ],
 *     primaryKey: new PrimaryKey(['uid', 'module', 'name']),
 *     indexes: [
 *       new Index(name: 'module', columns: ['module']),
 *       new Index(name: 'name', columns: ['name']),
 *     ],
 *     foreignKeys: [
 *       new ForeignKey(
 *         name: 'data_user',
 *         foreignTable: 'users',
 *         columns: ['uid'],
 *         foreignColumns: ['uid'],
 *       ),
 *     ],
 *   );
 *
 *   return new Schema(
 *     type: SchemaDefinitionType::Module,
 *     name: 'user',
 *     tables: $tables,
 *   );
 * }
 * @endcode
 *
 * @see \Drupal\Core\Extension\ModuleInstaller::installSchema()
 * @see \Drupal\Core\Extension\ModuleInstaller::uninstallSchema()
 * @see \Drupal\TestTools\Extension\SchemaInspector::getTablesSpecification()
 *
 * @}
 */

/**
 * @addtogroup hooks
 * @{
 */

/**
 * Perform alterations to a structured query.
 *
 * Structured (aka dynamic) queries that have tags associated may be altered by
 * any module before the query is executed.
 *
 * @param \Drupal\Core\Database\Query\AlterableInterface $query
 *   A Query object describing the composite parts of a SQL query.
 *
 * @see hook_query_TAG_alter()
 * @see node_query_node_access_alter()
 * @see AlterableInterface
 * @see SelectInterface
 *
 * @ingroup database
 */
function hook_query_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
  if ($query->hasTag('micro_limit')) {
    $query->range(0, 2);
  }
}

/**
 * Perform alterations to a structured query for a given tag.
 *
 * Some common tags include:
 * - 'entity_reference': For queries that return entities that may be referenced
 *   by an entity reference field.
 * - ENTITY_TYPE . '_access': For queries of entities that will be displayed in
 *   a listing (e.g., from Views) and therefore require access control.
 *
 * @param \Drupal\Core\Database\Query\AlterableInterface $query
 *   A Query object describing the composite parts of a SQL query.
 *
 * @see hook_query_alter()
 * @see node_query_node_access_alter()
 * @see AlterableInterface
 * @see SelectInterface
 *
 * @ingroup database
 */
function hook_query_TAG_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
  // This is an example of a possible hook_query_media_access_alter()
  // implementation. In other words, alter queries of media entities that
  // require access control (have the 'media_access' query tag).
  // Determine which media entities we want to remove from the query. In this
  // example, we hard-code some media IDs.
  $media_entities_to_hide = [
    1,
    3,
  ];
  // In this example, we're only interested in applying our media access
  // restrictions to SELECT queries. hook_media_access() can be used to apply
  // access control to 'update' and 'delete' operations.
  if (!$query instanceof SelectInterface) {
    return;
  }
  // The tables in the query. This can include media entity tables and other
  // tables. Tables might be joined more than once, with aliases.
  $query_tables = $query->getTables();
  // The tables belonging to media entity storage.
  $table_mapping = \Drupal::entityTypeManager()->getStorage('media')
    ->getTableMapping();
  $media_tables = $table_mapping->getTableNames();
  // For each table in the query, if it's a media entity storage table, add a
  // condition to filter out records belonging to a media entity that we wish
  // to hide.
  foreach ($query_tables as $alias => $info) {
    // Skip over subqueries.
    if ($info['table'] instanceof SelectInterface) {
      continue;
    }
    $real_table_name = $info['table'];
    if (in_array($real_table_name, $media_tables)) {
      $query->condition("{$alias}.mid", $media_entities_to_hide, 'NOT IN');
    }
  }
}

/**
 * Define the current version of the database schema.
 *
 * Only procedural implementations are supported for this hook.
 *
 * A Drupal schema definition is a structure of value objects representing one
 * or more tables and their related keys and indexes. A schema is defined by
 * hook_schema() which must live in your module's .install file.
 *
 * The tables declared by this hook will be automatically created when the
 * module is installed, and removed when the module is uninstalled. This happens
 * before hook_install() is invoked, and after hook_uninstall() is invoked,
 * respectively.
 *
 * By declaring the tables used by your module via an implementation of
 * hook_schema(), these tables will be available on all supported database
 * engines. You don't have to deal with the different SQL dialects for table
 * creation and alteration of the supported database engines.
 *
 * See the Schema API documentation for details on schema definition
 * structures. Note that foreign key definitions are for documentation purposes
 * only; foreign keys are not created in the database, nor are they enforced by
 * Drupal.
 *
 * @return \Drupal\Core\Database\SchemaDefinition\Schema
 *   A schema definition.
 *
 * @ingroup schemaapi
 */
function hook_schema() : Schema {
  $tables[] = new Table(name: 'users_data', description: 'Stores module data as key/value pairs per user.', columns: [
    Column::int(name: 'uid', description: 'The {users}.uid this record affects.', unsigned: TRUE, notNull: TRUE, default: new IntValue(0)),
    Column::varcharAscii(name: 'module', description: 'The name of the module declaring the variable.', length: DRUPAL_EXTENSION_NAME_MAX_LENGTH, notNull: TRUE, default: new StringValue('')),
    Column::varcharAscii(name: 'name', description: 'The identifier of the data.', length: 128, notNull: TRUE, default: new StringValue('')),
    Column::blob(name: 'value', description: 'The value.', size: ColumnSize::Big, notNull: FALSE),
    Column::int(name: 'serialized', description: 'Whether value is serialized.', size: ColumnSize::Tiny, unsigned: TRUE, default: new IntValue(0)),
  ], primaryKey: new PrimaryKey([
    'uid',
    'module',
    'name',
  ]), indexes: [
    new Index(name: 'module', columns: [
      'module',
    ]),
    new Index(name: 'name', columns: [
      'name',
    ]),
  ], foreignKeys: [
    new ForeignKey(name: 'data_user', foreignTable: 'users', columns: [
      'uid',
    ], foreignColumns: [
      'uid',
    ]),
  ]);
  return new Schema(type: SchemaDefinitionType::Module, name: 'hook', tables: $tables);
}

/**
 * @} End of "addtogroup hooks".
 */

Functions

Title Deprecated Summary
hook_query_alter Perform alterations to a structured query.
hook_query_TAG_alter Perform alterations to a structured query for a given tag.
hook_schema Define the current version of the database schema.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.