PHP基础语法

年後の新作2.14(。・∀・)ノ

本文参考PHP中文网:[PHP入门教程之一周学会PHP] [PHP入门视频教程之一周学会PHP]
资料查阅:[W3shcool PHP 教程]
 
 

PHP

 

一、 PHP基础语法

1.1 PHP 语法

1. PHP基础语法
PHP 脚本可以放在文档中的任何位置。
PHP 脚本以 尖括号、问号、PHP <?php**开始,以 ?> 问号、尖括号结束。
PHP 文件的默认文件扩展名是 “
.php**“。
PHP 文件通常包含 HTML 标签和一些 PHP 脚本代码。

1
2
3
<?php
//这里是我们要写的PHP代码
?>

&emsp;

2. PHP输出语法
PHP中echo(), print(), print_r(), var_dump()的区别:
echo:是PHP语句, 输出一个或多个字符串。实际上它并不是一个函数,所以不必对它使用括号,直接用echo就行。print和print_r是函数,语句没有返回值,函数可以有返回值(即便没有用)。可以一次输出多个值,多个值之间用逗号分隔。echo是语言结构(language construct),而并不是真正的函数,因此不能作为表达式的一部分使用。

print: 同样是一个语言结构,可以使用括号,也可以不使用括号: print 或 print()。只能打印出简单类型变量的值,如:int、string。
下面的实例演示了如何使用 print 命令输出字符串(字符串可以包含 HTML 标签):

print_r():
可以把字符串和数字简单地打印出来,而数组则以括起来的键和值得列表形式显示,并以Array开头。但print_r()输出布尔值和NULL的结果没有意义,因为都是打印”\n”。因此用var_dump()函数更适合调试。

var_dump():
var_dump(传入一个变量) 输出变类型和值(最常用)。var_dump() 是一个函数。向括号()中间插入变量。这个函数,会打印出来数据类型,还会对应显示变量的长度和值。

· echo - 可以输出一个或多个字符串
· print - 只允许输出一个字符串,返回值总为 1
提示:echo 输出的速度比 print 快, echo 没有返回值,print有返回值1。
echo 是一个语言结构,使用的时候可以不用加括号,也可以加上括号: echo 或 echo()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
echo:
<?php
$str="hello world!";
echo $str;
echo 'a','b','c';
?>
//运行结果:hello world!abc

print:
<?php
print "<h2>PHP is fun!</h2>";
print "Hello world!<br>";
print "I'm about to learn PHP!";

?>

print_r():
<?php
$age=array(18,20,24);
print_r($age);
?>
//运行结果:Array ( [0] => 18 [1] => 20 [2] => 24 )

var_dump():
<?php
$age=array(18,20,24);
var_dump($age);
?>
//运行结果:array(3) { [0]=> int(18) [1]=> int(20) [2]=> int(24) }
**注意事项:** php的代码部份全部要用半角的英文、很多人容易写成全角的英文和符号造成PHP代码报错。 PHP 中的每个代码行都必须以分号结束。分号是一种分隔符,用于把指令集区分开来。 PHP代码的最后一行可以加也可不加分号。由于很多学习者特别是初学者经常犯一个毛病:写完一行代码不加 分号。因此,容易报错。我们通常在公司里面规定:一行代码写完,就必须要加分号。

&emsp;
3.PHP中的注释:
单行注释(只注释一行): // 双斜杠表示单行注释,有时也用 # 表示,但用的比较少,多用 //
多行注释(注释多行):/* 开始, 以*/结束代表多行注释。

&emsp;
&emsp;

1.2 PHP 变量

1. PHP中的变量有几个特点:

  1. 必须要以$开始。如变量x必须要写成$x
  2. 变量的首字母不能以数字开始
  3. 变量的名字区分大小写
  4. 变量不要用特殊符号、中文,_不算特殊符号
  5. 变量命名要有意义(别写xxx,aaa,ccc这种 变量名)
  6. $ 叫作美元符,英文单词:dollar。PHP的变量必须以美元符开始。说明搞PHP有“钱”图
1
2
3
4
5
6
7
变量在您第一次赋值给它的时候被创建:在下面的语句执行中,变量txt将保
存值Hello world!,且变量 x 将保存值 5。
<?php
$txt="Hello world!";
$x=5;
$y=10.5;
?>

&emsp;
2. PHP是一门弱类型语言:
在上面的实例中,我们注意到,不必向 PHP 声明该变量的数据类型。
PHP 会根据变量的值,自动把变量转换为正确的数据类型。
在强类型的编程语言中,我们必须在使用变量前先声明(定义)变量的类型和名称。

&emsp;
3. PHP变量的作用域:local、global、static、parameter
局部和全局作用域(loacal global):在所有函数外部定义的变量,拥有全局作用域。除了函数外,全局变量可以被脚本中的任何部分访问,要在一个函数中访问一个全局变量,需要使用 global 关键字。

PHP global 关键字:global 关键字用于函数内访问全局变量。
PHP 将所有全局变量存储在一个名为 $GLOBALS[index] 的数组中。 index 保存变量的名称。这个数组可以在函数内部访问,也可以直接用来更新全局变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
$x=10;
$y=20;
function test(){
global $x,$y; //使用global关键字

$y=$x+$y;
}
test();
echo $y;//输出30
?>

上面例子也可以写成:

<?php
$x=5;
$y=10;
function myTest()
{
$GLOBALS['y']=$GLOBALS['x']+$GLOBALS['y'];
}
myTest();
echo $y;
?>

注意:
不可在global 后写 $变量 = 值。

1
2
3
4
5
6
7
8
9
10
<?php
$a = 10;
$b = 100;
function test(){
global $a , $b;
echo $a + $b;
}
//结果是不是显示出来了?
test();
?>

&emsp;
1.通过$GLOBLAS来读取外部变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

$one = 10;

function demo(){
$two = 100;

$result = $two + $GLOBALS['one'];

return $result;

}
//你会发现结果变成了110
echo demo();
?>

上例中:我们将函数体外的变量通过$GLOBALS拿到了函数体使用。所以,打破了函数外的变量不能在函数体内使用的限定。

&emsp;
static 作用域:当一个函数完成时,它的所有变量通常都会被删除。然而,有时候您希望某个局部变量不要被删除。要做到这一点,请在您第一次声明变量时使用 static 关键字:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
function myTest()
{
static $x=0;
echo $x;
$x++;
}
myTest();
myTest();
myTest();
myTest();
?>

&emsp;
2.通过$GLOBLAS,在函数内修改外部变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

$hongniu = '我是一个兵,来自老百姓';

function test(){

echo '执行了函数test哟<br />';
//调用test()函数,将通过$GLOBALS['hongniu'],把$hongniu的值改变掉

$GLOBALS['hongniu'] = '帮助别人很快乐';
}

test();
//发现是不是输出的值变了呀?
echo $hongniu;
?>

通过上例:我们发现通过$GLOBALS[‘hongniu’],把$hongniu的值改变掉,所以在最后输出$hongniu的时候,值发生了变化。

&emsp;
3.通过$GLOBLAS,在函数内创建全局变量

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

function hello(){

$GLOBALS['que'] = '提神喝茶更好哟';

echo '你调了一下函数hello<br />';
}

hello();

echo $que;
?>

上例中,我们发现$que是不存在的,可以调用函数hello()后,在函数外部可以执行echo $que了,能够看到结果:提神喝茶更好。我们明白了,函数内声明的变量,通过$GLOBALS声明一个变量,也能够显示出来。

&emsp;
下面的知识是【了解】级别,我们越来越少的使用这种方式来声明全局变量了。在函数内使用global关键词后面跟一个或多个变量,就把变量变为了全局变量,格式如下:

1
2
3
4
5
6
7
8
9
10
<?php
$a = 10;
$b = 100;
function test(){
global $a , $b;
echo $a + $b;
}
//结果是不是显示出来了?
test();
?>

&emsp;
4. PHP 全局变量 - 超全局变量:
PHP 中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中都可用。在函数或方法中无需执行 global
$变量名; 就可以访问它们。

PHP 超级全局变量列表: &emsp;[PHP 全局变量 - 超全局变量]
$GLOBALS
$_SERVER
$_REQUEST
$_POST
$_GET
$_FILES
$_ENV
$_COOKIE
$_SESSION

&emsp;
5. PHP 系统变量(魔术常量):
PHP 向它运行的任何脚本提供了大量的预定义常量。
不过很多常量都是由不同的扩展库定义的,只有在加载了这些扩展库时才会出现,或者动态加载后,或者在编译时已经包括进去了。
有八个魔术常量它们的值随着它们在代码中的位置改变而改变。

使用方法参见

常量符号 意义
__LINE__ 文件中的当前行号
__FILE__ 文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。自 PHP
4.0.2 起,__FILE__ 总是包含一个绝对路径(如果是符号连接,则是解析后的绝对路
径),而在此之前的版本有时会包含一个相对路径。
__DIR__ 文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。它等价于
dirname(__FILE__)。除非是根目录,否则目录中名不包括末尾的斜杠。(PHP 5.3.0
中新增)
__FUNCTION__ 函数名称(PHP 4.3.0 新加)。自PHP5起本常量返回该函数被定义时的名字(区分大小
写)。在 PHP 4 中该值总是小写字母的。
__CLASS__ 类的名称(PHP 4.3.0 新加)。自 PHP 5起本常量返回该类被定义时的名字(区分大小
写)
__TRAIT__ Trait 的名字(PHP 5.4.0 新加)。自 PHP 5.4.0 起,PHP实现了代码复用的一个方法,
称为 traits。
__METHOD__ 类的方法名(PHP 5.0.0 新加)。返回该方法被定义时的名字(区分大小写)。

&emsp;
&emsp;

1.3 PHP 数据类型

1. PHP的数据类型包括以下几种:
Integer(整型)、String(字符串)、Float(浮点型)、Boolean(布尔型)、Array(数组)、Object(对象)、NULL(空值)

2. 查看变量数据类型:
1. gettype(传入一个变量) 能够获得变量的类型
2. var_dump(传入一个变量) 输出变类型和值 (最常用)
var_dump()是一个函数。向括号()中间插入变量。这个函数,会打印出来数据类型,还会对应显示变量的长度和值。

&emsp;
&emsp;

1.4 PHP 字符串

1. 字符串型可以用三种方法定义:单引号形式双引号形式Heredoc结构形式。

2.单、双引号嵌套使用时注意事项:
1.若单引号嵌套单引号或者双引号嵌套双号时:里层(被嵌套)的引号要用“</font>”转义字符转义;
2.单引号嵌套双引号或者双引号嵌套单引号时:不需要用转义字符。

3.当美元符$在引号里时的区别:
1.在双引号里:当双引号里包含变量时,变量会双引号里的内容连在一起;
2.在单引号里:变量会被当做字符地输出,即“$”会被输出。

1

&emsp;
**4. Heredoc结构(<<<):**
2).然后在<<<后面写上字符(建议英文大写字符)。如下例中的:ABC
3).然后换行写上任意想写的字符
4).写完后,顶行。在行最开始处,再写上<<<后面的字符和分号。如下例中的:ABC;

1
2
3
4
5
<?php
$dingjie = <<<ABC //“=”和“<<<”和“ABC”这三个标志符号
这里是字符串的内容。
ABC;
?>

&emsp;
5. PHP strlen() 函数:
有时知道字符串值的长度是很有用的。
strlen() 函数返回字符串的长度(字符数)。
注意:在UTF-8下 strlen 把中文字符算成 3 个字节,英文,空格,符号占 1 个字节。
&emsp;
6. PHP strpos() 函数:
strpos()函数用于在字符串内查找一个字符或一段指定的文本。
如果在字符串中找到匹配,该函数会返回第一个匹配的字符位置。如果未找到匹配,则返回 FALSE。
实例:下面的实例在字符串 “Hello world!” 中查找文本 “world”:

1
2
3
4
<?php
echo strpos("Hello world!","world");
?>
运行结果:6

提示:在上面的实例中,字符串 “world” 的位置是 6。之所以是 6 而不是 7 的原因是,字符串中第一个字符的位置是 0,而不是 1。

&emsp;
&emsp;

1.5 PHP 常量

1. 自定义常量:
(1) 常量是单个值的标识符(名称)。在脚本中无法改变该值。
(2) 有效的常量名以字符或下划线开头(常量名称前面没有 $ 符号)。
(3) 常量名可以小写,但是通常大写。
(4) 常量是全局的,常量在定义后,默认是全局变量,可以在整个运行的脚本的任何地方使用。

定义方法:
如需设置常量,请使用 define() 函数 - 它使用三个参数:

  1. 首个参数定义常量的名称
  2. 第二个参数定义常量的值
  3. 可选的第三个参数规定常量名是否对大小写敏感。默认是 false。

注意关于define和const定义的区别:
可以用 define() 函数来定义常量。在 PHP 5.3.0 以后,可以使用 const 关键字在类定义的外部定义常量,先前版本const 关键字只能在类(class)中使用。一个常量一旦被定义,就不能再改变或者取消定义。
常量只能包含标量数据(boolean,integer,float 和 string)。 可以定义 resource 常量,但应尽量避免,因为会造成不可预料的结果。

1
2
3
4
5
6
7
8
9
10
11
12
define定义方式:
<?php
$p = "PII";
define("PI",3.14);define($p,3.14);
define($p,3.14);
echo PI;
echo "<br />";
echo PII;
?>
运行结果:
3.14
3.14

&emsp;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const定义方式:
希望一个成员变量不被修改 例如圆周率 3.1415926
定义:const 常量名=值; 没有$符
访问:类名 ::常量名 或 接口名::常量名

<?php                      defined('TEXT');检查一个名称的常量是否存在
class A{
const TAX_RATE=0.08;
public function payTax($var){
return $var*A::TAX_RATE;
}
}
$a=new A();
echo $a->payTax(200):
?>

&emsp;
用法一:const用于类成员变量,一经定义不可修改,define用于全局常量,不可用于类成员变量的定义,const可在类中使用,define不能。
用法二:const定义的常量大小写敏感,而define可通过第三个参数(为TRUE表示大小写不敏感)来指定大小写是否敏感。在运行时定义一个常量。define(‘TXE’,100,TRUE);
用法三:const不能在条件语句中定义常量,而define函数可以。if($a>10){define(‘LE’,’hello’);

&emsp;
2. 判定常量是否被定义:
如果常量被重复定义以后,PHP解析器会发出“Constant XXX already defined”的警告,提醒我们该常量已经被定义过。那么,在团队开发,或代码量很大的情况下,我们如何去判定一个常量是否被定义呢?
defined()函数可以帮助我们判断一个常量是否已经定义,其语法格式为:
bool defined(string constants_name)
它只有参数constant_name,指的是要获取常量的名称,若存在则返回布尔类型true,否则返回布尔类型false; (注:bool表示函数返回值类型为布尔类型)

1
2
3
4
5
6
7
8
<?php 
define("PI1",3.14);
$p = "PI1";
$is1 = defined($p);
$is2 = defined("PI2");
var_dump($is1);
var_dump($is2);
?>

&emsp;
3. PHP 全局变量 - 超全局变量:
PHP 中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中都可用。在函数或方法中无需执行 global
$变量名; 就可以访问它们。

PHP 超级全局变量列表: &emsp;[PHP 全局变量 - 超全局变量]
$GLOBALS
$_SERVER
$_REQUEST
$_POST
$_GET
$_FILES
$_ENV
$_COOKIE
$_SESSION

&emsp;
4. PHP 系统变量(魔术常量):
PHP 向它运行的任何脚本提供了大量的预定义常量。
不过很多常量都是由不同的扩展库定义的,只有在加载了这些扩展库时才会出现,或者动态加载后,或者在编译时已经包括进去了。
有八个魔术常量它们的值随着它们在代码中的位置改变而改变。

使用方法参见

常量符号 意义
__LINE__ 文件中的当前行号
__FILE__ 文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。自 PHP
4.0.2 起,__FILE__ 总是包含一个绝对路径(如果是符号连接,则是解析后的绝对路
径),而在此之前的版本有时会包含一个相对路径。
__DIR__ 文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。它等价于
dirname(__FILE__)。除非是根目录,否则目录中名不包括末尾的斜杠。(PHP 5.3.0
中新增)
__FUNCTION__ 函数名称(PHP 4.3.0 新加)。自PHP5起本常量返回该函数被定义时的名字(区分大小
写)。在 PHP 4 中该值总是小写字母的。
__CLASS__ 类的名称(PHP 4.3.0 新加)。自 PHP 5起本常量返回该类被定义时的名字(区分大小
写)
__TRAIT__ Trait 的名字(PHP 5.4.0 新加)。自 PHP 5.4.0 起,PHP实现了代码复用的一个方法,
称为 traits。
__METHOD__ 类的方法名(PHP 5.0.0 新加)。返回该方法被定义时的名字(区分大小写)。

&emsp;
&emsp;

1.6 PHP数组:索引数组、关联数组

数组可以存入多个不同类型的数据,是一个复合数据类型。
我们可以使用array() 来初始化数组,每个数组元素之间使用逗号分隔 ,在PHP5.4版本之后,数组的初始化更为简洁,用中括号[ ] 来初始化。
数组的格式:$shuzu=array(key=>value)
key:键值 &emsp; value:键值对应值

1. 索引数组:键值为整形(int)
我们来总结规律:
1.索引数组若不强制声明他的下标,他的下标是从0开始的。(我们的第一个数组的值:只有不断努力才能博得未来。这个值的下标为0)。
2.如果我指定过下标他的下标就为我指定的值。如下标为5,10和下标为19的,都是我指定过的值。
3.若某个值(如php.cn),强制指定了下标(下标为10)。在它后面加上的值(PHP学院),不指定下标的话。他们的下标增长规律为最大值+1。

1
2
3
4
5
6
7
<?php
header("Content-type:text/html;charset=utf-8"); //设置编码
$array=array(100,1.34,true,"PHP中文网",);
echo '<pre>';
var_dump($array);
echo '<pre/>';
?>

&emsp;
2. 关联数组:键值中只要有一个为字符串(String)类型即称为关联数组)
那我们来声明一下关联数组。跟索引数组的声明方式完成一样。不过不同的是,必须要指定字符串的下标和必须要使用键值对应符。
我们通过实验知道:
1.声明关联数组是 键名 => 值。
2.在关联数组可以有索引数组的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
$arr=[ //用[ ]创建数组
'name'=>'Tom',
'age'=>'18',
'gender'=>'male'
];
echo "<pre>";
var_dump($arr) ;
echo"</pre>"
?>

运行结果:array(3) {
["name"]=>
string(3) "Tom"
["age"]=>
string(2) "18"
["gender"]=>
string(4) "male"
}

注:上例中echo pre这个标签的主要目的是为原样输出,格式展示的更好看,更清晰。

&emsp;
3. 索引数组和关联数组遍历分别用for和foreach
1. 索引数组:使用for遍历

1
2
3
4
5
6
7
8
<?php
$arr=Array('tom','andy','jack');
$arrlength=count($arr);
for($x=0;$x<$arrlength;$x++){
echo $arr[$x];
echo "<br/>";
}
?>

&emsp;

2. 关联数组:使用foreach遍历
foreach的基本语法:
有一个布尔型循环是专门用来循环数组的。这个循环的基本语法就是foreach基本语法

foreach( 要循环的数组变量 as [键变量 =>] 值变量)
{
//循环的内容
}

这是一个固定用法,将要循环的数组放进去。
as 是一个固定的关键字;
后面的键变量是可选的,随意定义一个变量,每次循环的时候,foreach这个语法会把键取出来赋值到键变量里面;
后面的值变量是必填的。每次循环的时候,会把值放到值变量里面。
我们下面用代码来举例子,加强对这个语法的理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$arr=[
'name'=>'Tom',
'age'=>'18',
'gender'=>'male'
];
foreach($arr as $key=>$value){
echo $key.": ".$value."<br />";
};
?>
运行结果:
name: Tom
age: 18
gender: male

&emsp;
通过上面的运行结果我们得出下面的结果:
1.每次循环的时候,把下标赋值给了变量$key,把值的变量赋值给了变量$value
2.循环一次读一次键和值。读到最后,发现没有可以读取的数组元素后,停止循环遍历数据。
注意:$key 和$value并不是变量名必须得为这两个名字。你命名为其他的也可以,如 $kai => $wen是一样的。 你要清楚键赋值给了哪个变量,值赋值给了另外的哪个变量。

3. 通过foreach遍历不连续的索引数组,如下例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
header("Content-type:text/html;charset=utf-8"); //设置编码
$data = array(
0 => '中国',
100 => '美国',
20 => '韩国',
300 => '德国',
);
foreach($data as $k => $v){
echo $k . '------' . $v .'<br />';
}
?>
运行结果:
0------中国
100------美国
20------韩国
300------德国

按照foreach的结果推理与刚刚做的关联数组的结果是一样的。
不同的是不连续的索引数组。每读一次数组的元素,将当次循环的下标赋值给了变量$k,值赋值给了变量$v。(即不像for循环一样的循环遍历) 每读将键和值输出,然后显示出来。循环一次向后移动一次下标。读取至最后,退出执行。

&emsp;
4. foreach遍历遍历多维数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php

$data = array(

0 => array(
'中国' => 'china',
'美国' => 'usa',
'德国' => ' Germany',
),

1 => array(
'湖北' => 'hubei',
'河北' => 'hebei',
'山东' => 'shandong',
'山西' => 'sanxi',
),

);

//注:我们在使用foreach循环时,第一次循环将键为0和键为1的两个数组赋值给一个变量($value)。然后,
//再套一个循环遍历这个$value变量,$value中的值取出来,赋值给$k和$v。

foreach($data as $value){

//第一次循环把国家的数组赋值给了$value
//第二次循环把中国的省份的数组又赋值给了$value
//因此,我在循环的时候把$value再遍历一次

foreach($value as $k => $v){
echo $k . '-----' . $v .'<br />';
}

//为了看的更清晰,我在中间加上华丽丽的分割线方便你来分析

echo '----------分割线-----------<br />';

}

?>

总结:

  1. 第一次循环的时候,将数组赋值给了$value,然后用foreach循环$value。将二维的子数组中的键给到$k,值赋值给变量$v。
  2. 第一次循环退出子数组的循环,执行后续代码显示分割线。
  3. 依此类推,第二次循环也是这样。

&emsp;
5. 统计数组元素个数
数组是我们最常用到的类型,那如何计算某个一维数组的个数呢。其实我们可以用到我们之前学过的数学函数里面的一个:count()
count($变量) 函数用于返回数组的长度(元素数):

1
2
3
4
<?php
$name=Array('tom','andy','jack');
echo count($name);
?>

&emsp;
6. PHP 数组排序
数组中的元素可以按字母或数字顺序进行降序或升序排列。
升序:从小到大的顺序进行排序,如果是英文单词,那么按字母A-Za-z的顺序排序,如果是数字,那么按数字的大小进行排序。
降序:与升序相反

sort() - 对数组进行升序排列
rsort() - 对数组进行降序排列
asort() - 根据关联数组的值,对数组进行升序排列
ksort() - 根据关联数组的键,对数组进行升序排列
arsort() - 根据关联数组的值,对数组进行降序排列
krsort() - 根据关联数组的键,对数组进行降序排列

&emsp;
7. 数组函数
[PHP 数组函数]

&emsp;
&emsp;

1.7 PHP 命名空间

[参见本站博客:PHP-命名空间]

&emsp;
&emsp;

1.8 PHP 面向对象

  • [ ]类: 定义了一件事物的抽象特点。类的定义包含了数据的形式以及对数据的操作。
  • [ ]对象: 是类的实例。
  • [ ]成员变量: 定义在类内部的变量。该变量的值对外是不可见的,但是可以通过成员函数访问,在类被实例化为对象后,该变量即可称为对象的属性。
  • [ ]成员函数: 定义在类的内部,可用于访问对象的数据。
  • [ ]继承: 继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。
  • [ ]父类: 一个类被其他类继承,可将该类称为父类,或基类,或超类。
  • [ ]子类: 一个类继承其他类称为子类,也可称为派生类。
  • [ ]多态: 多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。
  • [ ]重载: 简单说,就是函数或者方法有同样的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。
  • [ ]抽象性: 抽象性是指将具有一致的数据结构(属性)和行为(操作)的对象抽象成类。一个类就是这样一种抽象,它反映了与应用有关的重要性质,而忽略其他一些无关内容。任何类的划分都是主观的,但必须与具体的应用有关。
  • [ ]封装: 封装是指将现实世界中存在的某个客体的属性与行为绑定在一起,并放置在一个逻辑单元内。
  • [ ]构造函数: 主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。
  • [ ]析构函数: 析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做”清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。

&emsp;
1. 构造函数
构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。
PHP 5 允行开发者在一个类中定义一个方法作为构造函数,语法格式如下:
void __construct ([ mixed $args [, $… ]] )
在上面的例子中我们就可以通过构造方法来初始化 $url 和 $title 变量:

1
2
3
4
 function __construct( $par1, $par2 ) {
$this->url = $par1;
$this->title = $par2;
}

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php
header("Content-type:text/html;charset=utf-8"); //设置编码
class Site {
/* 成员变量 */
var $url;
var $title;

/* 成员函数 */
function setUrl($par){
$this->url = $par;
}

function getUrl(){
echo $this->url ."<br/>";
}

function setTitle($par){
$this->title = $par;
}

function getTitle(){
echo $this->title . "<br/>";
}
function __construct( $par1, $par2 ) {
$this->url = $par1;
$this->title = $par2;
}
}

// 调用成员函数,设置标题和URL
$php = new Site('www.php.cn', 'php中文网');
$taobao = new Site('www.taobao.com', '淘宝');
$google = new Site('www.google.com', 'Google 搜索');

// 调用成员函数,获取标题和URL
$php->getTitle();
$taobao->getTitle();
$google->getTitle();

$php->getUrl();
$taobao->getUrl();
$google->getUrl();
?>

&emsp;
2. 析构函数
析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
header("Content-type:text/html;charset=utf-8"); //设置编码
class MyDestructableClass {
function __construct() {
print "构造函数\n";
$this->name = "MyDestructableClass";
}

function __destruct() {
print "销毁 " . $this->name . "\n";
}
}

$obj = new MyDestructableClass();
?>

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
header("Content-type:text/html;charset=utf-8"); //设置编码
class MyDestructableClass {
function __construct() {
print "构造函数\n";
$this->name = "MyDestructableClass";
}

function __destruct() {
print "销毁 " . $this->name . "\n";
}
}

$obj = new MyDestructableClass();
?>

&emsp;
3. 继承
PHP 使用关键字 extends 来继承一个类,PHP 不支持多继承,格式如下:

1
2
3
class Child extends Parent {
// 代码部分
}

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
// 子类扩展站点类别
class Child_Site extends Site {
var $category;
function setCate($par){
$this->category = $par;
}
function getCate(){
echo $this->category . "<br/>";
}
}
?>

&emsp;
4. 方法重写
如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
下面的例中重写了 getUrl 与 getTitle 方法:

1
2
3
4
5
6
7
8
9
function getUrl() {
echo $this->url . PHP_EOL;
return $this->url;
}

function getTitle(){
echo $this->title . PHP_EOL;
return $this->title;
}

&emsp;
5. 访问控制
PHP 对属性或方法的访问控制,是通过在前面添加关键字 public(公有),protected(受保护)或 private(私有)来实现的。
public(公有):公有的类成员可以在任何地方被访问。
protected(受保护):受保护的类成员则可以被其自身以及其子类和父类访问。
private(私有):私有的类成员则只能被其定义所在的类访问。

(1) 属性的访问控制
类属性必须定义为公有,受保护,私有之一。如果用 var 定义,则被视为公有。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?php
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';

function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}

$obj = new MyClass();
echo $obj->public; // 这行能被正常执行
echo $obj->protected; // 这行会产生一个致命错误
echo $obj->private; // 这行也会产生一个致命错误
$obj->printHello(); // 输出 Public、Protected 和 Private


/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// 可以对 public 和 protected 进行重定义,但 private 而不能
protected $protected = 'Protected2';

function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}

$obj2 = new MyClass2();
echo $obj2->public; // 这行能被正常执行
echo $obj2->private; // 未定义 private
echo $obj2->protected; // 这行会产生一个致命错误
$obj2->printHello(); // 输出 Public、Protected2 和 Undefined

?>

&emsp;
(2) 方法的访问控制
类中的方法可以被定义为公有,私有或受保护。如果没有设置这些关键字,则该方法默认为公有。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?php
/**
* Define MyClass
*/
class MyClass
{
// 声明一个公有的构造函数
public function __construct() { }

// 声明一个公有的方法
public function MyPublic() { }

// 声明一个受保护的方法
protected function MyProtected() { }

// 声明一个私有的方法
private function MyPrivate() { }

// 此方法为公有
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}

$myclass = new MyClass;
$myclass->MyPublic(); // 这行能被正常执行
$myclass->MyProtected(); // 这行会产生一个致命错误
$myclass->MyPrivate(); // 这行会产生一个致命错误
$myclass->Foo(); // 公有,受保护,私有都可以执行


/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// 此方法为公有
function Foo2()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate(); // 这行会产生一个致命错误
}
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // 这行能被正常执行
$myclass2->Foo2(); // 公有的和受保护的都可执行,但私有的不行

class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}

public function testPublic() {
echo "Bar::testPublic\n";
}

private function testPrivate() {
echo "Bar::testPrivate\n";
}
}

class Foo extends Bar
{
public function testPublic() {
echo "Foo::testPublic\n";
}

private function testPrivate() {
echo "Foo::testPrivate\n";
}
}

$myFoo = new foo();
$myFoo->test(); // Bar::testPrivate
// Foo::testPublic
?>

&emsp;
6. 接口
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
接口是通过 interface关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是公有,这是接口的特性。
要实现一个接口,使用 implements 操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
// 声明一个'iTemplate'接口
interface iTemplate
{
public function setVariable($name, $var);
public function getHtml($template);
}
// 实现接口
class Template implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
public function getHtml($template)
{
foreach($this->vars as $name => $value) {
$template = str_replace('{' . $name . '}', $value, $template);
}
return $template;
}
}
?>

&emsp;
7. 常量
可以把在类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用 $ 符号。
常量的值必须是一个定值,不能是变量,类属性,数学运算的结果或函数调用。
自 PHP 5.3.0 起,可以用一个变量来动态调用类。但该变量的值不能为关键字(如 self,parent 或 static)。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class MyClass
{
const constant = '常量值';

function showConstant() {
echo self::constant . "<br/>";
}
}

echo MyClass::constant . "<br/>";

$classname = "MyClass";
echo $classname::constant . "<br/>"; // 自 5.3.0 起

$class = new MyClass();
$class->showConstant();

echo $class::constant . "<br/>"; // 自 PHP 5.3.0 起
?>

&emsp;
8. 抽象类
任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。
定义为抽象的类不能被实例化。
被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。
继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么
子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。例如,子类定义了一个可选参数,而父类抽象方法的声明里没有,则两者的声明并无冲突。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue() {
return "ConcreteClass2";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') . "<br/>";
$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') . "<br/>";
?>

程序运行结果:
ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

&emsp;
9. Static 关键字
声明类属性或方法为 static(静态),就可以不实例化类而直接访问。
静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。
静态属性不可以由对象通过 -> 操作符来访问。
自 PHP 5.3.0 起,可以用一个变量来动态调用类。但该变量的值不能为关键字 self,parent 或 static。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
class Foo {
public static $my_static = 'foo';
public function staticValue() {
return self::$my_static;
}
}
print Foo::$my_static . "<br/>";
$foo = new Foo();
print $foo->staticValue() . "<br/>";
?>

程序运行结果:
foo
foo

&emsp;
10. Final 关键字
PHP 5 新增了一个 final 关键字。如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class BaseClass {
public function test() {
echo "BaseClass::test() called" . PHP_EOL;
}

final public function moreTesting() {
echo "BaseClass::moreTesting() called" . PHP_EOL;
}
}

class ChildClass extends BaseClass {
public function moreTesting() {
echo "ChildClass::moreTesting() called" . PHP_EOL;
}
}
// 报错信息 Fatal error: Cannot override final method BaseClass::moreTesting()
?>

程序运行结果:
Fatal error: Cannot override final method BaseClass::moreTesting() in D:\WWW\Basis\oop\opp_9.php on line 16

&emsp;
11.调用父类构造方法
PHP 不会在子类的构造方法中自动的调用父类的构造方法。要执行父类的构造方法,需要在子类的构造方法中调用 parent::__construct()

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
header("Content-type:text/html;charset=utf-8"); //设置编码
class BaseClass {
function __construct() {
print "BaseClass 类中构造方法" . "<br/>";
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct(); // 子类构造方法不能自动调用父类的构造方法
print "SubClass 类中构造方法" . "<br/>";
}
}
class OtherSubClass extends BaseClass {
// 继承 BaseClass 的构造方法
}

// 调用 BaseClass 构造方法
$obj = new BaseClass();

// 调用 BaseClass、SubClass 构造方法
$obj = new SubClass();

// 调用 BaseClass 构造方法
$obj = new OtherSubClass();
?>

程序运行结果:
BaseClass 类中构造方法
BaseClass 类中构造方法
SubClass 类中构造方法
BaseClass 类中构造方法

&emsp;
&emsp;

1.9 PHP 函数

[参见本站博客:PHP-函数]

&emsp;
&emsp;

二、 PHP 正则表达式

[参见本站博客:PHP-正则表达式]

&emsp;
&emsp;

三、 PHP 文件系统

[参见本站博客:PHP-文件系统]

&emsp;
&emsp;

四、 PHP 文件上传

[参见本站博客:PHP-文件上传]

&emsp;
&emsp;

五、 MySQL入门

[参见本站博客:MySQL入门]

&emsp;
&emsp;

六、 PHP操作MySQL数据库

[参见本站博客:PHP操作MySQL数据库]

&emsp;
&emsp;

七、 PHP会话管理和控制

[参见本站博客:PHP-会话管理和控制]