tp剩余未验证内容-7

bash脚本中 的 set -e表示 exit immediately if a simple command returns a non-zero value.主要是为了防止错误被忽略.会被当即退出, 可是最好在开发结束后, 删除这个指令, 以避免留下隐患.javascript

有四种命令提示符, 有PS1, 天然就有 PS2 PS3 PS4, 分别表示 PS2即 在后续的命令下一行的提示符(continu'ation interactive prompt), PS3是在select选项时 的提示符, PS4是调试时的提示符.php

shell中要进行算术运算, 有5种方法: (由于默认的算术运算符号+-*/ 都不会被直接当作运算符, 而只是当作普通字符来看待, 因此须要特殊处理)html

  • 使用算术扩展: $(( ... )); $[...]
  • 使用外部命令expr expr 1 + 2 注意有空格(特殊符号要用* 转义)
  • 使用内部命令: let 1+2 或 declare -i c=1+2
    外部命令,就是外部存在的 能够执行的文件, 能够用 which命令看获得的, 根shell无关的; 所谓内部命令,就是 shell自己提供的命令(函数), 用which是查看不到没有的.

shell的调试?java

  • 直接用 sh -x ./foo.sh 命令, 其中 -x就是调试的意思 还有其余一些选项 : sh -n只是检查文件是否有语法错误; sh -c "..." 表示文件从字符串中读取.
  • 或者直接将调试选项写在sh文件中的 #!bin/bash -xv???
  • 或者在文件中, 在要开始调试的 位置 写上 set -x 可是要注意, 只有set -x以后的命令才会调试, 这个以前的命令不会被调试.
  • 所谓调试就是 会将每一次/ 每一步 step by step 执行的语句 先显示出来, 而且会将执行语句中的变量用当前值 替换; 而后输出命令执行的结果. 并且执行语句前加上+号

$_SERVER['HTTP_REFERER']为何为空?mysql

  • referer的正确拼写是 referrer, 因此前者实际上是一种历史的错误遗留
  • http_referer是header请求头的一部分, 一般会带在向web服务器发生的信息中, 告诉服务器我是从 哪一个页面连接而来的. 能够给服务器一些额外的信息, 便于其余一些处理.
  • http_refer彻底依赖于浏览器自身, 有的浏览器是没有设置这个变量的. 你就得不到它.web

  • 可是, 在不少状况下http_referer会无效, null. 好比你 直接访问一个页面的时候, 或从收藏夹中访问页面的时候,
    因此通常来讲,只有经过 <a> 超连接 </a> 或者: location.href=...跳转, 以及 POST 或 GET 表单 提交访问的页面, $_SERVER['HTTP_REFERER']才有效。
    sql

  • 因为 $_SERVER['HTTP_REFERER'] 对 POST 表单访问也是有效的,所以在表单数据处理页面 必定程度上 能够经过校验 $_SERVER['HTTP_REFERER'] 来防止表单数据的恶意提交。但该方法并不能保证表单数据的绝对正确,即对表单数据的真实性检测并不能彻底依赖于 $_SERVER['HTTP_REFERER'] 。thinkphp

========================shell

因此, 在tp中, 操做成功或失败的提示 跳转是用 success和error. $this->success/errror('跳转提示信息', 跳转的地址_默认是http_referer, 跳转等待时间)数据库

使用js 使html中的数字递减?

  • 一个页面中, 包含多个head, body, html等标签虽然不规范, 可是仍然能够解析显示的.
  • js获取一个元素的属性?
  • setInterval和clearInterval?
  • 快速调用一个函数的方法.
<script type="text/javascript">
(function(){
var wait = document.getElementById('wait'),href = document.getElementById('href').href;
var interval = setInterval(function(){
    var time = --wait.innerHTML;
    if(time <= 0) {
        location.href = href;
        clearInterval(interval);
    };
}, 1000);
})();
</script>

关于tp?
tp的文件上传 在"专题"中.
tp使用 "类" 的思想: 先new一个 类对象, 而后让 类对象与实际要操做(上传)的文件相关联, 而后经过操做这个 已经关联了的类对象实现对该文件的各类操做.

  • 实际上,这也是 "类"的一个基本思想. 一个类对象(泛泛的), 必须跟具体的实物(生活中的个体) 相关联. (类的对象, 跟具体的实物/事物相关联的 过程, 正是所谓的 类对象的实例化/初始化). 实例化后, 这个类对象 就表明该具体的 人/事物了, 对该对象的操做, 就是对该人/事物的操做!
  • 若是类对象, 没有跟具体的实物相关联, 那么它其实是没有意义的, 也是没有用处的. 好比一张 银行卡"对象", 在没有跟某个具体的人(储户)相关联的时候, 即没有"开卡"的时候, 这张卡实际上是没有用的,你随便怎样处置都是能够的. 可是若是你有一张十万元的卡, 跟你的储存信息/存储资金 相关联了, 若是你丢失了, 又是怎样的一种情景呢?
  • 而上面所说的, 类(对象)没有跟具体的 事物相关联, 只是规定了这个类 能够具备的功能和特征, 这种类, 其实也是有用的, 它就是只是做为一种协议, 一种规定, 就是一种 "接口", "接口"都是抽象的, 即泛泛而论的东西, 不能跟具体的某个 实物相关联, 所以, 它是接口, 不能被 "实例化""初始化"



tp中的array数组, 是应用得最普遍的. 能够说凡是能用 "字符串"的地方, 几乎均可以用数组来 表示, 用数组来操做, 并且都推荐用数组, (由于数组更安全??)


tp的orm就是, 对数据库的操做, 再也不用原始的/原生的 mysql/mysqli函数(面向过程)来处理, 而是用 模型(跟数据库的表相对应)的类/对象来操做, 用对象的方法好比find,select add save等进行增删改查的操做.

其中, add和save方法, 须要先建立 插入和更新的 数据对象$data(实际上就是要插入/更新到表中的 记录)
这种建立数据对象的方法, 有两种, 一是 create()方法, 一是data()方法. 两个方法的相同点是: 均可以/都支持多种数据来源, 包括从 数组, 其余数据对象甚至 普通对象来建立; 不一样点是: create的功能更强大, 不但支持建立的数据对象的自动验证和自动完成($_validate和$_auto), 并且还能够 自动地从 $_POST数组建立数据对象.

  • 建立的数据对象是保持在 内存中, 并无立刻写入到数据库中, 要直到使用 add()方法和save()方法才会写入数据库.
  • 因此, create的数据对象, 你是能够直接显示dump出它的内容的; 并且还能够继续修改.

在进行数据库相关的操做时, 必定要首先设置 数据库配置.

  • 由于你在建立 模型对象 $User = M('user') 的时候, 就须要数据库配置, 若是没有配置/没有正确配置, 就会报错.
  • 首先去加载 Frame\Library\Think\Db.class.php, 执行第一个静态方法去获取数据库类的实例static public function getInstance($config=array()) 参数就是$config数据库链接配置!
  • tp错误的统一输出形式用 : E(L('_NO_DB_DRIVER_') . ':'. $class), E函数的原型是 E($msg, $code); 因此全部的错误提示内容, 都要放在整个 E() 函数的括号内 错误函数是 抛出了一个 异常 throw new Exception($msg, $code); 因此: E函数后的全部内容 都将 中止执行, 直接从 E()函数处退出了, 并且是调用 统一的 异常输出模板.
  • 注意配置的下标名称是: 因为DB自己就有 '数据库' 的意思, 数据库的名称 配置项 是 'DB_NAME' 不是DB_DATABASE, 数据库密码是DB_PWD, 不是 DB_PASSWD.
  • 数据库类型要明确写成, 由于在 convention.php中, 没有默认的数据库类型配置


tp表单在提交的时候, 有两种方式过滤字段,

一是使用 field函数,( 要注意, field方法没有复数, 因此其参数也是 一个 字符串. 另外field是指定 接收的/生效的字段, 不是 将被过滤被丢弃的字段 ) 而后用create()建立,
二是配置 insertFields, updateFields两个的值,
**即便设置了表单 的字段映射, 可是在 后面的全部 连贯操做的 field方法中, 表示 参数的 字段都 应该是实际的数据表字段, 而不是 字段映射, 不是表单中的 字段域, 不然 当定义了字段映射时, 又使用 filed('表单字段'), 那么就会出现 create的数据对象 为空 empty的 错误!

要注意, 若是要设置 $insertFields 和 $updateFields的值, 以及要实现自动验证和自动完成, 都要 创


建 自定义的 模型类, 不能直接使用标准 的模型类的基类.

甚至于, 即便一个大型的不少文件 须要同时编辑的场合下, 用一个 vim窗口界面都是能够胜任的, 首先它的打开速度很快, 其次能够分红多个(好比4~5)个子窗口来同时编辑多个文件, 最重要的是, 每个子窗口均可以 保存多个 曾经打开的 文件的缓冲, 在每个子窗口均可以使用 ctrl+^ 来切换缓冲的文件.

tp多个配置文件?

  • 你能够将全部的配置杂七杂八地放到同一个配置文件中, 好比/Application/Home/Conf/config.php中, 可是若是配置比较多, 比较繁杂的话,就会 显得比较凌乱. 因此将配置分门别类的放在各自的/ 单独的 配置文件, 而后 "包含它们" 是一个比较好的.
  • 你也不能单单的把 某个方面的 配置文件 "放到" '扔到' conf目录下就行, 那样的话, tp也不会知道 你的文件就是配置文件啊, 因此须要给 tp "说 一声, 告知一下 注册一下", 就是要在 "主"配置文件中 说一下: 好比 'load_ext_config' => 'mylang'
  • 本身扩展的配置文件,好比mylang.php是放在跟你包含 说明的配置文件相同目录下, 好比 在 Home/Conf/config.php中配置load_ext_config, 那么扩展配置也就放在Home/Conf中, 并且扩展配置 说明中 不要带.php扩展名

tp的配置尽可能用 小写字母, 由于无论大写仍是小写, 最后都要转变为小写. 虽然为了好看,"推荐"用小写. 可是在实际开发中, 一切都是 以 "效率" 为最高原则的.

tp如何配置本身的 语言文件?? 参考https://www.jb51.net/article/47624.htm http://www.cnblogs.com/yuwensong/p/4156383.html

这个仍是比较复杂的, 一般是不须要的.若是确实要这样作, 步骤是:(可是好像有错误???)

1.在/App/Home/Conf/config.php配置中, 追加
'LANG_SWITCH_ON'     =>     true,    //开启语言包功能       
    'LANG_AUTO_DETECT'     =>     true, // 自动侦测语言
    'DEFAULT_LANG'         =>     'zh-cn', // 默认语言       
    'LANG_LIST'            =>    'en-us,zh-cn,zh-tw', //必须写可容许的语言列表
    'VAR_LANGUAGE'     => 'l', // 默认语言切换变量
2.在Home/Conf目录中建立一个php文件, 好比: tag.php 内容以下

<?php
return array(
// 添加下面一行定义便可
'app_begin' => array('CheckLang')
);

3.把框架中的 Extend/Behavior/CheckLangBehavior.class.php 文件复制到 Home/lib/Behavior/中(完整版的thinkphp包才有,没有的话请自行建立)
4.而后就是 建立对应的语言项文件了, 在 /App/Home/下建立对应的三个语言文件夹: zh-cn, en-us, zh-tw. 而后再在这些语言目录中建立对应的语言文件, 文件名必须设置为common.php??
5.最后就是 引用/使用 语言配置了, 在模板文件中, 使用 `{$Think.lang.语言项}` 在后台控制器中, 用L()方法来引用.

==================================================================

若是dump一个对象的话, 将输出这个对象的全部内容, 包括对象的 全部成员变量和全部的成员方法.

关于数据对象data和模型对象$User的区别?

  • $User是 经过M, D等方法建立的模型对象. 有两个方面的做用, 一个是 关于模型的全部方法操做, 如add, select, save, delete等都必须经过这个对象完成; 另外一个做用是, 其自己也能够 保持/保存 一些"数据", (这些数据不是指 模型类自己定义时所包含的成员等, 而是指 包含 将要写入到数据库表中 "记录"内容).
  • 数据对象, 是指 模型类$User 所包含的 表记录 数据. $User得到 表记录数据有两种途径, 使用 data()方法, 或者使用 create()方法.
    一方面, 你能够直接 echo出 对象$User所包含的表记录字段, 好比: echo $User->name;
    另外一方面, 你还能够接收 create方法的返回对象 $var_data = $User->create() , 这样你就能够很直观地dump出 $var_data 查看数据了

数据表的select操做, 不仅是能够选择记录, 并且能够完成复杂的 字段运算等

where子句,不但能根据条件选择筛选记录, 并且 在 id自增的时候 能够用来选择最前/最后/中间 N条记录: ... where id > Max(id)....
一般来讲, where, limit等的操做耗时 比order的耗时 要小, 应该尽可能避免 order操做??
在非mysql的选择子句中,最前面N条记录 能够用 top子句 , 可是 mysql没有top子句! 只能使用limit子句. 参考 http://www.cnblogs.com/freeliver54/archive/2008/07/23/1249232.html

  • limit子句的格式是: limit <偏移offset> <记录个数 return_num> 由于是offset偏移, 因此老是比起始记录位置小1. 好比: 选择从第10条到20条的记录, 应该是: limit 9, 11 从第10条开始的共10条记录: limit 9, 10
  • mysql没有直接选取 最后N条 的子句.**

male和female不仅是指人, 还能够用来指 雄性动物或 雄性植物(雄株) . man和woman一般用来指成年男人和女人. 也就是说 male包括 man和boy. female的fe.

create在 建立数据对象时, 会 验证数据源的合法性(会自动过滤 数据表中没有的字段!). 因此即便表单中有 多余的/不是数据表中的字段信息, 也不用管, 由于 非数据表字段会自动过滤/丢弃,不会出如今 建立的数据对象中.

  • 模型类对表单中的 字段映射: 目的, 由于默认的在建立数据对象时, 是要求 表单中的 字段name要和 数据表中的字段名称 相同, 不然会报错. 可是那样会在表单中暴露数据表的字段,引发安全问题. 因此 经过字段映射, 让在表单中的字段名称 => 映射到 数据表中的字段名. (这样即实现了 从表单到 数据表的数据对象建立, 又隐藏了数据表自动名, 多了一点安全保护).
  • 字段映射的方式是: 在自定义模型类 中添加protected $_map=array('表单字段名' => '数据表字段名'); 注意是把 表单字段 映射为 数据表字段, 不多是反过来吧,自己你就要隐藏数据表字段呢, 你难道还想 主动暴露到表单中来吗?

  • 使用字段映射: 即便使用了字段映射, 并不会 自动 影响 查询结果, 查询结果中的 记录中的 字段名称仍然是 原来的数据表中的字段名称, 不会是 "表单"字段名. 除非你在配置中设置了 read_data_map' => true, 或者使用 D('user') -> parseFieldsMap($data_result)方法手动 转换.

  • $User->create() 后, 里面的数据对象就已经被 映射了, 即原来表单中的字段就已经自动转换为数据表中的字段了,(这个是create所做的工做之一),因此接下来就能够用 连贯操做 add了 .

字符为空 和 not null 是不一样的! 当表单中的input域(好比姓名) 没有填入内容的时候, 传递到$_post的是 ""空字符串, 不是not null. 因此 它是合法的, 会被add添加到数据表中.

$_POST是: 
array (size=2)
  'username' => string '' (length=0) //这里明确给出了是: string , 并且是 '', 不是 null!
  'gender' => string 'm' (length=1)

在数据表中, 字段field也叫作 column列. 在定义表/修改表结构的时候, 格式是: col_name colomn_specification/col_definition 即 列名 而后是对列的定义/说明/描述 (多个定义单词直接用空格分隔).

===============================================================

要想一次性的关闭多个 已经打开的缓冲区, (而不用一个一个地去关闭), 使用 冒号命令: bufdo bd其中 bufdo是指 针对全部的 缓冲区执行的命令.

关于sql语句中 各子句的执行顺序? 参考 主要是这个: http://www.cnblogs.com/Qian123/p/5669259.html 和http://www.cnblogs.com/Qian123/p/5669259.html 明确了sql语句的执行过程, 你对数据库的执行过程和原理就会更深刻, 也会避免一些使用上的错误, 好比:

  • sql语句中, 任何一个 "关键字(单词/词组)"都是一个子句, 包括: from -> on -> join -> where -> group by -> having -> select -> disctinct -> order by-> limit
  • select子句虽然在最前面, 但并非第一个执行, 它是在第8步才执行的. 而只有在select 子句中 才能定义 字段(列)的alias,(from子句中能够定义表的别名) 因此在第8步select子句以前都是不能使用 列的别名的, 只有在这以后, 即第9步distinct 第10步order by子句中使用列的别名
  • 最早执行的老是 from子句, 最后执行的老是 limit子句. 因此 在from子句中定义 的表的 alias别名, 能够在 其后的(从第2步后)全部子句中均可以使用, 包括随后的where子句中就可使用表的别名.
  •  mysql中 的全部别名, 包括 表的别名, 和 字段的别名 均可以加上 as, 也能够省略 as.
  • 一般每一步子句 获得的是一个 虚拟表virtual table(即虚表VT), 从 VT1~ VT9, 可是在第10步, 即order by子句, 返回的并非一个 虚表vt, 而是 一个游标 即VC(virtual cursor). 因此凡是包含 order by子句的 查询句都不能做为 "表的表达式)(即在 凡是须要一个 表的表达式的地方, 都不能包含order by子句) 表的表达式其实就是 一个虚表vt.
  • distinct子句 的原理 是 在内存中, 利用一个 临时表来 获得一个 vt的

  • 要理解select子句的过程: 查询/选择 结果字段, 其实并非直接拿着 这些要显示的字段到数据表里面去"挑选"记录.实际上, 在select以前, 已经作了大量的工做, 已经通过/获得了多个 步骤的 VT虚表的迭代过程了. 已经准备好了 查询结果的(包含全部字段)的 多个记录了. select子句的做用 仅仅是 挑选要显示/要返回的 部分字段(可是其余字段其实仍是存在的, 由于即便在 其后的 distinct/order by 等步骤中, 虚表VT10/11 其实仍是一直存在的, 在内存中), 因此在 select子句后, 还可使用 order by子句按 非select字段进行排序的.
  • 在order by子句前, 整个过程的vt都是 无序的. 只有当你确实须要有序的, 须要排序的结果集时, 才用order by. order by很耗资源和时间, 要慎用.
  • mysql中的统计函数, 好比max, min, sum, avg, 也叫 分组函数(group functions). 也就是说, 只有在 执行了group by子句后, 其余子句才能使用: 即在第5步后 才能使用 分组(统计)函数. 而where子句是在 group by子句以前执行的, 因此 在 where 子句中, 就不能使用 group子句中才能使用的 统计函数. 好比 where score>=average(score)??  就会报错: "invalid use of group functins"

  • 分组后, 在分组记录中, 咱们能够 select出关于分组的统计信息, 也能够select 原数据表中的非统计信息(即普通字段信息), 虽然分组操做的目的一般是要 select出统计信息. 若是分组后 select的是 非统计字段信息,则 在第9 步(select步骤)老是显示的/保留的是 相同分组中 排在最前面的那个记录的 字段信息. (可是 在分组后所得的虚拟表VT(第5步时)分组中的 其余记录/信息仍然是保留的. 是按分组字段的不一样 挨着挨着排列的(相似于excel中的分组), 因此, 一直到第8步select的时候 还能够用 count, max等统计函数对全部 记录 和 相关字段进行统计 )

关于分组后的显示结果?

+------+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| id   | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                                        |
+------+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
|    1 | SIMPLE      | user  | range | PRIMARY       | PRIMARY | 4       | NULL |    7 | Using where; Using temporary; Using filesort |
+------+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
1 row in set (0.00 sec)

关于explain中的说明?

  • type是指查询的范围, 是整个记录ALL, 仍是有条件/范围的, 一般where子句属于 type=range的. 若是查询条件中包含了主键 那么在explain中会显示primary key. extra是说会用到哪些 "额外" 操做. group by分组, 会使用到临时表temporary和其结果会自动 按分组字段 升序排序??(隐含一个 order by group_column asc)?? 因此explain中, 会有 using filesort. 凡有 (或者是 隐含有) order by 排序的操做, 都会有 using filesort的 执行计划. 好比 group by的分组操做, 就暗含了 分组后的记录 按 分组字段 asc 升序排列的 操做.

在要实现一些比较 复杂的 查询功能时, 都会使用 "子查询". 子查询主要有两个做用: 获得的 能够是一个 表的表达式, 用来做为中间表/临时表, 也能够获得的是一个 数值, 用在where等子句中. 因此, "子查询"的使用仍是 不少的!

当要求id最大值时, 慎用select Max(id) ... 而是用索引来作, 好比: 建立id的索引(show index from table_name), 而后用 select... order by id desc limit 1 来代替, 这样效率更高

  • 在用group by分组后, 可使用 分组函数(统计函数)好比max, min, sum等 确实可以 对每一组的数据 进行 最大值等的统计, 而不会只针对全部记录进行统计. 由于select子句在 group by子句后执行.
  • 可是 group by和max等统计函数一块儿使用时要注意: 若是包含了非统计数据(好比普通字段的值), 因为分组后, 老是取第一条记录的普通字段的值,这样 当第一条记录的普通字段值和该分组的最大值等统计值一块儿 并列组成一条记录时, 就可能发生误解,跟实际状况不符. 好比统计分组中的最大值, 可是这个最大值并不必定就是 第一条记录的用户 正好具备该最大值.
    此时有两种解决方案,
    参考: https://blog.csdn.net/john_hongming/article/details/42742965
    一是, 先将原来的表 按照要求Max/min的字段 进行排序, 升序或降序, 反正要保证 出现/保留在 分组里面的" 包含普通字段的那条记录" 要在 第一个记录位置就好. 获得一个 (中间表/表的表达式) 而后对这个中间表进行 分组.
    二是: 使用where in ...
MariaDB [test]> select * from user where score in (select max(score) from user group by gender);
+------------+-----------+--------+-------+
| id         | name      | gender | score |
+------------+-----------+--------+-------+
| 0000000002 | 孙徐连    | w      |    98 |
| 0000000010 | 王的徐    | m      |    97 |
+------------+-----------+--------+-------+
2 rows in set (0.00 sec)

MariaDB [test]>

对mysql而言, 当建立了主键后, (最经常使用的是id), 会自动地给 主键建立 索引 (因此, 没必要重复地 去建立索引). show index from user;

  • 给数据表建立主键时, 要注意对主键的设置加以程序安全性的保护, 由于一方面 增删改查主要就是根据主键来进行的; 另外一方面,主键也 比较容易暴露泄露 数据库的信息.
    数据表的 索引的建立很方便, 很简单, 不会给数据表带来负担. 可是, 索引在查询方面 能够带来很大的速度提高. 因此, 在实际项目中, 一般应该 给 要查询的 字段 (不仅是主键字段) 好比'name'字段建立索引. 另外, 在 可能出错, 根据某个字段进行 排错时的字段 也能够给它建立索引.

"every derived(派生的/继承的/衍生的/导出的...) table must have its own alias" 就是说, 在 mysql中, 任何 中间表(表的表达式)/临时表都必须有一个 别名,而无论你会不会用到这个别名.

  • 但并非全部的 中间查询/临时查询/放在括号中的查询, 都要用 表的别名. 这个只是针对 须要 "表"的时候, 只是在 derived table, 是table , 只是在 from子句 后面的中间表, 才须要用 别名. 而在 where子句 是不须要表 的别名的! 由于 where子句中 只是须要一个 数据/数值/集合,用来知足where的 >, in, between等表达式而已.

having 和where的区别?

  • 二者在语法上的写法是同样的, 都是条件筛选, 只不过where是对 表的 "列"进行筛选, 所以where表达式中只能 出现表的列字段, 而having是对 查询结果进行筛选.
  • having能够单独使用, 不必定老是 必须 跟 group by一块儿使用!
  • having 是对 (能够分组 也可能不分组 group by ->) select以后的结果 进行条件筛选. 因此 , 可使用 select子句中的 全部别名, 包括字段运算后的别名.
  • 在select语句中, 字段被 当作是 "变量" , 因此 能够对字段进行 算术运算的. 好比 查找成绩在90分以上的记录: select id, name as '姓名', score-60 as chazhi from score having chazi>30;
    ??? 难道having子句 是在 select子句后执行的??
MariaDB [test]> select id, name as '姓名',  score-60 as chazi from user where chazi>30;
ERROR 1054 (42S22): Unknown column 'chazi' in 'where clause'
// 很明显, where只是针对 字段来判断的, 若是是select中的 运算表达式, 则会报错, "未知的字段"

MariaDB [test]> select id, name as '姓名',  score-60 as chazi from user having chazi>30;
+------------+-----------+-------+
| id         | 姓名      | chazi |
+------------+-----------+-------+
| 0000000001 | 孙以的    |    34 |
| 0000000002 | 孙徐连    |    38 |
| 0000000010 | 王的徐    |    37 |
+------------+-----------+-------+
3 rows in set (0.00 sec)

MariaDB [test]>

group by和order by的一块儿使用?

  • 要求, order by中的字段, 必须是 出如今group by子句clause中.
  • order by子句必须放在 group by子句的后面
  • group by默认也要进行排序, 多个字段进行分组或排序时, 字段顺序必须固定, 不是随便写的.

===================================

终端terminal shell是一个集成环境, 在里面运行的任何程序包括 vim, mysql, 等都是子程序, 均可以使用 shell统一的 菜单/快捷键设置操做, 好比 复制/粘贴等. 消除其余行, 到最顶端, 使用 ctrl_L

====================================

tp的功能也不是尽善尽美(实际上世上也没有尽善尽美的东西吧), 还有一些bug的.

在 项目App/Runtime/Home/目录下的 那些php文件, 实际上就是 View目录下的 "模板" 的编译结果文件(所谓编译, 就是将模板中的php代码 解析成普通的html后)

关于布局模板

  • (模板)布局layout是tp的功能, 实现布局的方式是用 模板, 这个模板叫" 布局模板" . 无论哪个框架的模板布局, 仍是颇有用的. 它是生成 基本框架都相同的多个页面的一种快速方法: 把多个页面中, 相同的要素(结构)好比页面的头部, 菜单栏, 页脚等内容是基本相同的, 提取出来, 而后多个页面中只有 主体内容 不一样的部分进行组装. 没有必要每个页面都完整的写一遍, 这个正是 符合软件 "结构化/模块化+重用" 的思想.

  • 布局模板的实现有三种方式, 其中第二种方式, 是使用 layout标签, 这个标签的使用方法 ,跟其余html标签同样, 也是指定相应的属性就行了
    layout标签不须要任何配置;
    layout标签的属性有 name(使用哪一个布局模板), 和 replace(布局模板中的替换字符串)
    头部增长(好像不必定是要在 head中, 在body中定义也是能够的! 并且 layout标签甚至能够在body内容的最下面/最后面书写都是能够的. 可是必定要在配置中, 关闭 LAYOUT_ON设置,不然 布局不会成功, 不会应用 布局模板!!! )<layout name="Layout/newlayout" replace="{__REPLACE__}" />
    使用了layout标签后, 一样的, 是把 当前模板文件的内容 替换到 布局模板中的 {REPLACE}

  • 使用include标签 中的 layout标签, 能够实现模板标签的嵌套.

  • 在convention.php配置中, 关于布局(模板) 的配置 有3个:

'TMPL_LAYOUT_ITEM'      =>  '{__CONTENT__}', // 布局模板的内容替换标识
    'LAYOUT_ON'             =>  false, // 是否启用布局
    'LAYOUT_NAME'           =>  'layout', 
    // 当前布局名称 默认为layout
  • 这个是总体/全局配置, 对整个项目中的全部模板文件 都有效的.
    可是, 是能够来调节的,并非说, 只要开启layout_on=>true后, 就必须/不得不 使用布局功能了. 实际上, 即便开启了layout功能后, 仍然有二者方法来关闭: 一是 在 须要 关闭的模板页面中, 加上 {_ _NOLAYOUT_ _ } ; 二是 在 控制器的操做中 使用 全局函数layout(是框架中的functions.php文件中的函数), 好比 layout(true), layout(false)禁用布局功能, layout('layout/new_layout') 并且使用全局函数layout时是不须要开启layout_on=>true 这个配置的.

要注意, 布局模板的位置默认的 跟普通模板文件的位置同样, 即布局模板 文件是: /AppName/Home/View/layout.html, 注意默认的是View目录下的 layout.html, 而若是有的配置设置了 模板的子目录位置时, 就要从新指定 "layout_name" 了.

相关文章
相关标签/搜索