《Advanced PHP Programming》读书笔记
此书无中文版,但是写的极好!本来想翻译的,可是时间不允许了。
http://www.amazon.com/Advanced-PHP-Programming-George-Schlossnagle/dp/0672325616/ref=pd_rhf_dp_p_t_1
约定:加粗字体表示章节,由于时间关系解释性的说明全部省略。
《高级 PHP程序设计》
简介
PHP在企业级开发
一个编程语言满足下面6方面才能满足关键的商业应用:
快速原型设计和实施
现代编程范式的支持
可伸缩性
高性能
互操作性
可扩展性
平台和版本
本书主要是针对php5,更主要是使你的代码更快,更敏捷,设计的更好。
本书基于linux编写的。
平台和版本
平台和版本
第一部分 实施和开发方法
第一章 代码风格
选择适合你的代码风格
代码格式化和布局
包括行的长度,使用空白,使用SQL是最基本的技能。
缩进
本书使用缩进来表示代码块,但不能夸大其重要性。虽然php中不强制缩进,但是缩进是一个有用的工具。
考虑下面的代码
if($month == 'september' || $month == 'april' || $month == 'june' || $month ==
'november') { return 30;
}
else if($month == 'february') {
if((($year % 4 == 0) && !($year % 100)) || ($year % 400 == 0)) {
return 29;
}
else {
return 28;
}
}
else {
return 31;
}
和下面的代码比较,除了缩进都是相同的。
if($month == 'september' ||
$month == 'april' ||
$month == 'june' ||
$month == 'november') {
return 30;
}
else if($month == 'february') {
if((($year % 4 == 0) && ($year % 100)) || ($year % 400 == 0)) {
return 29;
}
else {
return 28;
}
}
else {
return 31;
}
后一段代码比前一段在逻辑上更好分辨。
当你使用tab代码缩进,你需要做出一致性选择使用硬或软tab,硬是常规选项,而软实际上是由一定量的空格表示,使用软的好处是他们总是相同,我比较喜欢软。当你使用硬,在多个开发人员使用不同的编辑器会造出不一致。
选择tab的宽度,四个空格的标签产生可读的代码。
行长
前面的第一段代码太长,这样不便于跟踪和调试,应该把长行分为多行,例如:
if($month == 'september' || $month == 'april' ||
$month == 'june' || $month == 'november') {
return 30;
}
可以缩进对齐条件
if($month == 'september' ||
$month == 'april' ||
$month == 'june' ||
$month == 'november')
{
return 30;
}
这个方法同样适合于函数的参数
mail("postmaster@example.foo",
"My Subject",
$message_body,
"From: George Schlossnagle <george@omniti.com>\r\n");
一般,我会80个字符就要换行,因为这是一个标准unix终端窗口的宽度。
使用空白
$lt = localtime();
$name = $_GET['name'];
$email = $_GET['email'];
$month = $lt['tm_mon'] + 1;
$year = $lt['tm_year'] + 1900;
$day = $lt['tm_day'];
$address = $_GET['address'];
通过空白进行逻辑分组
$name = $_GET['name'];
$email = $_GET['email'];
$address = $_GET['address'];
$lt = localtime();
$day = $lt['tm_day'];
$month = $lt['tm_mon'] + 1;
$year = $lt['tm_year'] + 1900;
SQL指引
$query = "SELECT FirstName, LastName FROM employees, departments WHERE
employees.dept_id = department.dept_id AND department.Name = 'Engineering'";
上面的sql组织的不好,可以从以下方面修改:
关键字大写;关键字换行;使用表的别名保持代码整洁
$query = "SELECT firstname,
lastname
FROM employees e,
departments d
WHERE e.dept_id = d.dept_id
AND d.name = 'Engineering'";
控制流结构
两种方式:条件和循环
控制结构使用大括号
php采用c语言风格,单行php条件语句不用使用大括号,例如下面的代码是正确的:
if(isset($name))
print "Hello $name";
但是,这样会引起混乱,应该总是使用大括号
if(isset($name)) {
print "Hello $name";
}
else {
print "Hello Stranger";
}
始终使用大括号
条件语句中三种使用括号的风格
BSD风格我比较喜欢
if ($condition)
{
// statement
}
GNU风格
if ($condition)
{
// statement
}
K&R 风格
if ($condition) {
// statement
}
for和foreach和while
如果for或者foreach循环可以做的事情不应该使用while循环
function is_prime($number)
{
if(($number % 2) != 0) {
return true;
}
$i = 0;
while($i < $number) {
// A cheap check to see if $i is even
if( ($i & 1) == 0 ) {
continue;
}
if ( ($number % $i ) == 0) {
return false;
}
$i++;
}
return true;
}
不小心会增加无限循环,使用for更加自然
function is_prime($number)
{
if(($number % 2) != 0) {
return true;
}
for($i=3; $i < $number; $i++) {
// A cheap check to see if $i is even
if( ($i & 1) == 0 ) {
continue;
}
if ( ($number % $i ) == 0) {
return false;
}
}
return true;
}
对数组迭代的时候foreach比for更好
$array = (3, 5, 10, 11, 99, 173);
foreach($array as $number) {
if(is_prime($number)) {
print "$number is prime.\n";
}
}
这样比使用for更快,因为避免计数器的使用。
使用break和continue控制循环
不需要循环的时候使用break跳出循环
$has_ended = 0;
while(($line = fgets($fp)) !== false) {
if($has_ended) {
}
else {
if(strcmp($line, '_END_') == 0) {
$has_ended = 1;
}
if(strncmp($line, '//', 2) == 0) {
}
else {
// parse statement
}
}
}
这个例子比前面的更短,而且避免了深层次的嵌套
while(($line = fgets($fp)) !== false) {
if(strcmp($line, '_END_') == 0) {
break;
}
if(strncmp($line, '//', 2) == 0) {
continue;
}
// parse statement
}
避免很深层的循环
常见的错误是在一个浅循环中使用深层嵌套
$fp = fopen("file", "r");
if ($fp) {
$line = fgets($fp);
if($line !== false) {
// process $line
} else {
die("Error: File is empty);
}
else { die("Error: Couldn't open file");
}
消除不必要的嵌套
$fp = fopen("file", "r");
if (!$fp) {
die("Couldn't open file");
}
$line = fgets($fp);
if($line === false) {
die("Error: Couldn't open file");
}
// process $line
命名符号
function test($baz)
{
for($foo = 0; $foo < $baz; $foo++) {
$bar[$foo] = "test_$foo";
}
return $bar;
}
下面的代码使用更有意义的变量名和函数名 function create_test_array($size)
{
for($i = 0; $i < $size; $i++) {
$retval[$i] = "test_$i";
}
return $retval;
}
三类命名规则:
全局变量要使用在全局范围
长时间存在的变量可存在于任何范围但要包含重要信息或大块代码的引用
临时变量用于小部分代码保持临时信息
常量和真正的全局变量
全局变量和常量要使用大写字母,便于辨识。
$CACHE_PATH = '/var/cache/';
...
function list_cache()
{
global $CACHE_PATH;
$dir = opendir($CACHE_PATH);
while(($file = readdir($dir)) !== false && is_file($file)) {
$retval[] = $file;
}
closedir($dir);
return $retval;
}
错误使用全局变量的原因:
它们可以在任何地方被改变不好定位;
污染了全局命名空间,例如使用一个全局变量命名为计数器$counter同时你还有另一个计数器也是$counter,随着代码的增长这种冲突越来越不可避免;
解决方案是使用一个“访问器”函数。
global $database_handle;
global $server;
global $user;
global $password;
$database_handle = mysql_pconnect($server, $user, $password);
可以使用如下的类:
class Mysql_Test {
public $database_handle;
private $server = 'localhost';
private $user = 'test';
private $password = 'test';
public function __construct()
{
$this->database_handle =
mysql_pconnect($this->server, $this->user, $this->password);
}
}
第二章中将探索更有效的方式处理这个例子,当我们处理单例模式和封装类时。
有时候,你需要访问一个特定的变量,像这样:
$US_STATES = array('Alabama', ... , 'Wyoming');
这个例子中类做了太多的事情,如果你想在这里避免全局变量,你可以使用一个访问函数全局数组使用一个静态变量。
function us_states()
{
static $us_states = array('Alabama', ... , 'Wyoming');
return $us_states;
}
长时间存在的变量
应该有简洁描述性的名称,长时间存在的变量不一定是全局的,甚至在主题范围内。
下面例子中变量名帮助理解代码的意思。
function clean_cache($expiration_time)
{
$cachefiles = list_cache();
foreach($cachefiles as $cachefile) {
if(filemtime($CACHE_PATH."/".$cachefile) > time() + $expiration_time) {
unlink($CACHE_PATH."/".$cachefile);
}
}
}
临时变量
临时变量的名称要简明扼要。由于临时变量通常只存在于一个小的代码块,所以他们并不需要有说明性名称。 特别是用于循环的数值变量应该始终被命名为J,K,L,M,和n
等。
比较这个例子
$number_of_parent_indices = count($parent);
for($parent_index=0; $parent_index <$number_of_parent_indices; $parent_index++) {
$number_of_child_indices = count($parent[$parent_index]);
for($child_index = 0; $child_index < $number_of_child_indices; $child_index++) {
my_function($parent[$parent_index][$child_index]);
}
}
例如
$pcount = count($parent);
for($i = 0; $i < $pcount; $i++) {
$ccount = count($parent[$i]);
for($j = 0; $j < $ccount; $j++) {
my_function($parent[$i][$j]);
}
}
这样会更妙
foreach($parent as $child) {
foreach($child as $element) {
my_function($element);
}
}
多词名称
$numElements = count($elements);
$num_elements = count($elements);
推荐第二种命名方法,原因是:
情况发生变化,你为了保持一致性不得不$CACHEDIR和$PROFANITYMACROSET
数据库不区分大小写;
非英语本土人士会在字典中更好的查到。
函数名
函数名和正常的变量名类似的处理方式,全部小写,多字要用下划线分割,推荐K&R风格:
function print_hello($name)
{
print "Hello $name";
}
foo() 和bar() 反映不出你的代码更多的信息,让你的代码看起来很不专业。
类名
参考官方的Java风格指南,类名应遵循以下规则:
一个类的名字第一个字母是大写;
下划线应该用来模拟嵌套的命名空间;
多字的类名应连接在一起,每个单词的首字母应大写。
class XML_RSS {}
class Text_PrettyPrinter {}
方法名
Java风格的串连字多字的方法名称是第一个字母后的单词第一个字母大写
class XML_RSS
{
function startHandler() {}
}
命名一致性
类似目的的变量保持类似的名称
$num_elements = count($elements);
...
$objects_cnt = count($objects);
推荐下面的风格
$max_elements;
$min_elements;
$sum_elements;
$prev_item;
$curr_item;
$next_item;
匹配变量名和架构名
与数据库中的记录相关联的变量名称应该始终有相匹配的名字。
$query = "SELECT firstname, lastname, employee_id
FROM employees";
$results = mysql_query($query);
while(list($firstname, $lastname, $employee_id) = mysql_fetch_row($results)) {
// ...
}
下面的代码容易混淆
$first_query = "SELECT a,b
FROM subscriptions
WHERE subscription_id = $subscription_id";
$results = mysql_query($first_query);
list($a, $b) = mysql_fetch_row($results);
// perform necessary logic
$new_a = $b;
$new_b = $a;
$second_query = "UPDATE subscriptions
SET a = '$new_a',
B = '$new_b'
WHERE subscription_id = $subscription_id";
Mysql_query($second_query);
开发人员为了保持列名和变量名在update中一致性
$first_query = "SELECT a,b
FROM subscriptions
WHERE subscription_id = $subscription_id";
$results = mysql_query($first_query);
list($b, $a) = mysql_fetch_row($results);
// perform necessary logic
$second_query = "UPDATE subscriptions
SET a = '$a',
B = '$b'
WHERE subscription_id = $subscription_id";
mysql_query($second_query);
这一代码会完全混乱不堪。
避免代码混乱
一致的代码风格让代码看一起是清晰的
避免短的开放的标签
php允许段标签
<?
print "Hello $username";
?>
但是不应该使用!
因为无法打印正常的XML内联文件
<?xml version="1.0" ?>
应该使用长标签
<?php
print "Hello $username";
? >
相关文章:

cookie记录用户的浏览商品的路径
在电子商务的网站中,经常要记录用户的浏览路径,以判断用户到底对哪些商品感兴趣,或者哪些商品之间存在关联。 下面将使用cookie记录用户的浏览过的历史页面。该网站将每个页面的标题保存在该页面的$TITLE 变量中,用户每访问一次&a…

如何快速写一个违背双亲委托机制的classloader
很多情况下,不得以必须写个classloader来满足需求。例如你一个工程里你想用相同的数据库的多个版本,自己制定了一个jar包目录,没有classloader管理等等。如果是一个遵循java已经规定好的机制的classloader(双亲委托以及加载依赖类…

让我们谈谈RAID
转自:http://soft.zdnet.com.cn/techupdate/2004/0330/397707.shtml 更新时间: 2004-03-30 17:14:00 作者: 赵效民 感觉写的很好就转来了。 RAID的种类 RAID的英文全称为Redundant Array of Inexpensive(或Independent) Disks&…

Ampere 携手 Rigetti 开发混合量子经典计算机
该合作旨在为价值 160 亿美元的机器学习市场提供服务,赋能机器学习应用的发展双方将把 Ampere Altra Max 处理器和 Rigetti 量子处理单元进行优化结合,为机器学习提供整合的云平台 2022 年 2 月 21 日,安晟培半导体科技有限公司(A…

[C++] NULL VS nullptr
NULL VS nullptr 转载于:https://www.cnblogs.com/tianhangzhang/p/4945623.html

swift 的defer使得资源的分配和释放代码可以放到一起
只是一种语法和逻辑上的优化

烂泥:haproxy学习之手机规则匹配
2019独角兽企业重金招聘Python工程师标准>>> 本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb。 今天我们来介绍下有关haproxy匹配手机的一些规则配置。 一、业务需要 现在根据业务的实际需要&a…

jQuery日期选择器插件date-input
官网:http://jonathanleighton.com/projects/date-input/下载: http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js http://github.com/jonleighton/date_input/raw/master/jquery.date_input.js http://github.com/jonleighton/date_inp…

厉害了,用Python绘制动态可视化图表,并保存成gif格式
作者 | 俊欣来源 | 关于数据分析与可视化最近有粉丝问道说“是不是可以将这些动态的可视化图表保存成gif图”,小编立马就回复了说后面会写一篇相关的文章来介绍如何进行保存gif格式的文件。那么我们就开始进入主题,来谈一下Python当中的gif模块。安装相关…

facade-门面模式
解决问题 客户端调用逻辑与业务代码有效隔离,使得客户端调用只和Facade进行交互,内部的调用逻辑由Facade进行实现。此模式也可以和接口化编程结合,进一步降低客户端与业务逻辑的耦合 应用场景 它主要应用在代码结构的设计,合理组织…

淘宝李晓拴:淘宝网PHP电子商务应用
源自:http://tech.qq.com/a/20110512/000298.htm 大家好,大家知道淘宝搜索是一个典型PHP架构。在座同学不知道有多少人使用过淘宝搜索可以举手示意一下?在开始这个话题之前我们先谈一下Polyglot,多语言混合编程,淘宝有…

玩爬虫不会登陆?这个工具拿走不谢!
作者 | 周萝卜来源 | 萝卜大杂烩在日常学习当中,我们或多或少都会到网上抓取一些数据,比如豆瓣、微博等等,但是这些网站在非登录的情况只能拿到部分数据,有很多数据都是需要登陆之后才可以获取的,那么模拟登陆就成为了…

Oracle分页
先看以下两条语句的执行结果: 语句一:select rownum,empno,sal from emp order by empno; ROWNUM EMPNO SAL ---------- ---------- ---------- 1 7369 800 2 7499 1600 3 7521 …

Scala类型系统——高级类类型(higher-kinded types)
高级类类型就是使用其他类型构造成为一个新的类型,因此也称为 类型构造器(type constructors)。它的语法和高阶函数(higher-order functions)相似,高阶函数就是将其它函数作为参数的函数;高级类类型则是将构造类类型作为参数类型。一个高级类…

android休眠唤醒驱动流程分析【转】
转自:http://blog.csdn.net/hanmengaidudu/article/details/11777501标准linux休眠过程:l power management notifiers are executed with PM_SUSPEND_PREPAREl tasks are frozenl target system sleep state is announced to the …

PHP使用curl_multi_add_handle并行处理
http://www.php.net/manual/zh/function.curl-multi-add-handle.php<?php// 创建一对cURL资源$ch1 curl_init();$ch2 curl_init();// 设置URL和相应的选项curl_setopt($ch1, CURLOPT_URL, "http://www.baidu.com/");curl_setopt($ch1, CURLOPT_HEADER, 0);curl…

斯坦福团队是如何构建更好用的聊天 AI 呢?
作者:Standford AI译者:Yang来源:数据实战派2019 年,凭借着 Chirpy Cardinal 机器人,斯坦福首次在 Alexa Prize Socialbot Grand Challenge 3 中赢得了第二名。本文将进一步揭示 Chirpy Cardinal 开发细节,…

使用Linux进行缓冲区溢出实验的配置记录
在基础的软件安全实验中,缓冲区溢出是一个基础而又经典的问题。最基本的缓冲区溢出即通过合理的构造输入数据,使得输入数据量超过原始缓冲区的大小,从而覆盖数据输入缓冲区之外的数据,达到诸如修改函数返回地址等目的。但随着操作…

Javascript导出Excel的方法
<SCRIPT LANGUAGE"javascript"> function method1(tableid) {//整个表格拷贝到EXCEL中 var curTbl document.getElementById(tableid); var oXL new ActiveXObject("Excel.Application"); //创建AX对象excel var oWB oXL.Workbooks.Add(); //获取…

Top 15 不起眼却有大作用的 .NET功能集
目录1. ObsoleteAttribute2. 设置默认值属性: DefaultValueAttribute3. DebuggerBrowsableAttribute4. ??运算符5. Curry 及 Partial 方法6. WeakReference7. Lazy8. BigInteger9. 非官方关键字:__arglist __reftype __makeref __…

M2 芯片终于要来了?全线换新,性能远超M1 Max
不知不觉日历已翻至 2 月下旬,掐指一算,距离苹果一年一度春季新品发布会的召开似乎已越来越近。根据年初统计的 2022 年苹果新品预测,预计今年的苹果“小春晚”将在 Mac 方面有大动作。 那么,苹果将如何“动作”,又…

Python抓取新浪新闻数据(三)
非同步载入一般在XHR下查找,但是没有发现XHR下有相关内容。 转载于:https://blog.51cto.com/2290153/2126862

不畏浮云遮望眼--离散数学和组合数学
不畏浮云遮望眼,基础很重要!离散数学是算法和数据结构的基础,而算法和数据结构又是什么的基础?不解释了。1.《离散数学及其应用》作者: (美)Kenneth H. R出版社: 机械工业出版社出版年: 2007-6页数: 804定价: 79.00元丛书: 计算机…

上班摸鱼,刚刚发现在 VScode 中可玩魂斗罗,超级玛丽
今天,再给大家介绍一款更加有意思的vscode插件——“小霸王”。 GitHub传送门:https://github.com/gamedilong/anes-repository 安装方式: 对于插件的安装,可以按照上图的操作流程。 1.打开VScode,然后点击拓展。 2.在输入框中&am…

JSP 三 :九大隐式对象
2019独角兽企业重金招聘Python工程师标准>>> ###细节 每个JSP页面在第一次被访问时,web容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet),然后按照servlet的调用方…
阿里90后工程师利用ARM硬件特性开启安卓8终端“上帝模式”
文/图 阿里安全潘多拉实验室 团控 编者按:团控,阿里安全潘多拉实验室研究人员,该实验室主要聚焦于移动安全领域,包括对iOS和Android系统安全的攻击和防御技术研究。团控的主攻方向为安卓系统级漏洞的攻防研究。在今年3月的BlackHa…

c语言模拟实现oc引用计数
#include<stdio.h> #include<stdlib.h> //在c中引入 引用计数机制 // 要解决的问题: 1,指向某块动态内存的指针有几个? // 应该让这块动态内存记录指针的数量 // 所以开辟的动态内存大小应该取多大? // …

ATT与Intel汇编语言的比较
转自 陈莉君 一书《深入分析Linux内核源码》 http://www.kerneltravel.net/kernel-book/第二章%20Linux运行的硬件基础/2.6.1.htm2.6.1 AT&T与Intel汇编语言的比较我们知道,Linux是Unix家族的一员,尽管Linux的历史不长,但与其相关的很多事…

最近,又发现了 Pandas 中三个好用的函数
作者 | luanhz来源 | 小数志导读近日,在github中查看一些他人提交的代码时,发现了Pandas中这三个函数,在特定场景中着实好用,遂成此文以作分享。程序的基本结构大体包含三种,即顺序结构、分支结构和循环结构࿰…

Java Web的Maven项目中Properties文件的使用(2)
为什么80%的码农都做不了架构师?>>> 背景 Java Web中常用一些Properties文件进行部署配置,其中如果在里面配置OS的路径,需要跨平台,主要就是考虑win系统的路径是“\”,而Linux的路径是“/”。 …