tp框架中 关于数据库mysql 的一些疑点知识
mysql创建索引, 通常是在 创建表的 同时/时候, 就创建了
即使是在win下, 用命令行操作数据库 , 也要比 图形界面的鼠标操作快得多
索引的类型有: unique, fulltext索引, spatial空间索引, 和普通索引 index/key
fulltext全文索引的使用?
-
使用索引的好处, 如同字典 的 索引一样, 如果你从头到尾不使用索引 一个字一个字地 查字典 找一个字的话, 是很老火的. 反之, 使用前面的偏旁部首索引 查字, 可以通过 字 和 页数 的 对应关系 一下子找到该字. mysql的索引是同样的道理, 它创建了 数据和 数据所在的 位置/记录行之间的 对应关系....
-
fulltext是全文索引, 也叫做 全站索引. 从 mysql4.0 开始支持.
其中的 ft_min_word_len 叫做 fulltext min word length. 默认的是 4个字符, 对英文的全站索引比较合理, 对中文, 就不是很合理了. 中文最好设置成
ft_min_word_len =2, 或 1
方法是在 : 配置文件 my.ini(linux的 my.cnf) 中的 [mysqld] 节中, 增加这一句:ft_min_word_len=2, 或 1
就好了
全文索引 通常是对 文章的标题(搜索文章标题 title), 或内容(搜索整个文章的内容 content) 进行创建 索引. 然后 对他们进行 搜索就变得 可能.... -
创建全文索引的方法是:
- alter tablearticle
add fulltext index_content(content
);
或者直接创建索引
- create fulltext index index_content on article(content
); -
使用 全文索引的搜索方法是:
select title, author, release_time, content, field1, field2... where `content_field`(全文索引的字段名称) against ('查询内容-搜索字符串') order by id desc limit 10
- 关键是 这里的 查询条件: where '全文索引字段' against ('搜索内容') 的用法
- 网页开发中, 只要 把数据 选择/搜查出来后, 显示和 呈现 就比较简单和随心所欲了.
关于编辑器中的字体选择,
- 可以选择 Courier New 字体. 这个字体也是每个 Windows都会带的,字体很好看,除了o O 0的区别,也是很多人在编程中使用的。
- 或Bitstream Vera Sans Mono
- Bitstream Vera Sans Mono,以及他的衍生字体DejaVu Sans Mono——DejaVu扩展了一些Unicode中的字符。 这也是很多开发者推荐的字体,除了完全满足上面说的所有条件之外,又是TTF字体,基本字形是无衬线的,适合屏幕阅读,最重要的还是开源的字体!
字母的宽度一致
或称为等宽字体,由于代码文件是普通文本,不带样式的,所以宽度一致易于排列和对齐,能迅速找到位置,提高可读性。
印刷术中这种等宽字体称之为monospaced字体,他是字体中的一个大分类(family),如常见的Courier和Courier New。由于考虑到现在的多语言环境,在不同的系统中,要将这个字体在不同字符集下映射到不同的具体字体上去,比如,一般我们的系统都会把中文的映射到“宋体”上。
courier: 快递员
tp中的add支持批量写入, 就是一次性写入多条记录, 用数组表示, 数组用 动态添加的方式定义, 方法名是 addAll. 注意是 AddAll , 不是 AddList
$dataList[] = array('name' => 'foo', 'age' => 10);
$datalist[] = array('name' => 'foo2', 'age' => 15);
$Model -> addAll($dataList);
- 在 add方法和save方法中, 要过滤字段, 既可以直接在 操作中, 用 field(...) 连贯操作方法来过滤字段, 也可以直接在 模型类中 直接定义 (一般是 类自己的属
性, 不是通用性的属性, 常用 protected 定义 ) protected $insertFields = array (...); 和 protected $updateFields = array(....);
- 在php和tp 的 很多操作方法和函数中, 比如find 方法 和 select方法等, 如果查询出错, 则返回false; 如果查询结果为空, 则返回null. 如果有结果, 则返
回字段或数组/数组集. 要清醒地认识到 返回的结果 false 和null的区别,不要搞混了.
**注意, find的结果, 即使满足条件的数据不止一个, find方法也只会返回第一条记录(当然可以用order排序等) **
class Model {
// 操作状态
const MODEL_INSERT = 1; // 插入模型数据
const MODEL_UPDATE = 2; // 更新模型数据
const MODEL_BOTH = 3; // 包含上面两种方式
const MUST_VALIDATE = 1; // 必须验证
const EXISTS_VALIDATE = 0; // 表单存在字段则验证
const VALUE_VALIDATE = 2; // 表单值不为空则验证
// 当前数据库操作对象
protected $db = null;
// 数据库对象池
private $_db = array();
public function field($field,$except=false){ ///这里的except是指定是否 进行排除...
if(true === $field) {// 获取全部字段
$fields = $this->getDbFields();
$field = $fields?:'*';
}elseif($except) {// 字段排除
if(is_string($field)) {
$field = explode(',',$field);
}
$fields = $this->getDbFields();
$field = $fields?array_diff($fields,$field):$field;
}
$this->options['field'] = $field;
return $this; //// 这里返回的是 模型对象本身, 连贯操作都返回的是 $this.
}
在tp中, 几乎所有的函数和方法中的参数, 都同时支持 字符串和数组的 参数形式, 即既可以使用 字符串的参数, 也可以使用 数组的参数 形式.
关于错误/成功/重定向 跳转处理?
-
全局的跳转函数:
function redirect($url, $time=0, $msg='') {...
-
控制器类的 跳转成员:
$this -> protected function redirect($url,$params=array(),$delay=0,$msg='') {
$url = U($url,$params); // 这里就是借助于U方法, 将基本url和额外参数组装成复杂url地址.
redirect($url,$delay,$msg); // 然后调用的 全局的redirect方法.
}
- 所以, 两个redirect方法其实没有本质的不同, 参数都是一样的(跳转地址url, 延伸time/delay, 提示消息message), 只是, 成员方法多了一个
$vars
后来被U方法组
装.
- 关于U方法. 熟练牢固地掌握U方法:
-
U($url, $vars, $suffix, $domain), $url地址本身支持 Module/Controller/Action#所有的锚点都用井号表示@别名的相同的域名? var1=val1&var2=val2... 而且还支持分开的 单独的额外参数$vars, 后面两个参数用来说明地址的开头和结尾, 结尾用$suffix ,开头用@domain来说明...
-
具体的参数 **很多时候 就是用 U方法 来将
初步的原始的 基本的$url地址和 参数 $vars/ $params
组装成完整的 复杂的url地址,比如 上面的两个 redirect方法. **
/**
* URL组装 支持不同URL模式
* @param string $url URL表达式,格式:'[模块/控制器/操作#锚点@域名]?参数1=值1&参数2=值2...'
* @param string|array $vars 传入的参数,支持数组和字符串
* @param string|boolean $suffix 伪静态后缀,默认为true表示获取配置值
* @param boolean $domain 是否显示域名
* @return string
*/
function U($url='',$vars='',$suffix=true,$domain=false) {
关于tp中的跳转?
- 在
$Model->redirect($url, $vars,$delay,$msg)
中,如果要设置延时,则必须输入params, 因为delay参数是在第三位
如果发现跳转后的url有问题, 可以先测试一下 U方法。U($url, $vars, $suffix, $domain);
如果不想使用U方法生成跳转地址, 也可以直接使用php的header函数或 全局的redirect函数。
-
$this->redirect方法和success, error的区别是
redirect 是利用php的header重定向,而success和error是使用的html的meta http-equiv属性。meta http-equiv='refresh" content="5; url=www.foo.com"
redirect 无模板页面, 输出的提示信息是直接在函数内echo输出的
而success和error都有对应的模板输出。
三者都可以实现页面跳转, 只是redirect可以无延时的重定向, 具体采用哪种情况视具体而定。 -
success和error 的模板文件可以定制:
-
tp中的分隔符, 是用 depr来表示的 , 不是 dept: 猜测: depr: 是 data/delimiter separator的缩写, 所以 最后那个字符是R不是T.
-
runtime下的 Home目录中的???.php文件 实际上是 从 控制器/操作方法到 生成 模板文件的 中间文件. 每个
{$foo}内容实际上 是转换成了 <?php echo (...); ?>
-
即使是开启了缓存, 'TMPL_CACHE_ON' =>TRUE, 'TMPL_CACHE_TIME' => 1等设置, 也并不是表示 模板缓存runtime/home/....php文件会随时重新生成新的不同名字的文件, 仍然是同一个 文件名称.
-
strip主要是动词, 表示 "剥夺, 剥掉, 剥皮"等的意思, 而stripe 主要是条带 讲, 没有剥夺的意思.
-
die和exit的区别: 两者实际上是一样的! exit是原函数, die是exit函数的别名alias. 两者可以接受 一个数字或字符串: 具体用法上,
如果是脚本运行多用exit, 如果是web运行, 多用die. 如果传入数值, 表示的是一种 运行结果的状态码 (比如123, 这个状态码数字是不会输出的), 要输出, 得用 字符串方式比如exit('123'), die('123')...
-
success和error 可以使用项目内部的模板文件, 用
TMPL_ACTION_SUCCESS => Public:success
等来定义, 注意, 模板表示文件路径用冒号来表示 , 其中 定义error也是类似的 -
模板文件中可以使用的 模板标签是: 5个:
$msgTitle, $message, $status(1表示成功, 0 表示失败) , $waitSecond, $jumpUrl
-
success和error会自动判断当前请求是否是ajax请求, 如果是ajax请求, 会调用 ajaxReturn方法 返回信息, 返回的数据$data会封装三个变量
$data['info'] = $message;
$data['status'] = $status;
$data['url'] = $jumpUrl;
tp中的查询语言(查询方式)包括很多种,主要有以下这些
-
子查询 就是生成$subQuery 语句(子语句), 然后生成的子语句 又用在其他查询语句中.
子查询有两种方式
一是在连贯操作后, 使用select(false), false就表示不进行真正的查询结果,而是生产查询子语句;
二是在连贯操作后, 用 buildSql()方法 -
虚拟模型
是指虽然是模型类, 但是不会进行真正的数据库curd操作,只是借助模型类来封装一些业务逻辑。 实际中几乎没有什么用。
建立一种思想认识, 就是tp的mysql数据库连接是惰性的: 即只有具有数据库操作: 读写 的时候, 才会去建立数据库连接 -
动态查询 这些方法都是通过
__call机制得到的
就是直接依据表中的某个字段(的值作为查询条件), 返回符合条件的记录(集)或字段的值,主要有两个方法:
- getBy... 比如根据“name”字段获得记录(集):
$User -> getByName('obaa');
- getFieldBy... 比如根据“name”字段获得字段值:
$User -> getFieldByName('foo');
-
tp中查询条件的表示方法一般、大致有这样几种: $where, $cond, $map.
-
在php中,甚至所有的编程语言中, return语句的写法, 后面可以 直接跟 变量,表达式, 甚至直接跟一个复杂的 语句, 比如
return $this->where($where)->getField($args[1]);
-
原生sql语句查询
- 凡是 tp 非原生语句, 都是支持/默认 表前缀的, 比如 think_, 那么凡是 原生语句查询, 都不能支持 表前缀, 那么都要用 表的全名, 或者使用 下划线的方式: 比如: USER, 或 __PREFIX__user.
tp的模型类也支持 原生的sql语句查询,提供了两个方法:(但是要注意 原生查询就不能使用连贯方法了)
一个是 query, 只进行查询语句
另一个是 execute,只进行 增加记录 和 更新记录的操作
如果设置了 读写分离的话,那么,query始终在读服务器上操作, execute始终在写服务器上操作
- 统计查询?
-
**跟上面的 动态查询一样, 统计查询也是使用Model的 __call重载机制实现的, 有
if (in_array(strtolower($method), array('count', 'max', 'min','avg', 'sum'), true表示严格检查类型和大小写匹配)) {... return $this->...} elseif ....
** -
Dejava是法语词, 表示 心灵之境, 似曾相识. Sans Mono 是一种编程中常用的字体
-
php中, else if既可以分开写, 也可以 连起来写: elseif 这样做是为了效率更快
-
in_array函数, 如果是字符串包含检查, 则 最后面不管是false还是true, 都会严格检查字符串字符的 大小写, 如果大小写不符, 都会认为不包含.
-
统计查询中, count可以有参数 , 常用的是id, 也可以不用参数. 而其他统计 方法必须有参数.
-
统计查询, 都支持 连贯操作的使用!
1.组合查询
其条件的主体$where还是数组, 但可以组合使用字符串条件_string, 查询_query , 或其他的数组条件_complex
组合查询, 就是多种格式的条件 一起混合使用.
【说明】
- 但是组合查询中, 除了主体的数组条件外, 其他的特殊查询一次只能定义一个.
- 由于才用数组索引的方式, 索引/下标相同的特殊查询会被覆盖
关于tp中字段过滤的处理.
首先, 当要插入或更新的data中, 包含了数据表中 没有的字段时, tp会自动过滤掉该字段;
其次, 也有不过滤的情况:
- 如果你使用了 strict 的连贯操作方法,将严格检查???
- 如果你开启了 APP_DEBUG 为true的调试模式, 将抛出异常: ???
'_ERROR_QUERY_EXPRESS_' => '错误的查询条件',
- tp中的E函数和L函数?
E函数是 抛出异常, 结尾是 直接是 throw, 不是 return. 在tp中 错误, 叫做" 异常" ??
function E($msg, $code=0) {
throw new Think\Exception($msg, $code);
}
L函数 ,可以获取和设置语言?
L函数中设置的 语言项 是 用下划线 开头和结尾的, 而且是大写
-
php中的foreach: 有for结构语句, 没有each语句, 所以要使用遍历数组的话,使用的结构是foreach语句.
-
分析链式操作的方法名,是在成员函数 protected function _parseOptions($options=array()). 在这个函数中进行了连贯操作的解析. 生成对应的 数据库操作 查询方法或条件
-
Model类的连贯操作(链操作)方法名,是放在 protected $methods=array('strict','alias', 'table', 'where', 'order','limit'....)数组中的.
-
类的成员变量和函数, 除了必须在外部访问的,用 public外, 其他的应该用 protected(本类和子类)和private(只有本类可以访问)都是私有的
-
类的常亮, 不能用\(符号, 约定使用 全部大写 来表示 常量MEMBER. 只能用类来引用, 在类中 , 如果类目很长, 也可以用self来代替. self\)this的区别是, 前者表示类自己, 后者表示类的一个 实例.即 AClass::MEMBER 和 self::MEMBER是一样的. 但是 self只能在类的内部使用, 因为在类的外部self没有上下文的约束, 就无意义了.
-
注意 类的常量 const 是 public的,而且, 一般都不用 public去修饰. 因为可以在 类的外部用 AClass::MEMBER 举个例子.
// 可以在类的外部, 比如index.php中访问类的常量:
print \Home\Controller\IndexController::INDEX_TYPE;
在IndexController类中, 可以直接用self访问:
print IndexController::INDEX_TYPE.'<BR>';
print self::FOO_TYPE;
- tp支持区间查询?
就是针对同一个字段的多个查询条件的组合. $where用数组表示, 其中的条件可以是字符串,数组,表达式等任何形式的. 最后的一个数组元素(参数)表示 条件组合类型,有'OR,XOR,AND', 默认不写的时候表示 AND.
$where['name'] = array( array('like', '李%'), '张三', array('exp', 'in("李四", "王五")'),'OR');
- 在tp中, 配置文件或语言文件中,表示某个意思的单词, 通常用缩写, 或者"基本单词", 后面一般不加后缀的,比如tion, re等...
比如'BUILD_DIR_SECURE' (不用security), 'ERROR_QUERY_EXPRESS' 不用expression.
php的header函数:
是将html中 meta 标签的 http-equiv 属性值和 content属性值, 放在一起来写的. 但是不要 meta和http-equiv和content,所以显得更加简洁. header('Content-type: text/html; charset=utf-8 ');
使用的L语言配置项要写正确, 特别是最后的下划线, 否则,会按原样显示... 比如: L('_ERROR_QUERY_EXPRESS');
将会是错误的, 还是按原样输出_ERROR_QUERY_EXPRESS
通常在php中引号用单引号(只有要在字符串中解析$foo变量的时候才用双引号), 但是在操作数据库语句 sql语句中的时候, 要使用双引号,包括在html中的属性时也要使用双引号.
php中的echo和print?
- 两者几乎是一样的, 凡是echo可以使用的地方, print也可以使用, 反之亦然
- echo和print都是 语言结构(什么叫语言结构? 就是 关键词, 比如case, if, foreach等之类的...) 所以, 后面不需要 加 括号.
- 通常还是在php中用echo. 只是如果你熟悉/习惯 了 c/c++ 语言风格的话, 你可以使用print语句.
- 两者的细微区别是: print 同时/一次 只能输出 一个 字符串, 不能输出多个字符串; echo可以 同时输出多个字符串.
- echo 不需要括号, 如果加括号, 则只能每个字符串都加括号, 不能把多个字符串放在一个括号中. 否则会 报错! 和print的错误输出一样" 非法的逗号".
- tp中的表达式查询?
-
主要是为了 解决复杂条件查询, 比如 like, 大于等于, not between等之类的条件
表达式查询, 用数组来表示. -
实际上就是将 字段 \ 比较运算符和\ 比较的具体值 \分开来写: 比如 字符串条件
$where = 'age>=10'
中包含三个部分, 一个是数据库字段, 一个是比较运算符 一个是比较值. 表达式查询方式就是: 将字段写在数组的'下标'中, 然后将比较运算符和 比较值分开写, 来放在另外的数组中:$where ['age'] = array('egt', 10);
-
也可以将 比较运算符和 比较值放在一起写 (像原生的sql), 那么 后面的array, 就用 'exp' 来表示. 比如:
$where [age] = array('exp', 'between(10, 20)');
-
tp中的条件查询?
可以使用 字符串/字符串预处理/数组/对象 等 方式都是可以的, 但是 tp推荐的是使用 数组方式, 更高效更安全.
多字段条件的数组方式, 默认的逻辑是and, 但是可以用$conditon['_logic'] = 'or';
来改变.
如果用对象的话, 要初始化一个 用在 条件 \(where中的对象, 使用 `\)where = new stdClass(); ` 来定义 -
tp中的快捷查询? 就是 多个字段的条件值 相对应赋值
- 只支持两种 逻辑运算符, 也就是只有两种情况: & 和 |
- & 和 | 只能放在 前面的 数组 的 索引字段 中 , 而不能放在后面的条件中, 因为条件是用array(....) 数组来表示的.
- 而且 & 的话, 后面数组条件的最后一个值 必须是
'_multi' => true
$where['a&b&c'] = array(1, '2', 3, '_multi' => true);
- 对于 | , 只只适用于 多个字段对应同一值的情形, 如果是 同一个字段 对应多个 值的 情形, 请使用 字段的区间查询...
$where['foo|bar'] = 'foobar';
tp查询语句中的 like? 特别补充两点
- like的array数组, 支持 多个值的情形: 而且支持用and /or等逻辑连接:
$where ['name'] = array('like', array('think%', '%foo%', 'other-foo'), 'or' );
- like 的字段模糊查询, 你可以手动的写百分号, 也可以在配置中设置模糊查询, 这样在like 查询条件中, 就不用写百分号了. 设置是:
'DB_LIKE_FIELDS' => 'title|content|memo等字段'
那么对应的查询条件就是:$where = array('like', array('think', 'foo', 'other' );