thinkphp疑难解决4
关于文件上传所涉及到的php.ini 中的一些配置:
(以当前要设置的关键字开头...)
-
是每个上传文件所允许的大小, 默认的 upload_max_filesize = 2M, 如果超过了2M,_POST $_FILES就是空。可以设置大些.
-
是整个form表单允许的post数据的总的大小, 默认的是8M, post_max_size = 8M, 可以设置大些.
-
是上传脚本允许执行的最大时间,通常,一个5M左右的文件, 在通常一般的wan网络中,需要 约半分钟的时间. 如果上传文件较大较多, 可以把这个时间稍微设置大一点...(过大恐怕也不行): max_execution_time = 30 (秒).
先要了解 Upload默认的 $config, 才能有意识的去配置自己的上传config.其中,
- maxSize =>0 , 表示没有限制. 但是要受 php.ini中的 upload_max_filesize的限制;
- exts => array(), 默认的扩展名限制, 默认的是空数组, 表示对上传文件的类型,扩展名没有做要求, 这个在linux下恐怕行不行?
- 保存的子目录: autoSub => true; subName => array('date', 'Y-m-d');(相对较好的是'Ymd', 则子目录中没有分割线, 连线).
- 如果用 saveName= '', 企图保持为原来的文件名时, 会出错?跟手册不一致, 可能是因为文件名为空, 无法保存文件, 而使上传出错...,所以还是不要用空字符串. ** 而实际上使用uniqid来命名也是可以接受的, 没有必要一定要保持为原来的文件名.**
- 对于管理每天上传的文章之类的子目录, 采用按日期来命名子目录是可以的, 但是对于你想自己分类的文件/如图片等, 则需要自己命名子目录的名字...
- 上传文件域, 为什么要给一个name呢? 因为在$_FILES, $info中, 就是通过客户端文件域的名字来区分是哪个上传文件的, $_FILES的key就是文件域的name!
着重区分 rootPath和 savePath的含义:
-
默认的保存文件的根路径是 rootPath => './Uploads/', 这里的 ./是相对于web的根路径,就是www的路径;
这里特别要注意的是, rootPath的路径一定要以 斜杠结尾, 否则后面的子 目录 名称, 将会和前面的 rootPath进在一起 -
而 savePath的路径是相对于 rootPath的 路径, 如: rootPath = './Public/',那么会在上面的/Uploads下再创建一个Public目录, 来保存上传文件, 而不是 直接的在/www下传人Public目录.
-
也就是, 最后的上传保存路径是: serverName/Uploads/Public/Y-m-d/[上传的文件名].., 实际上serverName/Public下是没有上传文件的!
-
也就是说, 最后, 真实的保存路径是: serverName/'rootPath'/'savePath'/
upload方法返回的, 不一定总是数组, 也可能是因为上传失败时返回的false, 即: funciton upload()
默认的路径: ./Uploads, 注意这个点是针对哪里呢? 是针对web的根路径 _ROOT _.
模板中的__URL__
, 指的是当前的脚本地址, 如果是 action="__URL__/upload"
,则是指的当前控制器中的方法.
要区别\(info和\)_FILES的区别:
$_FILES是指 关于上传文件的信息组成的 数组 array(fileinfo1, fileinfo2, file3info), 不是文件本身组成的数组,不是文件数组array(file1, file2, file3...);
另外, $info的key成员, 也要比 $_FILES的key更多.
另外, $upload->maxSize = 3M =310241024, 单位是Byte, 是按1024 为单位来计算的.
ucfirst和lcfirst, ucwords, lcwords?
ucfirst: upper capital char;
lcfirst: lower capital char;
ucwords work similarly, but there is not "lcwords" function!
basename和dirname...
在linux的终端中, 要给某个变量赋值, 一定要使等号紧挨着变量, 即变量和等号之间不能有空格, 因为空格会被认为是单词的分割符, 会把变量和 等号看作是命令名, 从而报错 "command not found".
在linux的命令中, 单双引号都表示字符串, 而反引号, 则表示中间也是一个命令, 执行命令后, 把结果作为操作数. 如: test=反引号basename ./index.php .php反引号
basename本身就是 linux 终端下的一个命令, 表示获取文件名(去掉路径), 或 去掉扩展名后的 文件名.如: 反引号basename ./index.php, 或 basename ./index.php .php反引号
因此, php借鉴了 linux下的basename, 有了basename函数, 函数的用法跟 basename的命令用法一致: basename($path, [$suffix])... 如果加上扩展名参数, 则只是返回纯粹的文件名
uniqid: 是基于 以微秒计的 当前时间生成的 唯一id. 但并不是 直接用当前时间 来作id的. 精确的事实是: 以微秒为单位的当前时间 *2 的20次方, 然后把结果转换成16进制数的结果, 所以 最后 uniqid 总是 13位长度的 16进制数字. 如: 3233a3789b5ef ,
为了避免在高并发情况下 ,(在同一微秒内, 产生两个id, 则是相同的), 可以使用以下解决方法:
- 使用第一个参数, 作生成的id的前缀: uniqid(rand());
- 连接一个随机数, 如: uniquid(). rand(1,10000);
- 更严格的是, 使用md5. md5(uniqid()); 或 md5(uniqid(rand()));
md5: 严格的是,不叫 加密, 而是一种算法, 一种散列算法, 标准生成的md5字符串是 128 位16进制字符串的. 实际使用时, 由于字符串太长, 存储和使用都不方便, 在普通强度的安全要求下, 常使用 截取标准长度中的 16位, 24, 32 , 64位等. 当然你也可以自己 定义 去取 多少位, 取哪些位都 是可以的!
time()是真正获取系统的时间戳, 而date是一个格式化函数,从时间戳得到日期和是间.
time()只精确到秒, 后面的部分直接丢弃, 或四舍五入. microtime()精确到微秒, 返回一个字符串, 分成两个部分, 一个是秒后面的 微秒数, 一个是秒数,两部分加起来才是现在的时间戳. 通常用exlopde函数来处理: \(arr=explode(microtime()), usec=\)arr[0], sec=$arr[1]. 注意, 两部分都是用秒作单位.
将time()+microtime()加起来 正好是当前的时间. 字符串相加用点号, 如果用加号, 就表示是转换成 数字 后再相加.
要灵活的使用/看待函数的参数, 特别是需要一个boolean类型的参数时, 只要给他一个 参数输入, 不一定就直接输入true, false, 可以输入一个表达式, 只要这个表达式的值是一个 boolean 类型的值就可以了! 比如上面的 microtime(get_as_float), 默认的是false, 作为字符串的方式返回.
特殊的: 三元运算符的主要使用地方: 一个是赋值, 另外一个是: 作为return 结果直接返回. 即要 返回一个值的时候, 如果要判断情况来返回不同的值时, 就使用三元运算符, 这个是最常见的了, 可以大大精简代码!这个需要牢固掌握!
对于数组变量, 我们通常是输入具体的树值来初始化, 实际上, 你也可以使用 变量 来初始化数组, 直接把变量写在数组中: 如: $info=array($files);
文件上传专题:
利用thinkphp开发时, 应该遵守推荐的命名规范.对于函数和方法, 只有全局的函数, 即app/Common/Common/function.php中的函数, 才采用小写字母加下划线的方式, 而对于类里面的函数方法和成员变量, 则是采用的 首字母小写的驼峰命名法. 私有的采用单下划线, 魔术函数采用双下划线...
从编辑模式退出到 普通模式, 使用的时 ctrl+[, 而不是 ], 所以不要 向右移动手指太多, 以至于"很疑惑?".
在php函数中, 使用echo等输出函数, 输出 html标签和实体符号的时候, 可以 只使用单引号, 因为输出到html时, 单引号即使是 按原样输出, 那么在html页面文件中, 也是html标签和实体符号, 所以也是可以生效的, 你去看它的source page就知道了!
__URL__
是当前文件 所在的目录, 在作链接时, 可以使用这个 模板 替换变量.
a标签的目标是: target=_blank, _self 等等.
PHP的数组统计函数有 : count, 它等于 sizeof, 要统计数组中, 值value的个数分布, 使用 array_count_values 函数.
开发php代码时候,为了代码效率,不一定完全按照 漂亮的代码规范来写,只要大的东西遵守规范就可以了,如函数内部的变量,不必写得很完整复杂(在linux中就把这种各种各样的简写/缩写,发挥到了极致),可以只用一个 单字母来表示就可以了!
0和false的区别?
false是boolean值,而0, 是等于false的, 非 boolean值!在一些函数中, 往往需要传人附加参数true, 来表示限定参加操作的参数之间不仅要比较(相等)值,而且要比较类型!
为什么写在head中的文本内容也会输出?
可以从两个方面来理解这个问题:
1 html只是标签, 对内容进行描述, 告诉浏览器标签中的内容是作什么的, 应该怎样去解析它. 实际上, 你可以把web页面看作是 普通的文档, 如记事本一样的文档, 没有用标签描述的内容, 就像是普通内容, 按原样输出就行.
2 浏览器 的容错机制, 就是 凡是没有放在 body ~ endbody之间的内容, 以及没有放在标签内的内容, 都可以容错, 把它们看成是body中的内容. 这个是利用了浏览器的容错功能, 来实现的, 比如google的代码, 它就没有</body> </html>
结束标签. 比如某宝, 它的script脚本是放在 </body>之后, </html>之前
3 虽然linux对文件的扩展名没有硬性的规定, (所以说, linux文件扩展名没有关系, 那也不是绝对的! ) 但是还是有大量的(应用程序工具)默认扩展名,, 所以为了使用方便, 还是加上约定俗成的扩展名.
但是对于浏览器ff, 它还是根据文件的扩展名来解析的, 如果你不使扩展名为 .html, 那么文件里面的标签 如p, a, h1等标签不会被解析,还是按原样输出. 即使你写上了<html><body> ...
也不会被解析. 所以一定要将扩展名改成 .html
4 对于html文件, 不一定所有的内容都放在body中, 正如第2点所说, 在 调用$this->display()
之前就已经有内容输出了.
为什么php文件不要写 结束符号?
第一, 如果你写上了结束标签, 那么结束标签后的内容, 即使是 空格/tab/回车 都会被作为html实体内容 输出, 这在某些地方如session中就会报错, 而且较难调试, 而你不写结束标签, 那么里面的 所有内容都是作为 php标签内容进行解析的, 没有输出;
第二, 如果写了结束标签, 在某些include 时会有问题. 所以, 为了在被 include 时可以直接使用, 应该在 "真实代码内容结束后" 加上一个空行,即回车, 这样在 include后 再写代码的时候, 就不会将后面的代码与前面的include的代码 在同一行上而出错, 如: .....}public function()....
一个php文件在浏览器的解析过程?
头脑中随时都要有这样的一个概念: 一个php文件 首先要被解析成html的源文件, 然后这个源文件被请求到浏览器, 浏览器引擎再render渲染输出. 所以, 虽然看到php转换成html源文件时, 会有/或者会保留 回车换行, 但是 由于html中的 回车 /换行 是不会被浏览器换行输出的, 所以实际上 php文件 的效果要经过两次转换 后被显示 而决定的!
“空操作”本质意思:一个对象(控制器)调用本身不存在的方法
在OOP里边,对象调用本身不存在方法,处于用户体验比较好的角度考虑,我们可以在类里边制作一个魔术方法:function __call();
空操作有两种解决方案:
在对应的控制器里边制作一个方法,名称为”_empty”,这个控制器的空操作都会自动执行该方法。(推荐使用)
给空操作的名称制作一个同名的模板出来,系统会自动调用