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或env变量中的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.至此可以插入数据做测试了
php核心技术与最佳实践知识点(上)的更多相关文章
- php核心技术与最佳实践知识点(下)
九.缓存 1.缓存三大要素:命中率, 缓存更新策略,缓存最大数据量 2.命中率(mysql为例):mysql提供了一系列的query cache的global status来提现数据库缓存的情况: s ...
- PHP核心技术与最佳实践——全局浏览
难得买到并喜欢一本好书,‘PHP核心技术与最佳实践’. 几天时间,先看了个大概,总结一下整体是什么样子的,怎么看怎么学. 1.总共14章: 2.第1.2章讲PHP的OOP: 其中第一章侧重于PHP的O ...
- 温习《PHP 核心技术与最佳实践》这本书
再次看这本书,顺手提炼了一下大致目录,以便后续看见目录就知道大概讲的些什么内容 PHP 核心技术与最佳实践 1.面向对象思想的核心概念 1.1 面向对象的『形』与『本』 1.2 魔术方法的应用 1.2 ...
- 十个书写Node.js REST API的最佳实践(上)
收录待用,修改转载已取得腾讯云授权 原文:10 Best Practices for Writing Node.js REST APIs 我们会通过本文介绍下书写Node.js REST API的最佳 ...
- go-zero解读与最佳实践(上)
本文有『Go开源说』第三期 go-zero 直播内容修改整理而成,视频内容较长,拆分成上下篇,本文内容有所删减和重构. 大家好,很高兴来到"GO开源说" 跟大家分享开源项目背后的一 ...
- 超实用的JavaScript技巧及最佳实践(上)
在这篇文章中,作者将会向大家分享JavaScript开发的小技巧.最佳实践等非常实用的内容,不管你是前端开发者还是服务端开发者,都应该来看看这些小技巧,它们绝对会让你受益的. 文中所提供的代码片段都已 ...
- 《深入理解Java 7核心技术与最佳实践》读书笔记(2) Java语言动态性引言
Java语言是一种静态类型的编程语言.静态类型的含义是指在编译时进行类型检查.Java源代码中的每个变量的类型都要显式地进行声明.所有变量.方法的参数和方法返回值的类型在程序运行之前就必须是已知的.J ...
- Unity C#最佳实践(上)
本文为<effective c#>的读书笔记,此书类似于大名鼎鼎的<effective c++>,是入门后提高水平的进阶读物,此书提出了50个改进c#代码的原则,但是由于主要针 ...
- PHP核心技术与最佳实践--笔记
<?php error_reporting(E_ALL); /* php 5.3引入 延迟静态绑定 */ /* php5.4引入trait,用来实现多层继承 trait Hello{} trai ...
随机推荐
- selenium 常用浏览器操作API
package test; import org.openqa.selenium.By;import org.openqa.selenium.Dimension;import org.openqa.s ...
- python类的__new__和__init__
python的类,和其他语言有一点不太一样,就是,他把新建一个类和初始化一个类,分成了两个方法: __new__ __init__ 当然,想想就知道,肯定是__new__先发生,然后才是__init_ ...
- MYECLIPSE中快速解决项目的错误的方法
Use the IDE's help as follows:- Right mouse click on the error in the 'Problems' view- Select the 'Q ...
- [BZOJ3585]mex 主席树
3585: mex Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1252 Solved: 639[Submit][Status][Discuss] ...
- OSSIM 4 组件目录
在查找openvas问题的时候,发现: 主要组件的配置文件目录:/etc/default主要组件的安装目录:/usr/share 感觉和kali linux的的结构类似.
- (转)Docker 基础 : Dockerfile
全文来自 Docker 基础 : Dockerfile Dockerfile 是一个文本格式的配置文件,用户可以使用 Dockerfile 快速创建自定义的镜像.我们会先介绍 Dockerfile 的 ...
- 使用moneykey对APP进行健壮性测试
注意:moneykey对app按钮伪随机点击,只能测试app稳定性和健壮性,无法进行常规测试 1.安装 A.jdk(不详细介绍) B.安装配置android配置环境:Android Studio 此环 ...
- HDU 1556.Color the ball-差分数组-备忘
备忘. 差分数组: 区间更新查询有很多方法,线段树.树状数组等都可以.如果为离线查询,就可以考虑使用差分数组. 假设对于区间[l,r]的每个数都加1,我们用一个数组a来记录,a[l]+=1;a[r+1 ...
- 线段树【CF620E】The Child and Sequence
Description At the children's day, the child came to Picks's house, and messed his house up. Picks w ...
- 转 select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型:int select(int maxfd,fd_set *rdset ...