本主题是《云客Drupal源码分析之数据库系统及其使用》的补充,便于查询,所以独立成一个主题

讲解数据库系统如何操作Schema(创建修改数据库、数据表、字段;判断它们的存在性等等),以及模块如何通过一个结构化数组去创建自己用到的数据表

官方的Schema文档地址是:https://www.drupal.org/node/146843
官方API文档:https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Database%21database.api.php/group/schemaapi/8.2.x
此外在\core\lib\Drupal\Core\Database\database.api.php文件中也有详尽的注释。

数据表定义:

程序要去创建数据表,那么需要先得到一个关于数据表的定义,才能据此创建,在drupal中这个定义是一个嵌套数组,结构如下:

$schema = array('description' => 'The base table for nodes.','fields' => array('nid'       => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),'vid'       => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE,'default' => 0),'type'      => array('type' => 'varchar','length' => 32,'not null' => TRUE, 'default' => ''),'language'  => array('type' => 'varchar','length' => 12,'not null' => TRUE,'default' => ''),'title'     => array('type' => 'varchar','length' => 255,'not null' => TRUE, 'default' => ''),'uid'       => array('type' => 'int', 'not null' => TRUE, 'default' => 0),'status'    => array('type' => 'int', 'not null' => TRUE, 'default' => 1),'created'   => array('type' => 'int', 'not null' => TRUE, 'default' => 0),'changed'   => array('type' => 'int', 'not null' => TRUE, 'default' => 0),'comment'   => array('type' => 'int', 'not null' => TRUE, 'default' => 0),'promote'   => array('type' => 'int', 'not null' => TRUE, 'default' => 0),'moderate'  => array('type' => 'int', 'not null' => TRUE,'default' => 0),'sticky'    => array('type' => 'int', 'not null' => TRUE, 'default' => 0),'translate' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),),'indexes' => array('node_changed'        => array('changed'),'node_created'        => array('created'),'node_moderate'       => array('moderate'),'node_frontpage'      => array('promote', 'status', 'sticky', 'created'),'node_status_type'    => array('status', 'type', 'nid'),'node_title_type'     => array('title', array('type', 4)),'node_type'           => array(array('type', 4)),'uid'                 => array('uid'),'translate'           => array('translate'),),'unique keys' => array('vid' => array('vid'),),// For documentation purposes only; foreign keys are not created in the// database.'foreign keys' => array('node_revision' => array('table' => 'node_field_revision','columns' => array('vid' => 'vid'),),'node_author' => array('table' => 'users','columns' => array('uid' => 'uid'),),),'primary key' => array('nid'),
);

下面解释各个键的意思:

      'description': 一个非标记字符串,用来描述表的目的.引用到其他表时,其他表名用{}包裹,如"储存标题数据为表{node}."'fields': 一个关联数组('字段名' => 规格描述) 它描述了表的列,规格描述也是一个数组. 以下规格参数被定义:'description': 一个非标记字符串,用来描述字段的目的.引用到其他表时,其他表名用{}包裹,如"储存标题数据为表{node}."'type': 常用数据类型: 'char', 'varchar', 'text', 'blob', 'int', 'float', 'numeric', or 'serial'. 大多数类型映射到相应数据库引擎指定的类型.  'serial' 代表自增字段. 对于MySQL来说是 'INT auto_increment'. 特殊类型'varchar_ascii'可用来限制字段机器名为US ASCII字符集.'mysql_type', 'pgsql_type', 'sqlite_type'等等:如果你要的类型在上面没有,你可以为特殊数据库指定类型,这时可以省略上面的类型参数,但这样可能有风险,通常可以使用"text"来代替'serialize': 布尔值,指定字段是否应该存储序列化数据'size': 数据大小: 'tiny', 'small', 'medium', 'normal', 'big'. 这是一个可储存最大值的暗示,指导储存引擎使用何种类型(比如在 MySQL中有 TINYINT、INT 、 BIGINT). 缺省值是'normal'(在MySQL中是INT, VARCHAR, BLOB,). 对于各种数据类型而言,不是所有大小均可用,可能的组合见DatabaseSchema::getFieldTypeMap()'not null': 布尔值,true表示no NULL值.默认为false.'default': 字段的默认值,注意数据类型,在php中'', '0',  0 是不同的. 为'int'字段指定'0'将不工作(注意引号),因为'0'是字符串,不是整数0'length': 类型'char', 'varchar' or 'text' 字段的最大长度.对于其他字段类型将忽略此值'unsigned': 布尔值,指明'int', 'float' and 'numeric' 类型有无符号(正负).默认为FALSE.对于其他字段类型将忽略此值'precision', 'scale': 对于'numeric' 字段而言是必须的,precision指明精度(有效数字的总数),scale (小数位位数). 其他类型将忽略'binary': 布尔值,指明 MySQL应该强制 'char', 'varchar' or 'text' 字段类型使用大小写敏感的二进制校对. 对于默认就是大敏感的类型,它没有影响字段定义中除'type'以外的全部参数是可选的,但有些另外: 'numeric' 必须指定'precision' 和'scale', 'varchar' 必须指定'length''primary key': 构成主键的多个列数组,一个表中只能有一个主键,但一个主键可以包含多个列,称为联合主键。'unique keys': unique键的关联数组 ('keyname' => specification). specification是一个构成unique的列数组'foreign keys': 一个关联数组('my_relation' => specification). 每个定义是一个包含被引用表名及列映射的数组,列映射为('源列' => '引用列'),外键不在数据库中创建,drupal不强制这个'indexes': 索引的关联数组 ('indexname' => specification).

上面的定义有些额外的说明:
primary key:主键,一个表中只能有一个主键约束,你可以命名这个主键约束,并指定它包含有哪些列,比如一个学生表,可以指定主键约束包含班级和学号,那么在行中班级可以相同,学号也可以相同,但班级和学号不能同时相同,这就是联合主键的作用

unique keys:唯一性,对字段数据进行唯一性约束,可以同时指定多个字段,被指定的这些字段,它们各自的数据不可以重复,各行数据在这个字段必须是唯一的

foreign keys:外键,这指明本字段引用到其他表的某个字段,在本字段所储存的值必须是被引用到的那个字段储存的值之一,如果插入值时,不在被引用字段内容中,那么将产生错误,比如权限表要储存用户ID,那么这个字段就应该指定外键到用户表的id字段

indexes:索引,主要用于加速数据查询,提高性能,包含多个列的索引又叫复合索引或者多列索引,条件子句涉及到索引指定的列时,在数据库内部这些索引被用到,当表很大时能大大提高搜索速度,表较小则索引体现不出优势,复合索引指定列时,顺序不是随意的,关于这方面知识请看:http://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html

在上面的定义中:索引处有个定义是'node_type' => array(array('type', 4)),为什么不是'node_type' => array('type',),呢?这个参数4是什么意思?这是指在type这个字段中储存的数据只有前4字节被用于索引内容,加快速度,如果存储引擎不支持这样的功能,那参数4将被忽略,这样的用法同样适用于主键。

有了这样的表定义就可以创建表了,方法如下:

$con=\Drupal\Core\Database\Database::getConnection($target, $key);
$con->schema()->createTable($table_name, $schema);

$con->schema()返回的是一个schema对象,专门操作schema,里面提供了许多方法
源码在\core\lib\Drupal\Core\Database\Driver\中,它是\core\lib\Drupal\Core\Database\Schema.php的子类,

母类提供个数据库通用功能,子类用以解决数据库之间的不同(数据库方言)

Schema对象的常用方法如下:

$con = \Drupal\Core\Database\Database::getConnection($target, $key);
$schema = $con->schema();
$schema->createTable($table_name, $schema); //创建表
$schema->tableExists($table); //判断表是否存在
$schema->renameTable($table, $new_name);//重命名表
$schema->fieldExists($table, $column); //判断字段是否存在
$schema->fieldNames($fields);//从一个column specifiers返回字段名
$schema->changeField($table, $field, $field_new, $spec, $keys_new = array());//修改字段
$schema->addField($table, $field, $spec, $keys_new = array());//添加字段
$schema->dropField($table, $field);//删除字段
$schema->fieldSetDefault($table, $field, $default);//为字段设置默认值
$schema->fieldSetNoDefault($table, $field); //取消默认值
$schema->indexExists($table, $name); //判断是否存在索引
$schema->addIndex($table, $name, $fields, $spec = array());//添加索引
$schema->dropIndex($table, $name);//删除索引
$schema->addPrimaryKey($table, $fields); //给联合主键添加字段
$schema->dropPrimaryKey($table);//删除主键
$schema->addUniqueKey($table, $name, $fields);//添加唯一性约束
$schema->dropUniqueKey($table, $name);//销毁唯一性约束
$schema->prepareComment($comment, $length = null); //预处理注释
$schema->getComment($table, $column = null); //获取字段注释

这些方法的说明请看注释:\core\lib\Drupal\Core\Database\Schema.php

常用数据库Mysql数据库的类型映射如下:

$map = array('varchar_ascii:normal' => 'VARCHAR','varchar:normal' => 'VARCHAR','char:normal' => 'CHAR','text:tiny' => 'TINYTEXT','text:small' => 'TINYTEXT','text:medium' => 'MEDIUMTEXT','text:big' => 'LONGTEXT','text:normal' => 'TEXT','serial:tiny' => 'TINYINT','serial:small' => 'SMALLINT','serial:medium' => 'MEDIUMINT','serial:big' => 'BIGINT','serial:normal' => 'INT','int:tiny' => 'TINYINT','int:small' => 'SMALLINT','int:medium' => 'MEDIUMINT','int:big' => 'BIGINT','int:normal' => 'INT','float:tiny' => 'FLOAT','float:small' => 'FLOAT','float:medium' => 'FLOAT','float:big' => 'DOUBLE','float:normal' => 'FLOAT','numeric:normal' => 'DECIMAL','blob:big' => 'LONGBLOB','blob:normal' => 'BLOB',);

在模块安装的时候怎么创建数据表呢?

在模块文件夹下创建一个文件,命名为:module_name.install

module_name是模块名,把此文件当做php文件看待,在里面定义函数hook_schema().

其中hook应该替换为模块名,比如模块名叫yunke,该函数名应该为yunke_schema()。

在函数中返回一个关联数组,键名表示数据库表名,键值为数据表定义数组(见上),格式如下:

function yunke_schema() {$table['table_name1'] = $schema;$table['table_name2'] = $schema2;return $table;
}

table_name1和table_name2为要创建的表名,他们的值为上面定义的表定义数组

在模块安装的时候将搜索module_name.install文件,执行里面的hook_schema()函数
通过返回值自动建立这两个数据表,结构为定义数组控制,在模块卸载的时候自动销毁这两个表

模块升级可能会涉及到数据表的更新、变更等升级操作,
这应该是一个独立的主题(它包含表定义、配置、数据处理等等),此处不做介绍,在模块相关主题中讲解

我是云客,【云游天下,做客四方】,联系方式见主页,欢迎转载,但须注明出处

云客Drupal源码分析之数据库Schema及创建数据表相关推荐

  1. 云客Drupal源码分析之Session进阶

    在本系列之前写过<云客Drupal源码分析之Session系统>,但那部分仅仅讲到了drupal会话的基础:Symfony的Session组件 至于drupal怎么去使用这个基础就是本主题 ...

  2. 云客Drupal源码分析之前端js中的翻译

    从本主题开始<云客Drupal源码分析>系列将连续发布和前端js相关的内容,如果您对JavaScript还不熟悉或者需要来一次系统性的整理回顾,在此云客为您准备了以下资料: <PHP ...

  3. 云客Drupal源码分析之配置系统Configuration(一)

    各位<云客drupal源码分析>系列的读者: 本系列一直以每周一篇的速度进行博客原创更新,希望帮助大家理解drupal8底层原理,并缩短学习时间,但自<插件系统(上)>主题开始 ...

  4. 云客Drupal源码分析之节点实体访问控制处理器

    以下内容仅是一个预览,完整内容请见文尾: 本篇讲解节点实体的访问控制,总结了访问检查链,对"域"."授权id"进行了清晰论述(该知识点可能是中文资料第一次提及, ...

  5. 云客Drupal源码分析之类型化数据Typed Data API

    各位<云客drupal源码分析>系列的读者: 本系列一直以每周一篇的速度进行博客原创更新,希望帮助大家理解drupal底层原理,并缩短学习时间,但自<插件系统(上)>主题开始博 ...

  6. 云客Drupal源码分析之国际化Internationalization:核心翻译系统

    各位<云客drupal源码分析>系列的读者: 本系列一直以每周一篇的速度进行博客原创更新,希望帮助大家理解drupal底层原理,并缩短学习时间,但自<插件系统(上)>主题开始博 ...

  7. 云客Drupal源码分析之插件系统(上)

    各位<云客drupal源码分析>系列的读者: 本系列一直以每周一篇的速度进行博客原创更新,希望帮助大家理解drupal底层原理,并缩短学习时间,但自<插件系统(上)>主题开始博 ...

  8. 云客Drupal源码分析之前言

    Drupal是一个非常优秀的网站系统,可以说她是一个网站应用开发框架,也可以说是一个cms,她在世界范围内被广泛使用,最为人所知的是美国白宫.联合国等知名机构的官方网站使用了她,随着Drupal8的来 ...

  9. 云客Drupal源码分析之实体表单显示EntityFormDisplay

    以下内容仅是一个预览,完整内容请见文尾: 实体的显示分为表单显示和视图显示,前者用于不同情况下的信息输入,后者用于不同情况下的信息展示,本篇很多内容不止用于本篇所讲的表单主题,也是学习drupal视图 ...

最新文章

  1. LC77 Combinations
  2. OpenCV Harris 角点检测子
  3. SpringMVC之context-dispatcher.xml,了解基本的控制器
  4. WINCE驱动程序快速入门
  5. FreeBSD学习笔记15-FreeBSD下安装Apache
  6. adb logcat 通过包名过滤日志并输出到txt文件
  7. Visual Studio 2017 15.4 正式发布,那些你必须知道的新特性!
  8. JSTL Tutorial with Examples – JSTL Core Tags
  9. 数据库设计(有实例)
  10. 签到系统实验报告_实验报告评分标准
  11. 蓝牙耳机测试软件apk_蓝牙耳机电量显示app下载
  12. matlab人工鱼群捕食,Matlab从入门到精通(3)——多目标人工鱼群算法
  13. 学计算机应用必备的软件,电脑装机六大必备软件神器推荐
  14. linux如何复制代码不乱码,网上复制代码要小心,很可能会带入乱码字符
  15. 用户购物行为数据分析
  16. 启动计算机应用程序的命令,如何设置电脑Windows开机启动项命令?
  17. 为什么“家徒四壁”中的徒是仅仅,只有的意思?
  18. 力扣刷题 DAY_74 回溯
  19. 迅捷路由器造成计算机无法上网,迅捷无线路由器设置好却不能上网
  20. Spring是什么意思?

热门文章

  1. Rails的静态资源管理(三)—— 开发环境的Asset Pipelin
  2. 封神台SQL注入-延时注入
  3. 力回馈方向盘测试软件,真假如何辨?力反馈方向盘深度剖析
  4. 为什么Java需要序列化
  5. linux 解决安装Nvidia驱动后,或者声音选项里只有HDMI,声卡没有声音的方法[集锦]
  6. 六、python操作mysql篇(黑马程序猿-python学习记录)
  7. Jzoj P6305 最小值___单调栈优化dp
  8. TraceId 搭配 ELK ,碉堡了!
  9. 智能驾驶 车牌检测和识别(三)《CRNN和LPRNet实现车牌识别(含车牌识别数据集和训练代码)》
  10. 如何防止论文重复率高?