-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.json
1 lines (1 loc) · 30 KB
/
content.json
1
[{"title":"从零开始学习go语言","date":"2019-11-09T11:26:05.000Z","path":"2019/11/09/从零开始学习go语言/","text":"看了一段时间的go语法,对go一知半解,go生态感觉慢慢会强大起来","tags":[{"name":"-go","slug":"go","permalink":"http://www.niuhead.com/tags/go/"}]},{"title":"【MySQL学习笔记】 MySQL 建立索引的思路和实例","date":"2018-04-28T15:54:39.000Z","path":"2018/04/28/mysql建立索引/","text":"一、索引的分类1、普通索引2、唯一索引3、全文索引 使用FULLTEXT参数可以设置为全文索引。全文索引只能创建在char,varchar或者 text 类型的字段上。 4、单列索引5、多列索引多列索引是在多个字段上建立一个索引,也叫联合索引。该索引指向创建时对应的多个字段,可以通过这几个字段进行查询。但是,只有查询条件中使用了这些字段中的第一个字段时,索引才会被使用。例如,在表中对id,name,sex字段上建立索引,那么,只有查询条件使用了id字段是,该索引才会被使用。 6、空间索引二、创建索引的原则为了使索引的使用效率更高,在创建索引时,必须考虑在那些字段上创建索引和创建什么类型的索引。下面来说一下索引的设计原则。 1、选择唯一性索引 唯一索引的值是唯一的,可以更快速的通过索引来确定某条记录。例如学生学号是具有唯一性的,往该字段建立唯一索引可以快速的确定某个学生的信息。如果使用姓名的话,可能存在同名的现象,从而降低查询速度。 2、为经常需要排序、分组和联合操作的字段建立索引 经常需要 order by、group by、DIST 和 UNION 等操作的字段,排序操作会浪费很多时间。如果围棋建立索引,可以有效的避免排序操作。 3、为常作为查询条件的字段建立索引 如果某个字段经常用来当做查询条件,那么该字段的查询速度会影响整个表的查询速度。因此,为这样的字段建立索引,可以提高整个表的查询速度。 4、限制索引的数目 索引的数目不是越多越好。每个索引都需要占磁盘空间,索引越多,需要的磁盘空间就越大。修改表时,对索引的重构和更新很麻烦。越多的索引,会使用更新表变得很浪费时间。 5、尽量使用数据量少的索引 如果索引的值很长,那么查询的速度会受到影响。例如,对一个char(100)类型的字段进行全文检索所需要的时间肯定要对比char(10)的类型的字段需要的时间要多。 6、尽量使用前缀来索引 如果索引的字段的值很长,最好使用值的前缀来索引。例如,text 和 Blog类型的字段,进行全文检索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索的速度。 7、删除不再使用的或者少使用的索引 表中的数据被大量更新,或者数据的使用方式改变后,原有的一些索引可能不再需要,可以将其删除,从而减少索引对更新操作的影响。 三、创建表时建立索引1、创建普通索引123456create table table_name( id int(11), name varchar(20), sex boolean, INDEX(id)); 查看表结构1show create table table_name; 可以使 EXPLAIN 语句查看索引是否被使用1explain select * from table_name where id = 1\\G 2、创建唯一索引12345create table index2( id int unique, name varchar(20), unique INDEX index_2(id asc)); 3、创建全文索引全文索引只能在char,varchar或者text 类型的字段上。而且,只有MyISAM 储存引擎支持全文索引。 12345create table idnex3( id int, info varchar(20), FULLTEXT INDEX index3_info(info))ENGINE=MyISAM; 4、创建单列索引12345create table index4( id int, subject varchar(255), index index4_st(subject(10))); 这里需要注意的,subject 的长度为255,但是index4_st索引只有10。这样做的目的还是为了提高查询速度。对于字符型的数据,可以不用查询全部信息,只查询其前面的若干字符信息。 5、创建多列索引123456create table index5( id int, name varchar(20), sex char(4), index index5_ns(name.sex)); 这是我们可以看到,name 和sex字段上已经创建了index_ns索引。 下面我们来用explain 来看看索引情况; 123456789101112131415161718mysql> explain select * from index5 where name = '22'\\G;*************************** 1. row *************************** id: 1 select_type: SIMPLE table: index5 partitions: NULL type: refpossible_keys: index5_ns key: index5_ns key_len: 63 ref: const rows: 1 filtered: 100.00 Extra: NULL1 row in set, 1 warning (0.00 sec)ERROR: No query specified 再看一条 123456789101112131415161718mysql> explain select * from index5 where sex = '22' \\G;*************************** 1. row *************************** id: 1 select_type: SIMPLE table: index5 partitions: NULL type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1 filtered: 100.00 Extra: Using where1 row in set, 1 warning (0.00 sec)ERROR: No query specified 我们发现: 在多列索引中,只有查询条件中使用了这些字段中的第一个字段时,才会被索引。 四、在已经存在的表中创建索引1、创建普通索引在example0() 表中的id 创建名为index7_id 的索引。 1create index index7_id on example0(id); 2、创建唯一索引1create UNIQUE index index8_name on index8(name); 3、创建全文索引1create FULLTEXT index index9_info on index9(info); 4、创建单列索引12create INDEX index_name ON index4(name(10)); 5、创建多列索引1create INDEX index_name ON table_name(name,sex); 五、用alter table 语句来创建索引1、创建普通索引在name字段上创建名为indx_name 的索引1alter table table_name ADD INDEX index_name(name(20)); 2、创建唯一性索引1alter table table_name ADD UNIQUE INDEX index_name(id); 3、创建全文索引1alter table table_name ADD FULLTEXT INDEX index_name(info); 4、创建单列索引1alter table table_name ADD INDEX index_name(name(4)); 5、创建多列索引1alter tabel table_name ADD INDEX index_name(name.sex); 六、删除索引1DROP INDEX index_name ON table_name;","tags":[]},{"title":"sql 会引起全表扫码的语句","date":"2018-04-18T15:10:15.000Z","path":"2018/04/18/sql会引起全表扫码的语句/","text":"1、模糊查询效率很低:like % ... % //会全表扫描 like %... //会全表扫描 like ...% //这种之前建立的索引会起作用 2、查询条件中含有is null的select语句执行慢is not null 时永远不会使用索引。一般数据量大的表不要用is null查询。 3、查询条件中使用了不等于操作符(<>、!=)的select语句执行慢原因:SQL中,不等于操作符会限制索引,引起全表扫描,即使比较的字段上有索引解决方法:通过把不等于操作符改成or,可以使用索引,避免全表扫描。例如,把column<>’aaa’,改成column<’aaa’ or column>’aaa’,就可以使用索引了。 4、or语句使用不当会引起全表扫描原因:where子句中比较的两个条件,一个有索引,一个没索引,使用or则会引起全表扫描。例如:where A=:1 or B=:2,A上有索引,B上没索引,则比较B=:2时会重新开始全表扫描。","tags":[{"name":"MySQL","slug":"MySQL","permalink":"http://www.niuhead.com/tags/MySQL/"}]},{"title":"php基础总结","date":"2018-04-16T15:14:07.000Z","path":"2018/04/16/高级php总结/","text":"一、常用魔术方法的触发时机?1) autoload() :当程序实例化某个类,而该类没有在当前文件中被引入。此时会触发执行autoload()。程序希望通过该方法,自动引入这个类文件。该方法有一个参数,即就是那个忘记引入的类的名称。autoload()方法的工作原理是什么?当程序执行到实例化某个类的时候,如果在实例化前没有引入这个类文件,那么就自动执行autoload()函数。这个函数会根据实例化的类的名称来查找这个类文件的路径,当判断这个类文件路径下确实存在这个类文件后,就执行include或者require来载入该类,然后程序继续执行,如果这个路径下不存在该文件时就提示错误。使用自动载入的魔术函数可以不必要写很多个include或者require函数。 2) __construct() :这个是魔术构造方法。构造方法是实例化对象的时候自动执行的方法,作用就是初始化对象。该方法可以没有参数,也可以有多个参数。如果有参数,那么new这个对象的时候要记得写上相应的参数。在php5以前,没有魔术构造方法,普通构造方法是一个跟类名同名的方法来实现构造的。如果一个类中既写了魔术构造方法,又定义了普通构造方法。那么php5以上版本中,魔术方法起作用,普通构造方法不起作用。反之,在php5以前版本中,不认识魔术构造方法,只是把该方法当做普通的方法。 3) __destruct() :这个是魔术析构方法。析构方法的作用和构造方法正好相反,是对象被销毁时被自动调用的,作用是释放内存。析构方法没有参数。 4) call() :当程序调用一个不存在或不可见的成员方法时,自动触发执行call()。它有两个参数,分别是未访问到的方法名称和方法的参数。而第二个参数是数组类型。 5) get() :当程序调用一个未定义或不可见的成员属性时,自动触发执行get()。它有一个参数,表示要调用的属性的名称。 6) set():当程序试图写入一个不存在或不可见的成员属性时,PHP就会自动执行set()。它包含两个参数,分别表示属性名称和属性值。 7) tostring() :当程序使用echo或print输出对象时,会自动调用该方法。目的是希望通过该方法将对象转化为字符串,再输出。tostring() 无参数,但是该方法必须有返回值。 8) clone() :当程序clone一个对象的时候,能触发clone()方法,程序希望通过这个魔术方法实现:不仅仅单纯地克隆对象,还需要克隆出来的对象拥有原来对象的所有属性和方法。 二、$this,self::, parent::,static:: 使用场景$this代表的是当前对象 self代表的是当前的类 parent代表的是当前类的父类 使用场合:$this只能使用在当前类中,通过$this->可以调用当前类中的属性和方法;self只能在当前类中使用,通过作用域操作符::访问当前类中的类常量、当前类中的静态属性、当前类中的方法;parent只能使用在有父类的当前类中,通过作用域操作符::访问父类中的类常量、父类中的静态属性、父类中的方法 后期静态绑定 自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。 准确说,后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)的类名。当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧部分);当进行非静态方法调用时,即为该对象所属的类。所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。可用 get_called_class() 函数来得到被调用的方法所在的类名,static:: 则指出了其范围。 该功能从语言内部角度考虑被命名为“后期静态绑定”。“后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。self:: 的限制 使用 self:: 或者 CLASS 对当前类的静态引用,取决于定义当前方法所在的类: Example #1 self:: 用法 代码实例 12345678910111213141516171819<?phpclass A { public static function who() { echo __CLASS__; } public static function test() { self::who(); }}class B extends A { public static function who() { echo __CLASS__; }}B::test();?> 以上例程会输出: A 后期静态绑定的用法 后期静态绑定本想通过引入一个新的关键字表示运行时最初调用的类来绕过限制。简单地说,这个关键字能够让你在上述例子中调用 test() 时引用的类是 B 而不是 A。最终决定不引入新的关键字,而是使用已经预留的 static 关键字。 Example #2 static:: 简单用法 123456789101112131415161718<?phpclass A { public static function who() { echo __CLASS__; } public static function test() { static::who(); // 后期静态绑定从这里开始 }}class B extends A { public static function who() { echo __CLASS__; }}B::test();?> 以上例程会输出: BNote: 在非静态环境下,所调用的类即为该对象实例所属的类。由于 $this-> 会在同一作用范围内尝试调用私有方法,而 static:: 则可能给出不同结果。另一个区别是 static:: 只能用于静态属性。 Example #3 非静态环境下使用 static::123456789101112131415161718192021222324252627<?phpclass A { private function foo() { echo \"success!\\n\"; } public function test() { $this->foo(); static::foo(); }}class B extends A { /* foo() will be copied to B, hence its scope will still be A and * the call be successful */}class C extends A { private function foo() { /* original method is replaced; the scope of the new one is C */ }}$b = new B();$b->test();$c = new C();$c->test(); //fails?> 以上例程会输出: success!success!success! Fatal error: Call to private method C::foo() from context ‘A’ in /tmp/test.php on line 9 Note: 后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。另一方面,如果静态调用使用 parent:: 或者 self:: 将转发调用信息。 Example #4 转发和非转发调用 <?php class A { public static function foo() { static::who(); } public static function who() { echo __CLASS__.\"\\n\"; } } class B extends A { public static function test() { A::foo(); parent::foo(); self::foo(); } public static function who() { echo __CLASS__.\"\\n\"; } } class C extends B { public static function who() { echo __CLASS__.\"\\n\"; } } C::test(); ?> 以上例程会输出: ACC 参考博客:http://php.net/manual/zh/language.oop5.static.php https://www.cnblogs.com/jerrypro/p/6422923.html","tags":[]},{"title":"正则学习笔记","date":"2018-04-16T06:46:45.000Z","path":"2018/04/16/正则学习笔记/","text":"正则表达式的基本知识汇总行定位符(^与$)“^” 表示以什么开头 eg: /^de“&” 表示以什么结尾 eg: de$/","tags":[]},{"title":"常见的一些算法","date":"2018-04-13T10:16:59.000Z","path":"2018/04/13/常见的一些算法/","text":"算法题1、遍历出一个文件夹下的所有文件和文件夹 123456789101112131415function my_scandir($dir){ //定义文件输出的变量 $files = []; if($handle = opendir($dir)){ //是否有权限打开 while(( $file = readdir($handle)) !== false ){ if(is_dir($dir.'/'.file)){ $files[$file] = my_scandir($dir.'/'.file) }else{ $files[] = $file; } } closedir($dir); return $diles; }} 2、写一个函数是不是回文字符串 1234567891011121314151617181920212223function ishuiwen($string){ //将字符串转化成数组 $stra = str_split($string); //逆序输出数组array_reverse $strb=array_reverse($stra); //判断两数组是否相等,相等为回文 for($i=0;$i<count($stra);$i++){ if($stra[$i]!=$strb[$i]){ return 1; break; } } return 2;}$string=\"abc12363211cba\";$res = ishuiwen($string);if($res==2){ echo \"YES\";}else{ echo \"NO!\";} 概念题抽象类和接口的概念以及区别?抽象类:它是一种特殊的,不能被实例化的类,只能作为其他类的父类使用。使用abstract关键字声明。 它是一种特殊的抽象类,也是一个特殊的类,使用interface声明。 抽象方法:在方法前面有abstract,而且方法没有方法体,连“{ }”也不能有 (1)抽象类的操作通过继承关键字extends实现,而接口的使用是通过implements关键字来实现。 (2)抽象类中有数据成员,可以实现数据的封装,但是接口没有数据成员。 (3)抽象类中可以有构造方法,但是接口没有构造方法。 (4)抽象类的方法可以通过private、protected、public关键字修饰(抽象方法不能是private),而接口中的方法只能使用public关键字修饰。 (5)一个类只能继承于一个抽象类,而一个类可以同时实现多个接口。 (6)抽象类中可以有成员方法的实现代码,而接口中不可以有成员方法的实现代码 __autoload()方法的工作原理是什么?使用这个魔术函数的基本条件是类文件的文件名要和类的名字保持一致。 当程序执行到实例化某个类的时候,如果在实例化前没有引入这个类文件,那么就自动执行__autoload()函数。 这个函数会根据实例化的类的名称来查找这个类文件的路径,当判断这个类文件路径下确实存在这个类文件后 就执行include或者require来载入该类,然后程序继续执行,如果这个路径下不存在该文件时就提示错误。 使用自动载入的魔术函数可以不必要写很多个include或者require函数。","tags":[]},{"title":"Linux 的几个常用的命令","date":"2017-12-05T03:01:01.000Z","path":"2017/12/05/Linux 常用的机构命令/","text":"给某个文件权限(以后有时间总结一篇关于权限的文章)1chown -R www:www /home/wwwroot 查看链接服务器的ip12netstat -an | grep ESTABLISHEDnetstat -an | grep 192.168.1.99 centos7 开启80端口1iptables -I INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT telnet 某个端口1telnet 172.0.0.101 8001 退出1ctrl + ] 然后 quit 注意,后面没有 ‘;’分号 统计80端口链接数1netstat -nat|grep -i \"80\"|wc -l 查看磁盘io1iostat -d -k 1 10 参数 -d 表示,显示设备(磁盘)使用状态;-k某些使用block为单位的列强制使用Kilobytes为单位;1 10表示,数据显示每隔1秒刷新一次,共显示10次","tags":[{"name":"Linux","slug":"Linux","permalink":"http://www.niuhead.com/tags/Linux/"}]},{"title":"搭建shadowsoks服务器","date":"2017-12-05T03:01:01.000Z","path":"2017/12/05/搭建shadowsoks服务器/","text":"安装 shadowsoksR,Shadowsocks的一个分支,比较不错。但是默认是 aes-256-cfb 加密,如果需要 chacha20 加密,需要手动切换。 123wget --no-check-certificate https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocksR.shchmod +x shadowsocksR.sh./shadowsocksR.sh 2>&1 | tee shadowsocksR.log 安装 shadowsocks-go版本,据说有buff,比python版Shadowsocks要快: 123wget --no-check-certificate https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocks-go.shchmod +x shadowsocks-go.sh./shadowsocks-go.sh 2>&1 | tee shadowsocks-go.log 服务器传送门 win客户端传送门 Ubuntu客户端传送门","tags":[{"name":"Linux","slug":"Linux","permalink":"http://www.niuhead.com/tags/Linux/"}]},{"title":"jqweui loading 如何显示","date":"2017-11-30T05:03:09.000Z","path":"2017/11/30/jqweui_toast/","text":"首先吐槽一下 jqweui的官方手册,有的地方确实不是太完善。不过现在做小程序的应该用官方的weui了。 toast 在jqweui 的手册中,只有下面几个方法(http://jqweui.com/components#toast )。 12345$.toast(\"取消操作\", \"cancel\");$.toast(\"禁止操作\", \"forbidden\");$.toast(\"纯文本\", \"text\");// 第二个参数可以是时间,单位毫秒$.toast(\"消息\", 20000); 但是右边的正在加载样式,手册中怎么也找不到。百度了一遍,解决方案几乎千篇一律的是自己用jqweui的样式自己封装。无赖只能F12 找到对应的按钮后,发现官方有现成的方法可以调用。 展示正在加载中页面1$.showLoading(\"开门中...\"); 关闭正在加载中页面 1$.hideLoading(); ok,完美解决。","tags":[{"name":"jqweui","slug":"jqweui","permalink":"http://www.niuhead.com/tags/jqweui/"},{"name":"weui'","slug":"weui","permalink":"http://www.niuhead.com/tags/weui/"}]},{"title":"Ubuntu17.04+github+hexo 搭建博客","date":"2017-11-11T07:22:58.000Z","path":"2017/11/11/Ubuntu17.04+github+hexo 搭建博客/","text":"第一步: 首先安装nodejs,这个是hexo运行的基础环境,安装很简便:1$ sudo apt-get install nodejs 第二步 安装npm,这个也很简单,这是是node.js的包管理器,跟apt,pip等差不多的东东, 直接1$ sudo apt-get install npm 第三步接下来安装hexo或者hexo-cli,后者安装出现问题,前者没有问题,暂时还不知道原因.所以我安装的是hexo,如果你使用sudo npm install hexo -g 或者 sudo npm install hexo-cli -g,是不会成功的,最起码我是这样的。正确的方法如下:1$ sudo npm install --unsafe-perm --verbose -g hexo 第四步修改以下hexo所在路径的文件1$ sudo vi /usr/local/lib/node_modules/hexo/bin/hexo 把#!/usr/bin/env node修改为!/usr/bin/env nodejs即可 123#!/usr/bin/env nodejs'use strict';require('hexo-cli')(); 然后输入hexo 看是否安装成功 第五步创建项目: 12345$ mkdir blog$ cd blog$ hexo init$ hexo g # 生成$ hexo s # 启动服务 然后输入127.0.0.1:4000 就可以预览了 第六步上传到github 首先在github 建造一个 youname(自己的github名字).github.io 在项目文件下安装插件 1npm install hexo-deployer-git --save 在__config.yml中加入 1234deploy: type: git repository: [email protected]:youname/youmane.github.io.git branch: master 然后进入blog 文件 12$ hexo g$ hexo d 就可以上传到github了。然后youname.github.io 就可以访问到blog了","tags":[{"name":"github","slug":"github","permalink":"http://www.niuhead.com/tags/github/"},{"name":"hexo","slug":"hexo","permalink":"http://www.niuhead.com/tags/hexo/"}]},{"title":"《高性能MySQL》笔记 - MySQL 锁的基本类型","date":"2017-10-06T07:53:58.000Z","path":"2017/10/06/mysql-lock/","text":"MySQL 主要在两个层面上实现并发控制:服务器层和存储引擎层。当读写有冲突的时候,一般对于MySQL来说,是进行锁表操作的。 读写锁读锁:读锁是共享的,多个用户同一时刻读取同一资源,他们之前互不影响。 写锁:写锁则是排他的,也就是说一个写锁会阻塞其他的写锁和读锁,这是出于安全策略的考虑,只有这样,才能确保在给定的时间里,只有一个用户能执行写入,并防止其他用户读取正在写入的同一资源。 锁粒度一种提高共享资源的并发性的方式就是让锁定的对象更有选择性。尽量只锁定需要修改的部分数据,而不是所有资源。更加理想的方式是,只对会修改的数据片进行精确的锁定。任何时候,在给定的资源上,锁定的数据量越少,则系统的并发程度越高,只要相互之间不发生冲突即可。 但是,所有的锁都是需要消耗资源的。锁的各种操作,包括获得锁,检查锁是否已经解除,释放锁等,都会增加系统的开销。 这里我们可以意识到:所谓的锁策略,是在锁的开销和数据的安全之间寻求平衡,这种平衡会影响到性能。 表锁表锁是MySQL中的基本策略,并且是开销最小的策略。当一个用户在对表进行操作(CUD)前,需要先获得写锁,这会阻塞其他用户对该表的所有操作。只有没有写锁时,其他读取用户才能获得读锁,读锁之间互不阻塞。 行锁行级锁可以最大程度的支持并发处理(同时也带来了最大的锁开销)。","tags":[{"name":"MySQl","slug":"MySQl","permalink":"http://www.niuhead.com/tags/MySQl/"},{"name":"高并发","slug":"高并发","permalink":"http://www.niuhead.com/tags/高并发/"},{"name":"数据库锁","slug":"数据库锁","permalink":"http://www.niuhead.com/tags/数据库锁/"}]},{"title":"写在开头","date":"2017-10-05T07:22:28.000Z","path":"2017/10/05/hello-world/","text":"嗯,作为一个coder,早就有打算做一个博客的的想法,今天用github+hexo搭建这个blog,基本上还算顺利!以后的日子里,会将工作中遇到的一些问题解决的方案记录在这里。由于一些客观原因,有的解决方案会有些缺陷,欢迎PR! 嗯,今天是blog可以访问的第一天,也算是自己的一个小小的成就。目前的想法是blog的内容主要有 PHP,MySQL,Linux(简单的运维知识),以及会有一些python的东西。","tags":[]},{"title":"如何优雅的使用接口","date":"2017-06-02T07:22:28.000Z","path":"2017/06/02/interface/","text":"嗯,6.1刚过完,我们不在是宝宝了,来吧,撸一篇接口的文章(interface). 在编程的过程中我们应该学会如何使用接口来给变我们的生活,极大的提升自我能力。接口不是新特性,但是非常重要,下面我们来撸个接口的小例子。 虚构一个DocumentStore的类,这个类负责从不同的资源收集文本。可以从远程url读取html,也可以读取资源,也可以收集终端命令输出。 定义DocumentStore类 1234567891011121314class DocumentStore{ protected $data = []; public function addDocument(Documenttable $document){ $key = $document->getId(); $value = $document->getContent(); $this->data[key] = $value; } public function getDocuments(){ return $this->data; } } 既然addDocument()方法的参数只能是Documenttable的类的实例,这样定义DocumentStore的类怎么行呢? 其实Documenttable不是类,是接口; 定义Documenttable 123456interface Documenttable{ public function getId(); public function getContent(); } 这个接口定义表名,实现Documenttable接口的任何对象都必须提供一个公开的getId()方法和一个公开的getContent()方法。 可是这么做有什么用呢?这么做的好处就是,我们可以分开定义获取稳定的类,而且能使用十分不同的方法。下面是一种实现方式,这种方式使用curl从远程url获取html。 定义HtmlDocument类 123456789101112131415161718192021222324class HtmlDocument implements Documenttable{ protected $url; public function __construct($url) { $this->url = $url; } public function getId(){ return $this->url; } public function getContent(){ $ch = curl_init(); curl_setopt($ch,CURLOPT_URL,$this->url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,3); curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1); curl_setopt($ch,CURLOPT_MAXREDIRS,3); curl_close($ch); return $thml; }} 下面一个方法是获取流资源。 123456789101112131415161718192021222324class StreamDocument implements Documenttable{ protected $resource; protected $buffer; public function __construct($resource,$buffer = 4096) { $this->resource=$resource; $this->buffer=$buffer; } public function getId(){ return 'resource-' .(int)$this->resource; } public function getContent(){ $streamContent = ''; rewind($this->resource); while (feof($this->resource) === false){ $streamContent .= fread($this->resource,$this->buffer); } return $streamContent; }} 下面一个类是获取终端命令行的执行结果。 12345678910111213141516class CommandOutDocument implements Documenttable{ protected $command; public function __construct($command) { $this->command=$command; } public function getId(){ return $this->command; } public function getContent(){ return shell_exec($this->command); }} 下面我们来演示一下借助上面的三个类来实现DocumentStore类。 123456789101112131415161718192021$documentStore = new DocumentStore();//添加html文档$htmlDoc = new HtmlDocument('https:// www.i360.me');$documentStore->addDocument($htmlDoc);//添加流文档$streamDOC = new StreamDocument(fopen('stream.txt','rb'));$documentStore->addDocument($streamDOC);//添加终端命令文档$cmdDoc = new CommandOutDocument('cat /etc/hosts');$documentStore->addDocument($command);print_r($documentStore->getDocuments());die; 这里HtmlDocument,StreamDocument,CommandOutDocument这三个类没有任何共同点,只是实现了同一个接口。","tags":[{"name":"接口","slug":"接口","permalink":"http://www.niuhead.com/tags/接口/"},{"name":"设计模式","slug":"设计模式","permalink":"http://www.niuhead.com/tags/设计模式/"}]},{"title":"php 生僻知识点","date":"2015-04-05T07:22:28.000Z","path":"2015/04/05/php学习笔记/","text":"类名前加’\\’ 与不加的区别Example #1 在命名空间中访问全局类123456789<?phpnamespace A\\B\\C;class Exception extends \\Exception {}$a = new Exception('hi'); // $a 是类 A\\B\\C\\Exception 的一个对象$b = new \\Exception('hi'); // $b 是类 Exception 的一个对象$c = new ArrayObject; // 致命错误, 找不到 A\\B\\C\\ArrayObject 类?> Example #2 命名空间中后备的全局函数/常量1234567891011121314151617181920<?phpnamespace A\\B\\C;const E_ERROR = 45;function strlen($str){ return \\strlen($str) - 1;}echo E_ERROR, \"\\n\"; // 输出 \"45\"echo INI_ALL, \"\\n\"; // 输出 \"7\" - 使用全局常量 INI_ALLecho strlen('hi'), \"\\n\"; // 输出 \"1\"if (is_array('hi')) { // 输出 \"is not array\" echo \"is array\\n\";} else { echo \"is not array\\n\";}?> 英文字母和中文汉字在不同字符集编码下的字节数英文字母: 字节数 : 1;编码:GB2312 字节数 : 1;编码:GBK 字节数 : 1;编码:GB18030 字节数 : 1;编码:ISO-8859-1 字节数 : 1;编码:UTF-8 字节数 : 4;编码:UTF-16 字节数 : 2;编码:UTF-16BE 字节数 : 2;编码:UTF-16LE 中文汉字: 字节数 : 2;编码:GB2312 字节数 : 2;编码:GBK 字节数 : 2;编码:GB18030 字节数 : 1;编码:ISO-8859-1 字节数 : 3;编码:UTF-8 字节数 : 4;编码:UTF-16 字节数 : 2;编码:UTF-16BE 字节数 : 2;编码:UTF-16LE","tags":[]}]