ZenCart函数-functions_categories.php

共计有21个函数 已经列出了12个

zen_has_category_subcategories($category_id)

根据分类ID—-检查该分类是否有子分类,实现过程是统计 parent_id=$category_id的数量,如果数量大于1,表示有子分类,返回bool类型

zen_get_categories_parent_name($categories_id)

根据分类ID—-获取父分类的名字 categories_name

zen_get_parent_categories($categories, 37)

根据分类的ID—-向上查找父分类的ID,比如子分类:37 cPath=33_35_37,那么$categories最终是一个数组,[35,37],如果没有父分类就返回true,表示该分类是一个顶级分类。自身迭代函数,一直向上查找,直到parent_id为0为止,里面有个非常重要的判断 如果查找出来的当前分类的ID 不等于当前分类的ID 继续调用自身 直到查询到顶级分类。

zen_get_subcategories(&$subcategories_array, $parent_id = 0)

同理获取子分类的ID,并不是仅仅获取一级子分类,包括子分类的子分类,都一次性获取

比如:zen_get_subcategories($categories_sub,33);得到的结果是下面 有11个子分类

zen_get_product_path($products_id)

根据产品ID—-获得产品的cPath,比如产品ID:90,调用函数得到,获取48_45

实现过程:先根据产品的ID,查找出master_categories_id—》继续查找master_categories_id所有的父分类,得到数组后反转数组,最后拼接上当前分类的ID 返回48_45。

zen_get_path($current_category_id = ”)【还要继续研究】

zen_get_path函数中有个非常关键的 $cPath_array 暂时还不知道它的用法

zen_count_products_in_category($category_id, $include_inactive = false)

统计分类下的产品,产品ID,$include_inactive表示是否包含隐藏产品,如果产品隐藏了,我们统计的时候是否选择呢?

此函数默认会统计该分类下的所有子分类的产品,会累加在一起

zen_get_generated_category_path_rev(39)

用来生成当前分类的路径,包含当前分类“33_35_39”,函数实现过程是:根据参数查找到所有的父分类,然后反转函数,用连字符连接起来,最后拼接上当前分类ID,最后返回

zen_parse_category_path(’33_35_39′)

解析cPath变量并去掉重复的分类ID 比如 33_35_39,返回一个int类型数组。

以上学习了9个函数了

zen_get_product_types_to_category($lookup)

根据分类的ID,查找分类类型的ID,在TABLE_PRODUCT_TYPES_TO_CATEGORY表的product_type_id字段,一个产品分类可以有多个产品类别。

zen_get_categories_products_list(15)

zen_get_categories_products_list($categories_id, $include_deactivated = false, $include_child = true, $parent_category = ‘0’, $display_limit = ”)

获得一个分类下面所有的产品的ID【包括它的子分类】 得到一个数组 数组结构是 产品–分类ID

$include_deactivated:表示是否包含隐藏的产品

$include_child:是否包含子分类

$parent_category

$display_limit:表示限制条件

zen_product_in_category(1, 4)

检查分类ID和产品ID是否有对应的关系,在表TABLE_PRODUCTS_TO_CATEGORIES中,根据$product_id–检索categories_id,如果检索出来的categories_id和我们传入的分类ID相同,表示存在对应关系。如果不存在就继续检查父分类ID。

zen_product_in_parent_category($product_id, $cat_id, $parent_cat_id)
此函数就是继续检查父分类ID函数

ZenCart函数-functions_general.php

关于获取参数的两个函数

zen_get_all_get_params($exclude_array = array())

返回所有的http get变量 除了哪些 什么之外
$exclude_array:定义需要排除的参数

zen_post_all_get_params($exclude_array = array(), $hidden = true)

关于域名

解析一个URL
实现如下
先判断URL ://是否包含,然后解析URL中的host 值
可能是如下值
localhost
www.abc.com
abc.com
zen.abc.com
以小数点分割这个函数
abc.com

系统常量 定义
SESSION_USE_FQDN

关于产品ID解析

zen_get_prid($uprid)

从购物车的ID中解析出商品ID。

var_dump(zen_get_prid('11:abcdef12345'));echo '<hr />';//int(11) 

zen_get_uprid($prid, $params)

关于基础函数

zen_string_to_int($string)

字符串转int类型

zen_not_null($value)

检查值不为空,null,“NULL”,”” ,空数组,查询结果空。主要用来检查这五个值

1.如果是数组,要求数组元素大于0
2.如果是is_a($value, ‘queryFactoryResult’) 要求查询结果大于0【$value->result】
3.最后不为 空 不为NULL  并且字符长度大于0
true 表示 值是一个有效值

【如果值不为null,则返回true】

zen_rand($min = null, $max = null)

var_dump(zen_rand());echo '<hr />';
        var_dump(zen_rand(1,9999));echo '<hr />';

返回一个随机值,可以指定范围,也可以不指定

zen_get_ip_address()

获得IP地址

zen_round($value, $precision)

round()的包装函数。四舍五入返回一个指定位数的小于,但是不包括“.00”这样的格式

var_dump(zen_round(3.14159364,3));echo '<hr />';//double(3.142)
        var_dump(zen_round(3.14159364,2));echo '<hr />';//double(3.14)
        var_dump(zen_round(100.00,2));echo '<hr />';//double(100)

zen_exit()

Stop from parsing any further PHP code 停止解析任何进一步的PHP代码

zen_is_leap_year($year)

检查年份是否为闰年,如果是 返回true

zen_clean_html($clean_it, $extraTags = ”)

remove common HTML from text for display as paragraph

从文本中删除公共HTML以显示为段落

关于zen_db
zen_db和数据库查询,参数组装相关的函数

zen_db_input($string)

别名到$db->prepareInput(),用于清理数据库插入

zen_db_prepare_input($string)

zen_db_perform($table, $data, $action = ‘insert’, $parameters = ”)

zen_db_output($string)

关于基本业务

zen_get_country_zones($country_id)

根据国家ID获得国家区域zones,返回一个数组$zones_array[] = array(‘id’ =>$zone[‘zone_id’], ‘text’ => $zone[‘zone_name’]); 

ZenCart函数-常用的函数

zen_get_module_directory

函数说明:获得模块的目录。实现了includes/modules/*.php模块的重写。

此函数只是返回模块的名字

        var_dump(zen_get_module_directory('downloads'));echo '<hr />';//"CUSTOM/downloads.php"
        var_dump(zen_get_module_directory('downloads',true));echo '<hr />';//"CUSTOM/"

调用示例

<?php require(DIR_WS_MODULES . zen_get_module_directory('column_left.php')); ?>

此函数的一个兄弟函数是

zen_get_file_directory($check_directory, $check_file, $dir_only = ‘false’)

这个函数的功能应该更加的强大

$lang_file = zen_get_file_directory(DIR_FS_CATALOG . DIR_WS_LANGUAGES . $_SESSION['language'] . '/modules/order_total/', $value, 'false');

$lang_file = zen_get_file_directory(DIR_WS_LANGUAGES . $_SESSION['language'] . '/modules/order_total/', $value, 'false');

var_dump(zen_get_file_directory(DIR_WS_MODULES, 'attributes.php', $dir_only = 'false'));echo '<hr />';//"includes/modules/attributes.php"

从调用上看 函数可以检查相对目录,绝对目录

zen_href_link

函数说明:构造一个链接。function zen_href_link($page = ”, $parameters = ”, $connection = ‘NONSSL’, $add_session_id = true, $search_engine_safe = true, $static = false, $use_dir_ws_catalog = true)

25个sideboxes中特殊的search_header.php

所在目录 E:\wamp64\www\ZenCart156cDev\includes\modules\sideboxes

search_header.php 并不是一个真正的 sideboxes,它提供了一种思路,如何解决全局调用sideboxes的问题?

search_header.php调用示例如下

<?php require(DIR_WS_MODULES . 'sideboxes/search_header.php'); ?>

其余的sideboxes都是被模块column_left.php调用的

这样做的好处和坏处是?没有column_left.php提供的重写机制了

常用链接

<?php echo zen_href_link(FILENAME_LOGOFF, '', 'SSL'); ?>"><?php echo zen_href_link(FILENAME_ACCOUNT, '', 'SSL'); ?>">
<?php echo zen_href_link(FILENAME_LOGIN, '', 'SSL'); ?>

<?php echo zen_href_link(FILENAME_SHOPPING_CART, '', 'NONSSL'); ?>">

<?php echo zen_href_link(FILENAME_CHECKOUT_SHIPPING, '', 'SSL'); ?>">

表单函数
zen_draw_form
函数说明:构造一个表单。function zen_draw_form($name, $action, $method = ‘post’, $parameters = ”)

PHP新函数学习
basename
函数说明:返回路径中的文件名部分

需求和疑问
语言文件的载入
主语言文件的载入
让远程图片和本机图片同时兼容

ZenCart类库-payment.php解读实现原理

本篇解读 includes/classes/payment.php

关于具体实现模块的翻译

__construct

Constructor–构造器

函数–update_status()


Calculate zone matches and flag settings to determine whether this module should display to customers or not

计算区域匹配并标记设置以确定此模块是否应显示给客户

函数–javascript_validation()


JS validation which does error-checking of data-entry if this module is selected for use (Number, Owner Lengths)

JS验证,如果选择使用此模块,则将对数据输入进行错误检查(数字,所有者长度)

函数–selection()


Display Credit Card Information Submission Fields on the Checkout Payment Page

在结帐付款页面Checkout Payment Page 上显示信用卡信息提交字段

函数–pre_confirmation_check()


Evaluates the Credit Card Type for acceptance and the validity of the Credit Card Number & Expiration Date

评估可接受的信用卡类型 以及信用卡号 和有效期的有效性 

函数–confirmation()


Display Credit Card Information on the Checkout Confirmation Page

在结帐确认页面上显示信用卡信息

此函数和提交逻辑 好像没有关系

函数–process_button()


Build the data and actions to process when the “Submit” button is pressed on the order-confirmation screen.
This sends the data to the payment gateway for processing.
(These are hidden fields on the checkout confirmation page)

建立在订单确认屏幕上按下“提交”按钮时要处理的数据和操作。
这会将数据发送到支付网关进行处理。
(这些是结帐确认页面上的隐藏字段)

函数before_process()


Store the CC info to the order and process any results that come back from the payment gateway

将抄送信息存储到订单中,并处理从付款网关返回的所有结果

after_process()

Post-processing activities

Post-process activities. Updates the order-status history data with the auth code from the transaction.

Add receipt and transaction id to order-status-history (order comments)

后处理活动

后处理活动。 使用交易中的验证码更新订单状态历史记录数据。

check()

Check to see whether module is installed

检查是否安装了模块

install()

Install the payment module and its configuration settings

安装支付模块及其配置设置

remove() 

删除模块及其所有设置

keys()

Internal list of configuration keys used for configuration of the module

用于配置模块的配置密钥的内部列表

ZenCart类库-order_total.php解读原理

解读order_total.php文件

File contains the order-totals-processing class (“order-total”)
文件包含订单总数处理类(“订单总数”)

order-total class
Handles all order-total processing functions
处理所有订单总计处理功能

output($return_html=false)
函数处理输出最终的结果

credit_selection()

ZenCart类库-shipping.php解读实现原理

本篇文章解读 includes/classes/shipping.php shipping类的实现
关于 MODULE_SHIPPING_INSTALLED
表示系统中已经安装的模块,在后台配置中描述如下

Installed Modules
List of shipping module filenames separated by a semi-colon. This is automatically updated. No need to edit. (Example: ups.php;flat.php;item.php)

请进行必要的更改

已安装的模块
装运模块文件名列表,以分号分隔。
这会自动更新。 无需编辑。 (例如:ups.php; flat.php; item.php)
————————————————

关于构造函数的作用

1.加载你安装的模块

加载原理就是上面 MODULE_SHIPPING_INSTALLED,这个数据库配置,此配置在隐藏配置组id=6里面,后台其实没有显示,但是可以通过http://localhost/ZenCart156cDev/sprAy-Dsk-birtH/configuration.php?gID=6 访问这个配置组

另外此字段的配置是在 includes/init_includes/init_db_config_read.php 初始化时加载到系统中的。

分割此字段的值,得到数组

循环数组--得到类名和文件的名字

然后在DIR_WS_MODULES . 'shipping/'目录下加载

先加载模块对应的语言文件,然后加载模块本身

最后注册到 $GLOBALS变量中去,类名字作为索引,类实例作为值
————————————————

2.加载模块对应的语言

3.根据模块属性,确定模块是否开启or关闭

检查的原理是使用 check_enabled 函数,该函数的参数类型--使用类实例作为 输入参数。其内部使用method_exists方法检查类实例对象是否有指定的方法,然后调用类实例的方法 check_enabled_for_zone 或者check_enabled。

至此shipping其实已经实现了,类似的.net反射的特性,也是实现插件机制的原理。

通过shipping可以调用某一个具体实现类,比如flat类中的函数,实现了易于扩展的特性。

按照以下的优先次序返回插件是否启用

第一:默认$enabled = $class->enabled;默认的,其实就是flat类构造函数执行时初始化的属性,其内部调用了zen_get_shipping_enabled函数,并对区域做了检查

第二:$enabled = $class->check_enabled_for_zone();

第三:$enabled = $class->check_enabled();
————————————————

4.实例化模块,构造实例对象,并注册到全局变量【这是最终的目的】

$modules

构造函数中定义了此属性

这个属性只是单纯的安装模块“MODULE_SHIPPING_INSTALLED”分割之后的结果,除此之外再无其他

MODULE_SHIPPING_INSTALLED

在初始化过程中,只是读取了配置组2和3的配置,MODULE_SHIPPING_INSTALLED在配置组6里面,那么它是如何读取的呢?

此问题已经解答了,从上面看

关于flat类–模块的属性

code--模块的标识代码,通常就是类名字,和类文件同名,同时在$GLOBALS变量中引用它

title--模块标题,在语言文件中定义

description--模块本身描述,在语言文件中定义

sort_order--排序,排序字段是否定义决定了模块是否启用,也是非常重要的

icon---图标

tax_class--使用的税种

tax_basis--税种基于什么计算 一下是说明

On what basis is Shipping Tax calculated. Options are
Shipping - Based on customers Shipping Address
Billing Based on customers Billing address
Store - Based on Store address if Billing/Shipping Zone equals Store zone

enabled--该模块是否被启用

_check--属性用来读取插件的MODULE_SHIPPING_FLAT_STATUS 状态值
————————————————

关于zen_get_shipping_enabled的作用

disable only when entire cart is free shipping
仅当整个购物车免费送货时禁用

此函数内部注释先列出来

for admin always true if installed
对于管理员,如果已安装,则始终为true


Free Shipping when 0 weight - enable freeshipper - ORDER_WEIGHT_ZERO_STATUS must be on
0重量时免费送货-启用freeshipper-订单重量必须为0状态


Free Shipping when 0 weight - disable everyone - ORDER_WEIGHT_ZERO_STATUS must be on
0重量时免费送货-禁用所有人-订单重量必须为0


Always free shipping only true - enable freeshipper
始终免费送货-启用freeshipper


Always free shipping only true - disable everyone
始终免费送货-禁用所有人


Always free shipping only is false - disable freeshipper
总是免费送货是错误的-禁用免费送货
————————————————

同时牵连出一下函数

$_SESSION[‘cart’]->in_cart_check(‘product_is_always_free_shipping’,’1′);

检查指定字段的产品数

$_SESSION[‘cart’]->count_contents();

统计购物item总数

$_SESSION[‘cart’]->show_weight();

统计购物车总重量
————————————————

关于quote方法

返回对方法的引用,此方法可以返回所有模块的引用,也可以单独返回某一个模块的引用

内部实现机制是:

首先引用$shipping_weight, $uninsurable_value;$uninsurable_value表示的是运费险,看某一具体的类是否有get_uninsurable_value方法

定义$quotes_array,这是我们最终要返回的数组对象,这个数组对象是只包含已经启用的模块

通过两个循环,从$this->modules属性中分析你要的模块

第一个foreach循环实现了从$GLOBALS检查,判断模块的启用状态,只将满足启用状态的模块存入到$quotes_array

第二个循环,更新状态;调用某一具体shipping的quote方法,重新赋值计算重量的全局变量
————————————————

接下来一个问题是:flat的运费是如何被计算出来的呢?
$shipping_weight是在何时定义的?
会话$_SESSION[‘shipping’]是在什么地方被写入的?
shipping模块在实例化的时候,就已经确定并检查好哪些模块是可以使用的

关于设想的需求环境
所有订单免邮费

所有订单固定一个邮费

所有订单固定一个邮费,但是对某一个区域单独启用

订单满多少金额,就免邮费

订单金额设置区间范围,在不用的范围内,运费不一样

订单安装数量免邮费

关于flat类
这是一个提供统一费率的运输模块,所有的订单运费都是一样的,但是还可以设置在某个地区开启

关于flat类quote方法

quote中文意思是引用,此方法就是返回对此类的相关信息的引用

存储在quotes数组内,结构如下

id--模块的唯一标识符,全局内不要重复

module--模块的标题,被定义在语言包内

methods--这是一个数组,其中包含了关于运费的计算

tax--税率

icon--运费图标

结合分析 flat.php模块和freeshipper.php模块,两者编写方式高度相同

flat.php—-表示所有的订单采用统一的运费,税率

freeshipper.php—-表示免邮费

flat配置模块的区域是在什么地方设置的?暂时未知

zen_cfg_pull_down_zone_classes

ZenCart-数据库处理思路

处理数据库的思路是这样
1.原始数据库是我不做任何的更改
2.我对数据库的修改,使用单独的脚本,即使修改也是在单独的脚本中运行
3.我对原始脚本的操作大概有一下几种

  • 做新站的时候需要清空数据库的数据
  • 增加新表,比如products_images
  • 修改原始表的某些字段,比如字段长度等等
  • 插入某些配置,只是插入
  • 更新某些配置,比如隐藏模块,主要更加具体的生成环境来说
  • 数据新增,比如:货币数据,语言数据,国家数据等等,包括但是不限于

以上是我总结的6种操作 

SQL Server-数据库三范式和数据建模

数据库三范式

第一范式:
任何给定行的列必须是只包含一个值;
表中的每一行必须有相同数量的列;
表中的每一行必须是唯一的即是不相同的;
第二范式:
必须满足第一范式;
表中的所有非主键必须依赖整个主键;
第三范式:
必须满足第二范式;
表中的所有非主键必须相互独立;

数据建模

1 工具:Sysbase PowerDesigner ,  Borland Together , Rose, MS Visio
2 概念模型:概念数据模型也称信息模型,它以实体-联系(Entity-RelationShip,简称E-R)理论为基础,并对这一理论进行了扩充。它从用户的观点出发对信息进行建模
3 物理模型:数据库物理结构模型
4 正向工程:从物理模型产生一个数据库, 或产生数据库脚本,这是正向工程
5 逆向工程:从数据库映射为物理模型

SQL Server-常用语法

1 创建数据库

  create database AA
  on
  (
    name='aa_data',filename='C:\aa.mdf',size=10,filegrowth=5
  )
  log on
  (
    name='aa_log', filename='c:\aa.ldf', size=10, filegrowth=5
  )

2 备份还原数据库

backup database AA to disk =’E:\aa.dat’

还原数据库
restore database AA from disk =’E:\aa.dat’

3 创建表: create table BB ( … )

创建临时表:#是本地临时表,##是全局临时表
复制表:select * into table1 from table2

约束:  主键 primary key
        自增 identity
        不能为空字段 not null
        默认值 default(1)
        外键 id2 int,  foreign key (id2) references table1
        唯一值 unique
        检查 id int check(id>100 and id<200)

4 添加修改删除

insert into 表(字段1,…) values(值1, …)
修改:update 表 set 字段1 = 值1 , 字段2 = 值2 where 主键字段 = 值
删除:delete from 表 where 主键字段 = 值

5 查询
    排序 order by desc
        模糊 like ‘%a%’
        联合 union
        分组统计 group by 
    包含 in / not in / exits / not exits
 
        内连接: 列出与连接条件匹配的数据行
        select * from 表1 inner join 表2 on 条件

    外连接: 查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行
        select * from 表1 left outer join 表2 on 条件
       
交叉连接: 交叉连接不带WHERE 子句,它返回被连接的两个表所有数据行的笛卡尔积
        select a1, a2 from 表1 CROSS JOIN 表2 ORDER BY a1
       
嵌套查询: select * from talbe1 where id = (select …. )

6 流程控制
        赋值语句:declare @i int    set @i=0
      条件语句:if 条件为真
           begin … end
                  else
          begin … end   
    循环语句:while 条件为真
                  begin  … end

7 视图
创建单表视图
create view 视图名
as
select * from employees

8 存储过程
    create proc 存储过程名
     @i int,       –输入参数
     @j int output –输出参数
        as
    begin
            …
            return
    end

9 函数
    字符串:
        字符串长度 len(‘…’)
        获取字符串 str(‘…’) ,返回的是char
        截取字符串 substring(开始位置,长度)
        随机数 Rand()
 
    时间:
        添加时间间隔 dateadd(day, 2, getdate())
        时间差 datediff(day, 时间1, 时间2)
                获取年,月,日 datepart(yy,getdate())
 
    类型转换:
        convert(nvarchar(10), 123), cast(124 as nvarchar(10))
 
    自定函数:
        create function 函数名称(@i int, @j int) returns int
            as
            begin
                   …
                   return
                end

10 游标
    declare 游标名称 cursor for select * from 表
    open 游标名称
        — declare @i int
    fetch 游标名称   –或 fetch from 游标 into @i
    while @@fetch_status = 0
    begin
     fetch next from 游标名称
    end
    close 游标名称
    deallocate 游标名称

11 触发器
create trigger 触发器名 on 表名 for insert –或delete
as
begin
–select * from inserted
insert into 相关表
end

12 事务
事务是指一个单元的工作,这些工作要么全做,要么全部不做。作为一个逻辑单元,必须具备四个属性:自动性、一致性、独立性和持久性

begin tran
if @@error>0
rollback tran
commit tran

13 锁
为什么要引入锁
  当多个用户同时对数据库的并发操作时会带来以下数据不一致的问题:
  ◆丢失更新
  A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统
  ◆脏读
  A用户修改了数据,随后B用户又读出该数据,但A用户因为某些原因取消了对数据的修改,数据恢复原值,此时B得到的数据就与数据库内的数据产生了不一致
  ◆不可重复读
  A用户读取数据,随后B用户读出该数据并修改,此时A用户再读取数据时发现前后两次的值不一致
  并发控制的主要方法是封锁,锁就是在一段时间内禁止用户做某些操作以避免产生数据不一致
 
从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁
  共享(S)用于不更改或不更新数据的操作(只读操作),如SELECT语句。
  排它(X)用于数据修改操作,例如INSERT、UPDATE或DELETE。确保不会同时同一资源进行多重更新。
    更新(U)用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。
 
    HOLDLOCK持有共享锁,直到整个事务完成,应该在被锁对象不需要时立即释放,SERIALIZABLE事务隔离级别
  NOLOCK语句执行时不发出共享锁,允许脏读,READUNCOMMITTED事务隔离级别
    UPDLOCK强制在读表时使用更新锁而不用共享锁

SQL Server-数据库中多对多的关系设计

数据库中多对多的关系设计
数据库设计多对多关系的几种形态 
前言:多对多关系至少需要3个表,我们把一个表叫做主表,一个叫做关系表,另外一个叫做字典表或者副表(字典表是纪录比较少,而且基本稳定的,例如:版块名称;副表是内容比较多,内容变化的,例如)。 
按照数据库的增删查改操作,多对多关系的查找都可以用inner join或者select * from 主表 where id in (select 主表id from 关系表) 
1,角色任命型
 
特点:关系表两外键组合无重复纪录,关系表一般不需要时间字段和主键,有一个表是字典类型的表。 
界面特点:显示主表,用checkbox或多选select设置多选关系。 
例如:任命版主(用户表-关系表-版块名称表),角色权限控制等,用户是5个版块版主,只要关系表5行纪录就可以确立,关系表的两个外键具有联合主键性质。 
增加关系:如果没有组合纪录,insert之。 
删除关系:如果有组合纪录,删除之。 
2,集合分组型
 
特点:同角色任命型类似,关系表两外键组合无重复纪录,关系表一般不需要时间字段和主键。区别是主副表都不是字典表,可能都很大不固定。 
界面特点:显示主表,用搜索代替简单的checkbox或多选select,或者一条一条的添加。 
例如:歌曲专集(专集表-关系表-歌曲表)。手机分组(分组表-关系表-手机表)。用户圈子(圈子表-关系表-用户表)。文章标签(文章表-关系表-标签表) 
增加关系:同版主任命型。 
删除关系:同版主任命型。 
3,明细帐型
 
特点:关系表可以有重复纪录,关系表一般有时间字段,有主键,可能还有文字型的字段用来说明每次发生关系的原因(消费)。 
界面特点:显示关系表,用radio或下拉设置单选关系。 
例如:现金消费明细帐或订单(用户表-订单表-消费原因表),用户可能多次在同一事情上重复消费。积分变化纪录也属于这类。 
增加关系:不管有没有组合纪录,insert之,纪录时间。 
删除关系:根据关系表PK删除。 
4,评论回复型
 
特点:同明细帐型关系表一般有时间字段,有主键,区别是重点在文字型的字段用来说明每次发生关系的内容(评论回复)。 
界面特点:回复文本框。 
例如:论坛回复(用户表-回复表-帖子表),用户可能多次在不同帖子上评论回复费。 
增加关系:不管有没有组合纪录,insert之,纪录时间和文字。 
删除关系:根据关系表(回复表)PK删除。 
5,站内短信型
 
特点:主副表是同一个,关系表一般有时间字段,有主键,重点在关系表文字型的字段用来说明每次发生关系的内容(消息)或者其他标记位来表示文字已读状态时间等。 
界面特点:回复文本框。 
例如:站内短信(用户表-短信表-用户表),用户可能给用户群发或者单发,有标记位来表示文字已读状态时间等。 
增加关系:不管有没有组合纪录,insert之,纪录时间和文字。 
删除关系:根据关系表(回复表)PK删除。 
6,用户好友型
 
特点:主副表是同一个,同集合分组型,关系表两外键组合无重复纪录,关系表一般不需要时间字段和主键。 
界面特点:同集合分组型,显示主表,用搜索代替简单的checkbox或多选select,或者一条一条的添加。 
例如:下载站点的文件,(文件表-关系表-文件表)可以被软件工具打开,软件工具本身也是一种文件,可以被下载。用户的好友,也是用户(用户表-好友关系表-用户表) 
增加关系:同版主任命型。 
删除关系:同版主任命型。 
7,未知属性型
 
特点:在设计初期,主表的某些字段类型和名称是不确定的时候,关系表实际上是主表的可扩展字段, 
一个[主表](ID), 
一个[属性名称表](属性ID.属性名称), 
一个[属性值表],包括3个字段: 
  属性值(属性Value varchar(500)) 
  主表ID 
  属性ID 
这样可以作到最小冗余度。 
(和常见的多对多关系不同的是:值统一用varchar来存储,因为这类型的值一般不会用来计算)。 
比如: 
军队的数据库设计中有种物资叫做“战缴物资”,就是打仗的时候缴获的,军队自己都不知道这些物资有什么属性。 
比如缴获的化学品有化学名,通用名,是否有辐射,计量单位,包装规格,数量等等,或者不是化学品是其他任何未知的东西。 
这样东西就可以 
某奇怪东西.属性集合[“某某奇怪属性名”]=”某某奇怪值”;  
某变态东西.属性集合[“某某变态属性名”]=”某某变态值”;  
这样存储。 
再比如: 
手机型号有几千种,除了共同属性外还有不同属性有几百个,属性名和值类型都不一样,有的手机有这属性,有的没有。 
对于这样的“多态”,我们就采用上面的设计结构。 
其效果相当于: 
某奇怪手机.属性集合[“某某奇怪属性名”]=”某某奇怪值”; 
某变态手机.属性集合[“某某变态属性名”]=”某某变态值”; 
界面特点:设置主表一行纪录的属性时候,要列出所有可能的属性名称,每个对应一个文本框。