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 脚本代码。
<?php
     //这里是我们要写的PHP代码
?>


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()。

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代码的最后一行可以加也可不加分号。由于很多学习者特别是初学者经常犯一个毛病:写完一行代码不加
分号。因此,容易报错。我们通常在公司里面规定:一行代码写完,就必须要加分号。

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


1.2 PHP 变量

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

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

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

PHP global 关键字:global 关键字用于函数内访问全局变量。
PHP 将所有全局变量存储在一个名为 $GLOBALS[index] 的数组中。 index 保存变量的名称。这个数组可以在函数内部访问,也可以直接用来更新全局变量。
<?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 后写 $变量 = 值。

<?php
$a = 10;
$b = 100;
function test(){
   global $a , $b;
   echo $a + $b;
}
//结果是不是显示出来了?
test();
?>


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

<?php

$one = 10;

function demo(){
   $two = 100;

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

   return $result;

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

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

static 作用域:当一个函数完成时,它的所有变量通常都会被删除。然而,有时候您希望某个局部变量不要被删除。要做到这一点,请在您第一次声明变量时使用 static 关键字:
<?php
 function myTest()
 {
     static $x=0;
     echo $x;
     $x++;
 }
 myTest();
 myTest();
 myTest();
 myTest();
 ?>


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

<?php

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

function test(){

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

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

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

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


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

<?php

function hello(){

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

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

hello();

echo $que;
?>

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


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

<?php
$a = 10;
$b = 100;
function test(){
   global $a , $b;
   echo $a + $b;
}
//结果是不是显示出来了?
test();
?>

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

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

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 新加)。返回该方法被定义时的名字(区分大小写)。


1.3 PHP 数据类型

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

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


1.4 PHP 字符串

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

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

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

1

4. Heredoc结构(<<<):
2).然后在<<<后面写上字符(建议英文大写字符)。如下例中的:ABC
3).然后换行写上任意想写的字符
4).写完后,顶行。在行最开始处,再写上<<<后面的字符和分号。如下例中的:ABC;
<?php
$dingjie = <<<ABC     //“=”和“<<<”和“ABC”这三个标志符号
这里是字符串的内容。
ABC;
?>

5. PHP strlen() 函数:
有时知道字符串值的长度是很有用的。
strlen() 函数返回字符串的长度(字符数)。
注意:在UTF-8下 strlen 把中文字符算成 3 个字节,英文,空格,符号占 1 个字节。

6. PHP strpos() 函数:
strpos()函数用于在字符串内查找一个字符或一段指定的文本。
如果在字符串中找到匹配,该函数会返回第一个匹配的字符位置。如果未找到匹配,则返回 FALSE。
实例:下面的实例在字符串 “Hello world!” 中查找文本 “world”:
<?php
 echo strpos("Hello world!","world");
 ?>
运行结果:6
提示:在上面的实例中,字符串 “world” 的位置是 6。之所以是 6 而不是 7 的原因是,字符串中第一个字符的位置是 0,而不是 1。


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 常量,但应尽量避免,因为会造成不可预料的结果。
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

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):
?>

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

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

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

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

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 新加)。返回该方法被定义时的名字(区分大小写)。


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

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

1. 索引数组:键值为整形(int)
我们来总结规律:
1.索引数组若不强制声明他的下标,他的下标是从0开始的。(我们的第一个数组的值:只有不断努力才能博得未来。这个值的下标为0)。
2.如果我指定过下标他的下标就为我指定的值。如下标为5,10和下标为19的,都是我指定过的值。
3.若某个值(如php.cn),强制指定了下标(下标为10)。在它后面加上的值(PHP学院),不指定下标的话。他们的下标增长规律为最大值+1。
<?php
 header("Content-type:text/html;charset=utf-8");    //设置编码
 $array=array(100,1.34,true,"PHP中文网",);
 echo '<pre>';
 var_dump($array);
 echo '<pre/>';
 ?>

2. 关联数组:键值中只要有一个为字符串(String)类型即称为关联数组)
那我们来声明一下关联数组。跟索引数组的声明方式完成一样。不过不同的是,必须要指定字符串的下标和必须要使用键值对应符。
我们通过实验知道:
1.声明关联数组是 键名 => 值。
2.在关联数组可以有索引数组的元素。
<?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这个标签的主要目的是为原样输出,格式展示的更好看,更清晰。

3. 索引数组和关联数组遍历分别用for和foreach
1. 索引数组:使用for遍历
<?php
 $arr=Array('tom','andy','jack');
 $arrlength=count($arr);
 for($x=0;$x<$arrlength;$x++){
     echo $arr[$x];
     echo  "<br/>";
 } 
 ?>


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

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

这是一个固定用法,将要循环的数组放进去。
as 是一个固定的关键字;
后面的键变量是可选的,随意定义一个变量,每次循环的时候,foreach这个语法会把键取出来赋值到键变量里面;
后面的值变量是必填的。每次循环的时候,会把值放到值变量里面。
我们下面用代码来举例子,加强对这个语法的理解。
<?php
 $arr=[
     'name'=>'Tom',
     'age'=>'18',
     'gender'=>'male'
 ];
 foreach($arr as $key=>$value){
     echo $key.": ".$value."<br />";
 };
?>
运行结果:
name: Tom
age: 18
gender: male

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

3. 通过foreach遍历不连续的索引数组,如下例:
<?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循环一样的循环遍历) 每读将键和值输出,然后显示出来。循环一次向后移动一次下标。读取至最后,退出执行。

4. foreach遍历遍历多维数组:
<?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. 依此类推,第二次循环也是这样。

5. 统计数组元素个数
数组是我们最常用到的类型,那如何计算某个一维数组的个数呢。其实我们可以用到我们之前学过的数学函数里面的一个:count()
count($变量) 函数用于返回数组的长度(元素数):
<?php
$name=Array('tom','andy','jack');
echo count($name);
?>

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

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

7. 数组函数
[PHP 数组函数]


1.7 PHP 命名空间

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


1.8 PHP 面向对象

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

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

示例代码:

<?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();
 ?>

2. 析构函数
析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
<?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();
?>

示例代码:

<?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();
?>

3. 继承
PHP 使用关键字 extends 来继承一个类,PHP 不支持多继承,格式如下:
class Child extends Parent {
   // 代码部分
}

示例代码:

<?php
// 子类扩展站点类别
class Child_Site extends Site {
    var $category;
    function setCate($par){
        $this->category = $par;
    }
    function getCate(){
        echo $this->category . "<br/>";
    }
}
?>

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

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

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

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

代码示例:

<?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

?>

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

示例代码:

<?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
?>

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

示例代码:

<?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;
    }
}
?>

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

示例代码:

<?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 起
?>

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

示例代码:

<?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

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

示例代码:

<?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

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

代码示例:

<?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

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

代码示例:

<?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 类中构造方法


1.9 PHP 函数

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


二、 PHP 正则表达式

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


三、 PHP 文件系统

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


四、 PHP 文件上传

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


五、 MySQL入门

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


六、 PHP操作MySQL数据库

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


七、 PHP会话管理和控制

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

  Reprint please specify: Treecatee PHP基础语法

 Previous
PHP-命名空间 PHP-命名空间
(o゚v゚)ノ 如果没有定义任何命名空间,所有的类与函数的定义都是在全局空间,与 PHP 引入命名空间概念前一样。在名称前加上前缀 \ 表示该名称是全局空间中的名称,即使该名称位于其它的命名空间中时也是如此。对于函数和常量来说,如果当前
2019-02-14
Next 
Wireshark简单介绍和数据包分析 Wireshark简单介绍和数据包分析
   Wireshark-Acquaintance    前言Wireshark是一款世界范围最广、最好用的网络封包分析软件,功能强大,界面友好直观,操作起来非常方便。它的创始人是Gerald Co
2019-01-19
  TOC