php核心技术与最佳实践知识点(上)

一.基础

1.serialize:序列化一个类,只是保存了类的属性,所以还需要反序列化unserialize的时候包含该类.

2.对于将array转为object,这个转换因为没有具体的类,所以称为了一个孤类:

<?php
$arr = [1,2];
var_dump((object) $arr);

输出
object(stdClass)#1 (2) {
  [0]=>
  int(1)
  [1]=>
  int(2)
}

  

3.其他语言的多态是向上转型,php的多态没有转型,只是调用了不同的派生类.

4.接口是一种契约,但php的接口并不具备约束的能力.

interface Engine
{
    public function run();
}

class Car implements Engine
{
    public function run()
    {
        echo ‘run‘ . PHP_EOL;
    }

    public function fly()
    {
        echo ‘fly‘ . PHP_EOL;
    }

}

function check(Engine $e) {
    $e->fly();
}

$car = new Car();
check($car);

  

我们在函数check中指明传入的参数应该是一个符合Engine的接口约束,但实际上并没有起到这个作用.php只关心传入的对象是否实现了接口中定义的方法,并不关心接口的语义是否正确.

5.为了弥补php缺乏多重继承的缺陷,自php5.4.0起,php引入了Trait,实现代码复用.Trait可以被视为一种加强型的接口

trait HelloWorld {
    public function sayHello() {
        echo ‘Hello World!‘;
    }
}

class TheWorldIsNotEnough {
    use HelloWorld;
}

$o = new TheWorldIsNotEnough();
$o->sayHello();

  

6.反射API:ReflectionClass

7.tokenizer
tokenizer函数提供了一个内嵌在Zend引擎的"PHP tokenizer"的调用接口。使用这些函数,你可以写出你自己的PHP源码分析或者修改工具,而无需处理词法分析级别上的语言规范。

示例代码:
$tokens = token_get_all(‘<?php echo 1; ?>‘);
print_r($tokens);

  

8.php中的错误指脚本运行不正常,异常是业务流程不正常.php中的异常需要手动抛出,意义不是很大.

9.set_error_handler():自定义错误,如果自定义错误,则错误抑制符失效.

function handler($errorNo, $errorStr, $errorFile, $errorLine) {
    die($errorStr);
}
set_error_handler(‘handler‘, E_ALL);

@$a[500];

  

自定义错误和异常想结合的一个例子:

function handler($errorNo, $errorStr, $errorFile, $errorLine) {
    throw new Exception($errorStr, $errorNo);
}

set_error_handler(‘handler‘, E_ALL);

try {
    @$a[500];
} catch (Exception $e) {
    echo $e->getMessage();
}

  

10.捕获致命错误fetal error:register_shutdown_function

function shutdown()
{
    //echo error_get_last();
    echo ‘ok‘;
}

register_shutdown_function(‘shutdown‘);

a;

  

产生致命错误时,会回调shutdown,提供一些补救机会,但程序终止是必然的.

11.语法错误(parse error)处理:计入日志,register_shutdown_function并不会对语法错误进行处理.

php.ini
log_error=on
error_log=/usr/log/php-error.log

  

12.触发错误:trigger_error

<?php
function test() {
    trigger_error(‘手动触发错误‘);
}

test();

  

13.面向对象的一个基本例子:

// domain
class Message
{
    public function setMsg()
    {

    }

    public function getMsg()
    {

    }
}

// model
class MessageModel
{
    // 从数据库读
    public function read()
    {

    }

    // 从数据库写
    public function write(Message $data)
    {

    }

    // 分页
    public function page()
    {

    }
}

// 逻辑层
class LogicMessage
{
    public function write(MessageModel $model, Message $data)
    {
        $model->write($data);
    }

    public function view(MessageModel $model)
    {
        return $model->read();
    }
}

// 控制器
class ActionMessage
{
    public function write(LogicMessage $logicMessage, MessageModel $model, Message $data)
    {
        $logicMessage->write($model, $data);
    }

    public function read(MessageModel $model)
    {
        return $model->read();
    }
}

// 调用
$message = new Message();
$logic = new LogicMessage();
$model = new MessageModel();

$action = new ActionMessage();
$action->write($logic, $model, $message);
$action->read($model);

  

14.ignore_user_abort(true); //用户即便关闭网页,程序在后台执行不会中断.

二.http协议

1.cookie
服务器发给客户端使用:Set-Cookie报头
客户端发给服务器使用Cookie报头

两者区别是Cookie报头的value可以有多个Cookie值,并且不需要指定domain;Set-Cookie只能有一个值,并且需要指明path和domain

2.ip在tcp层传递,因此PHP中的SERVER变量中的HTTP_CLIENT_IP或REMOTE_ADDR,两者是难以伪造的.而HTTP_X_FORWARDED_FOR来自于与http请求中的X FORWARDED FOR报头,而这个报头是可以修改的.

三.cUrl

cUrl中的批处理,异步执行:

$ch1 = curl_init();
$ch2 = curl_init();

curl_setopt($ch1, CURLOPT_URL, ‘http://www.baidu.com‘);
curl_setopt($ch1, CURLOPT_HEADER, 0);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch2, CURLOPT_URL, ‘http://news.baidu.com‘);
curl_setopt($ch2, CURLOPT_HEADER, 0);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1);

$mh = curl_multi_init();

curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);

// 执行批处理
do {
    $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active and $mrc == CURLM_OK) {

    if(curl_multi_select($mh) === -1){
        usleep(100);
    }
    do {
        $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);

}

// 获取内容
$content1 = curl_multi_getcontent($ch1);
$content2 = curl_multi_getcontent($ch2);

// 移除句柄,否则造成死循环
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);

curl_multi_close($mh);

echo $content1;
echo $content2;

  

四.cookie

1.setrawcookie和setcookie的区别是,前者不对值进行urlencode

2.php并没有设置cookie,只是通知浏览器来设置cookie.cookie设置在当前页不会生效,在下一个页面才会生效.

3.cookie是http头的一部分,因此在设置cookie前,不能有输出.

4.每个域名下允许的cookie是有限制的,ie8是50个,firefox是150个

5.一个域名的每个cookie限制大小为4kb

五.session

1.php.ini中的Session设置中的session.save_path="N;MODE;/path"
N:表示目录级数;如为2表示2级目录存放,每一级有0-9和a-z共36个字符作为目录名,2级则可以有36*36个目录
MODE:表示目录权限,默认为600
path:表示存放路径

2.对于设置分级目录存储的session,php不会自动回收,需要自己实现回收机制

3.访问量大的站点,默认的文件session并不适合,可以用数据库或内存缓存

六.基本SQL优化的十个原则

1.避免在列上进行运算,这将使索引失效.
SELECT * FROM table WHERE YEAR(d) > 2017;

优化为
SELECT * FROM table WHERE d > ‘2017-01-01;

2.使用join时,小结果集驱动大结果集,同时把复杂的join查询拆分为多个query.因为join多个表时,导致更多的锁定和阻塞.

内联结时MySQL自动用小结果集驱动大结果集.
左联结和右联结,则需要作出优化

3.避免like的模糊查询
select * from user where username like ‘%u%‘;

优化为:
select * from user where username >= ‘u‘ AND username < ‘v‘;

select * from user where username like ‘u%‘;

4.列出仅需要的字段,这对速度不会有影响,主要考虑节省内存.
select * from user where username >= ‘u‘ AND username < ‘v‘;

优化为
select id from user where username >= ‘u‘ AND username < ‘v‘;

5.使用批量插入,节省交互
insert into table values(‘a‘, ‘b‘, ‘c‘);
insert into table values(‘a‘, ‘b‘, ‘c‘);
insert into table values(‘a‘, ‘b‘, ‘c‘);

优化为:
insert into table values(‘a‘, ‘b‘, ‘c‘),(‘a‘, ‘b‘, ‘c‘),(‘a‘, ‘b‘, ‘c‘);

6.limit基数比较大时使用between
select * from user order by id asc limit 1000000,10

优化为:
select * from user where id between 1000000 and 1000010 order by id asc

但是如果有断行,该项将不适用 .

7.不用使用rand返回随机数据.

8.避免使用NULL,MYSQL难以优化引用了可空列的查询

9.不用使用count(id),而应使用count(*)

10.不要做无谓的排序操作,应尽可能在索引中完成排序.

七.MySQL

1.explain:保证type达到range级别,最好是ref级别,All为全表扫描,这是最坏的情况
2.简单的确定读写比例(R/W):
show global status;

com_select为读,com_update+com_insert为写
如果R/W小于10:1,则认为是以写为主的数据库.

3.MyISAM:适当增加key_buffer_size;可以根据key_cache的命中率进行计算
show global status like ‘key_read%‘;

缓存未命中率:key_cache_miss_rate=Key_reads/Key_read_requests * 100%,如果大于1%就要适当增加key_buffer_size

还要注意table_cache的设置.如果该值过小,mysql就会反复打开,关闭frm文件.如果过大,又会造成cpu的浪费.一个合理的办法是观察opened_tables的值,如果持续增长,就要增加table_cache的值.

4.InnoDB:重点注意innodb_buffer_pool_size;

5.从表中删除大量行时,可运行 optimize table tableName;

八.MySQL模拟消息队列

0:流程:
用户发布一篇文章(insert into article),触发tigger_insert_feed,向feed表插入一条动态,触发tigger_insert_queue,定时器event_push_broadcast每1分钟从queue中提取数据到feed_broadcast.

1.新建user表
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

2.新建friend表
CREATE TABLE `friend` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) DEFAULT NULL,
`fuid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

3.新建feed_broadcast
CREATE TABLE `feed_broadcast` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) DEFAULT NULL,
`title` char(255) DEFAULT NULL,
`is_read` tinyint(4) DEFAULT ‘0‘ COMMENT ‘是否已读‘,
`time` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

4.新建article表
CREATE TABLE `article` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) DEFAULT NULL,
`title` char(255) DEFAULT NULL,
`time` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

建立触发器trigger_insert_feed
create trigger trigger_insert_feed after insert on article for each row
begin
insert into feed(uid,article_id,content,time) values(New.uid, New.id,‘发布了文章‘,New.time);
end

5.新建feed表
CREATE TABLE `feed` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`article_id` int(11) NOT NULL,
`content` varchar(500) NOT NULL,
`time` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

建立触发器trigger_insert_queue
create trigger trigger_insert_queue after insert on feed for each row
begin
insert into queue(uid,feed_id,content,status,time) values(New.uid,New.id,‘发布了文章‘,0,New.time)
end

6.建立queue表:
CREATE TABLE `queue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`feed_id` int(11) NOT NULL,
`content` varchar(500) NOT NULL,
`status` tinyint(4) NOT NULL DEFAULT ‘0‘ COMMENT ‘0未未处理,1为处理‘,
`time` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk

7.创建存储过程push_broadcast:
CREATE DEFINER=`root`@`localhost` PROCEDURE `push_broadcast`()
BEGIN
insert into feed_broadcast(uid,title,time) select ef.fuid,tmp.content,tmp.time from (select * from queue where status=0 order by id desc limit 10) tmp,friend ef where tmp.uid=ef.uid;
update queue set status=1 where status=0 order by id desc limit 10;
END

8.创建一个定时事件event_push_broadcast:
CREATE DEFINER=`root`@`localhost` EVENT `event_push_broadcast` ON SCHEDULE EVERY 1 MINUTE STARTS ‘2017-11-12 17:53:58‘ ON COMPLETION NOT PRESERVE ENABLE DO call push_broadcast()

查看event_scheduler是否是开启状态
show global variables like ‘%sche%‘;

如果event_scheduler为off;
开启:
set global event_scheduler=on;

9.至此可以插入数据做测试了

时间: 2024-10-29 19:06:15

php核心技术与最佳实践知识点(上)的相关文章

PHP核心技术与最佳实践--笔记

<?php error_reporting(E_ALL); /* php 5.3引入 延迟静态绑定 */ /* php5.4引入trait,用来实现多层继承 trait Hello{} trait World{} class MyHelloWorld{ use Hello,World; } */ /* php4时代 php是不支持析构函数的*/ /* php中数组索引是字符串,但是没有使用引号,php就将其认为是一个常量,找不到在视为变量 */ /** * php中的异常必须手动 * 可以结合错

PHP核心技术与最佳实践之Hash算法

PHP核心技术与最佳实践之Hash算法 Hash表又称散列表,通过把关键字Key映射到数组中的一个位置来访问记录,以加快查找速度.这个映射函数称为Hash函数,存放记录的数组称为Hash表. 1.     Hash函数 作用是把任意长度的输入,通过Hash算法变换成固定长度的输出,该输出就是Hash值.这种转换是一种压缩映射,也就是Hash值得空间通常远小于输入的空间,不输入可能会散列成相同的输出,而不可能从Hash值来唯一的确定输入值. 一个好的hash函数应该满足以下条件:每个关键字都可以均

PHP核心技术与最佳实践之Hash表冲突

PHP核心技术与最佳实践之Hash表冲突 接着上一篇文章,测试后输出value1value2.当 $ht->insert('key12','value12'); Echo $ht ->find('key12');时, 发现输出value12value12.这是什么原因呢? 这个问题称为Hash表的冲突.由于insert的是字符串,采用的算法是将字符串的ASIIC码相加,按照此方法,冲突产生了.通过打印key12和key1的Hash值,发现他们都为8,也就说,value1和value12同时被存

PHP核心技术与最佳实践之正则表达式反向引用

PHP核心技术与最佳实践之正则表达式反向引用 反向引用用于重复搜索前面某个分组匹配的文本.例如:"\1"代表分组1匹配的文本: \b(\w+)\b\s+\1\b 要反向引用分组捕获的内容,可以使用"\k<word>"上个例子: \b(?<word>\w+)\b\s+\k<word>\b [示例]:UBB标签代码 UBB标签用来在论坛和留言板中代替HTML,实现一些简单的HTML效果,同时防止滥用HTML出现安全问题. 最终UBB标

PHP核心技术与最佳实践

<PHP核心技术与最佳实践>是一本致力于为希望成为中高级PHP程序员的读者提供高效而有针对性指导的经典著作.系统归纳和深刻解读了PHP开发中的编程思想.底层原理.核心技术.开发技巧.编码规范和最佳实践.全书分为5个部分:第一部分(1-2章)从不同的角度阐述了面向对象软件设计思想的核心概念.技术和原则,分析了面向对象的特性.设计模式的理念,指出了如何设计低耦合.高可扩展性的软件,等等:第二部分(3-6章)详细讲解了PHP中正则表达式的规范和使用技巧,PHP网络编程的原理.方法.技巧和一些重要的操

PHP核心技术与最佳实践之正则表达式匹配规则

PHP核心技术与最佳实践之正则表达式匹配规则 本文介绍几种常用的匹配规则. 1.     字符组 查找数字.字母.空白很简单,因为已经有了对应这些集合的元字符,但是如果匹配没有预定义元字符的字符集合,方法很简单, 就是在方括号内列出它们. 例如:[aeiou]匹配任何一个英文元音字母,[.*?]匹配标点中的一个.注意此时方括号内的元字符失去了特殊意义. 也可以指定字符范围,例如[0-9]的含义和\d完全一致:代表一位数字:同理[a-zA-Z0-9]等同于\w; 字符组很简单,但是一定要弄清楚字符

PHP核心技术与最佳实践之对象的序列化

PHP核心技术与最佳实践之对象的序列化 对象是一堆数据,可以把对象存储起来,以便需要时使用,这就是对象的序列化. 所谓序列化,就是把保存在内存中的各种对象状态(属性)保存起来,并且在需要时可以还原出来.下面代码实现了把内存中的对象当前状态保存到一个文件中. $str = serialize($student); Echo $str; File_put_contents('store.txt',$str); 输出序列化后的结果: O:6:"person":2:{s:4:"nam

PHP核心技术与最佳实践——全局浏览

难得买到并喜欢一本好书,‘PHP核心技术与最佳实践’. 几天时间,先看了个大概,总结一下整体是什么样子的,怎么看怎么学. 1.总共14章: 2.第1.2章讲PHP的OOP: 其中第一章侧重于PHP的OOP与Java等的对比,面对对象开发的概念性问题,PHP的OOP的特殊之处,并对此给出代码例子: 3.第3.4.5章对某一个基础技术应用进行详解: 第3章讲正则表达式(md,为啥我总是看了就忘,这个东西...): 第4章讲网络技术,包括HTTP协议,socket,抓包,cURL,SMTP等应用层应用

温习《PHP 核心技术与最佳实践》这本书

再次看这本书,顺手提炼了一下大致目录,以便后续看见目录就知道大概讲的些什么内容 PHP 核心技术与最佳实践 1.面向对象思想的核心概念 1.1 面向对象的『形』与『本』 1.2 魔术方法的应用 1.2.1 __set和 __get 方法 PHP 的重载和Java 等语言的重载不同. Java 里,重载指一个类中可以定义参数列表不同但名字相同的多个方法.比如,Java 也有构造 函数,只要保证方法签名不一样就行:而 PHP 则在一个类中只允许有一个构造函数. PHP 提供的『重载』指动态的『创建』