在 PHP 中,array() 函数用于创建数组:
在 PHP 中,有三种类型的数组:
count() 函数用于返回数组的长度(元素的数量):
$cars=array("Volvo","BMW","Toyota");
echo "I like " . $cars[0] . ", " . $cars[1] . " and " . $cars[2] . ".";
echo count($cars);
?>
$cars=array("Volvo","BMW","Toyota");
$arrlength=count($cars);
for($x=0;$x<$arrlength;$x++)
{
echo $cars[$x];
echo "
";
}
?>
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");
echo "Peter is " . $age['Peter'] . " years old.";
?>
"35","Ben"=>"37","Joe"=>"43");
foreach($age as $x=>$x_value)
{
echo "Key=" . $x . ", Value=" . $x_value;
echo "
";
}
?>
PS:print_r() 函数用于打印变量,以更容易理解的形式展示。如果给出的是 string、integer 或 float 类型变量,将打印变量值本身。如果给出的是 array,将会按照一定格式显示键和元素。object 与数组类似。
";
rsort($cars);
print_r($cars);
?>
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");
asort($age);
print_r($age);
echo "
";
arsort($age);
print_r($age);
?>
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");
ksort($age);
print_r($age);
echo "
";
krsort($age);
print_r($age);
?>
PS:PHP中预定义了几个超级全局变量(superglobals) ,这意味着它们在一个脚本的全部作用域中都可用。 你不需要特别说明,就可以在函数及类中使用。
PHP 超级全局变量列表:
$GLOBALS 是一个包含了全部变量的全局组合数组。变量的名字就是数组的键。
$x = 75;
$y = 25;
function addition()
{
$GLOBALS['z'] = $GLOBALS['x'] + $GLOBALS['y'];
}
addition();
echo $z;
?>
$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。不能保证每个服务器都提供全部项目;服务器可能会忽略一些,或者提供一些没有在这里列举出来的项目。
元素/代码 | 描述 |
---|---|
$_SERVER[‘PHP_SELF’] | 当前执行脚本的文件名,与 document root 有关。例如,在地址为 http://example.com/test.php/foo.bar 的脚本中使用 $_SERVER[‘PHP_SELF’] 将得到 /test.php/foo.bar。FILE 常量包含当前(例如包含)文件的完整路径和文件名。 从 PHP 4.3.0 版本开始,如果 PHP 以命令行模式运行,这个变量将包含脚本名。之前的版本该变量不可用。 |
$_SERVER[‘GATEWAY_INTERFACE’] | 服务器使用的 CGI 规范的版本;例如,“CGI/1.1”。 |
$_SERVER[‘SERVER_ADDR’] | 当前运行脚本所在的服务器的 IP 地址。 |
$_SERVER[‘SERVER_NAME’] | 当前运行脚本所在的服务器的主机名。如果脚本运行于虚拟主机中,该名称是由那个虚拟主机所设置的值决定。(如: www.runoob.com) |
$_SERVER[‘SERVER_SOFTWARE’] | 服务器标识字符串,在响应请求时的头信息中给出。 (如:Apache/2.2.24) |
$_SERVER[‘SERVER_PROTOCOL’] | 请求页面时通信协议的名称和版本。例如,“HTTP/1.0”。 |
$_SERVER[‘REQUEST_METHOD’] | 访问页面使用的请求方法;例如,“GET”, “HEAD”,“POST”,“PUT”。 |
$_SERVER[‘REQUEST_TIME’] | 请求开始时的时间戳。从 PHP 5.1.0 起可用。 (如:1377687496) |
$_SERVER[‘QUERY_STRING’] | query string(查询字符串),如果有的话,通过它进行页面访问。 |
$_SERVER[‘HTTP_ACCEPT’] | 当前请求头中 Accept: 项的内容,如果存在的话。 |
$_SERVER[‘HTTP_ACCEPT_CHARSET’] | 当前请求头中 Accept-Charset: 项的内容,如果存在的话。例如:“iso-8859-1,*,utf-8”。 |
$_SERVER[‘HTTP_HOST’] | 当前请求头中 Host: 项的内容,如果存在的话。 |
$_SERVER[‘HTTP_REFERER’] | 引导用户代理到当前页的前一页的地址(如果存在)。由 user agent 设置决定。并不是所有的用户代理都会设置该项,有的还提供了修改 HTTP_REFERER 的功能。简言之,该值并不可信。) |
$_SERVER[‘HTTPS’] | 如果脚本是通过 HTTPS 协议被访问,则被设为一个非空的值。 |
$_SERVER[‘REMOTE_ADDR’] | 浏览当前页面的用户的 IP 地址。 |
$_SERVER[‘REMOTE_HOST’] | 浏览当前页面的用户的主机名。DNS 反向解析不依赖于用户的 REMOTE_ADDR。 |
$_SERVER[‘REMOTE_PORT’] | 用户机器上连接到 Web 服务器所使用的端口号。 |
$_SERVER[‘SCRIPT_FILENAME’] | 当前执行脚本的绝对路径。 |
$_SERVER[‘SERVER_ADMIN’] | 该值指明了 Apache 服务器配置文件中的 SERVER_ADMIN 参数。如果脚本运行在一个虚拟主机上,则该值是那个虚拟主机的值。(如:[email protected]) |
$_SERVER[‘SERVER_PORT’] | Web 服务器使用的端口。默认值为 “80”。如果使用 SSL 安全连接,则这个值为用户设置的 HTTP 端口。 |
$_SERVER[‘SERVER_SIGNATURE’] | 包含了服务器版本和虚拟主机名的字符串。 |
$_SERVER[‘PATH_TRANSLATED’] | 当前脚本所在文件系统(非文档根目录)的基本路径。这是在服务器进行虚拟到真实路径的映像后的结果。 |
$_SERVER[‘SCRIPT_NAME’] | 包含当前脚本的路径。这在页面需要指向自己时非常有用。FILE 常量包含当前脚本(例如包含文件)的完整路径和文件名。 |
$_SERVER[‘SCRIPT_URI’] | URI 用来指定要访问的页面。例如 “/index.html”。 |
echo $_SERVER['PHP_SELF'];
echo "
";
echo $_SERVER['SERVER_NAME'];
echo "
";
echo $_SERVER['HTTP_HOST'];
echo "
";
echo $_SERVER['HTTP_REFERER'];//没有上一个页面,所以为空
echo "
";
echo $_SERVER['HTTP_USER_AGENT'];
echo "
";
echo $_SERVER['SCRIPT_NAME'];
?>
$_REQUEST 用于收集HTML表单提交的数据。(好像用的挺少的)
都是用于收集表单数据
POST的数据对任何人都不可见,URL地址栏看不到
GET的数据对任何人都可见,URL地址栏可以看到
Test $GET
在 PHP 中,提供了下列循环语句:
先判断再执行
$i=1;
while($i<=5)
{
echo "The number is " . $i . "
";
$i++;
}
?>
先执行一次,再做判断
";
}
while ($i<=5);
?>
for ($i=1; $i<=5; $i++)
{
echo "The number is " . $i . "
";
}
?>
foreach 循环用于遍历数组。(遍历数据库中的表经常用)
$x=array("one","two","three");
foreach ($x as $value)
{
echo $value . "
";
}
?>
PHP 函数准则:
function writeName()
{
echo "Kai Jim Refsnes";
}
echo "My name is ";
writeName();
?>
function writeName($fname)
{
echo $fname . " Refsnes.
";
}
echo "My name is ";
writeName("Kai Jim");
echo "My sister's name is ";
writeName("Hege");
echo "My brother's name is ";
writeName("Stale");
?>
function add($x,$y)
{
$total=$x+$y;
return $total;
}
echo "1 + 16 = " . add(1,16);
?>
魔术常量的值随着它们在代码中的位置改变而改变 。(有八个)
namespace MyProject;
echo '这是第 " ' . __LINE__ . ' " 行';
echo"
";
echo '该文件位于 " ' . __FILE__ . ' " ';
echo"
";
echo '该文件位于 " ' . __DIR__ . ' " ';
echo"
";
class Test{
public function doit(){
echo '函数名为:'.__FUNCTION__;
}
public function doitAgain(){
echo '函数名为:'.__METHOD__;
}
}
$obj = new Test();
$obj->doit();
echo '
';
$obj->doitAgain();
echo"
";
class test1 {
function _print() {
echo '类名为:' . __CLASS__ . "
";
echo '函数名为:' . __FUNCTION__ ;
}
}
$t = new test1();
$t->_print();
echo"
";
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World';
}
}
class MyHelloWorld {
use Hello, World;
public function sayExclamationMark() {
echo '!';
}
}
$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
echo"
";
echo '命名空间为:"', __NAMESPACE__, '"'; // 输出 "MyProject"
?>
命名空间必须是程序脚本的第一条语句
PHP 命名空间可以解决以下两类问题:
与目录和文件的关系很像,PHP 命名空间也允许指定层次化的命名空间的名称。因此,命名空间的名字可以使用分层次的方式定义:
上面的例子创建了常量 MyProject\Sub\Level\CONNECT_OK,类 MyProject\Sub\Level\Connection 和函数 MyProject\Sub\Level\Connect。
PHP 命名空间中的类名可以通过三种方式引用:
';
}
namespace CC;
function showinfo(){
echo __METHOD__.'
';
}
namespace AA;
function showinfo(){
echo __METHOD__.'
';
}
//非限定访问:用于访问当前空间中的成员,位于哪个命名空间下就访问哪个
showinfo();
//限定访问:只能访问当前所在空间的子空间中的成员
BB\showinfo();
//完全限定访问:可以访问其他所有空间的成员
\CC\showinfo();
?>
动态访问命名空间的元素,PS:因为在动态的类名称、函数名称或常量名称中,限定名称和完全限定名称没有区别,因此其前导的反斜杠是不必要的。
test.php
";
}
}
function funcname()
{
echo __FUNCTION__."
";
}
const constname = "global";
?>
test1.php
namespace namespacename;
class classname
{
function __construct()
{
echo __METHOD__,"
";
}
}
function funcname()
{
echo __FUNCTION__,"
";
}
const constname = "namespaced";
include 'test.php';
$a = 'classname';
$obj = new $a; // 输出 classname::__construct
$b = 'funcname';
$b(); // 输出函数名
echo constant('constname'), "
"; // 输出 global
/* 如果使用双引号,使用方法为 "\\namespacename\\classname"*/
$a = '\namespacename\classname';
$obj = new $a; // 输出 namespacename\classname::__construct
$a = 'namespacename\classname';
$obj = new $a; // 输出 namespacename\classname::__construct
$b = 'namespacename\funcname';
$b(); // 输出 namespacename\funcname
$b = '\namespacename\funcname';
$b(); // 输出 namespacename\funcname
echo constant('\namespacename\constname'), "\n"; // 输出 namespaced
echo constant('namespacename\constname'), "\n"; // 输出 namespaced
?>
PHP支持两种抽象的访问当前命名空间内部元素的方法,NAMESPACE 魔术常量和namespace关键字。
1.常量__NAMESPACE__的值是包含当前命名空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它包含一个空的字符串。
2.关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素。它等价于类中的 self 操作符。
'; // 输出 "MyProject"
}
namespace{
echo '"', __NAMESPACE__, '"','
';//输出 ""
}
';
}
namespace AA;
function showinfo(){
echo __METHOD__.'
';
}
namespace\showinfo();
namespace\BB\showinfo();
?>
PHP 命名空间支持 有两种使用别名或导入方式:为类名称使用别名,或为命名空间名称使用别名。
';
}
}
}
namespace My\Full\NSname\subns{
function func(){
echo __NAMESPACE__.'
';
}
}
namespace FOO\bar{
const name = "test";
function say(){
echo __NAMESPACE__.'
';
}
}
namespace Foo{
class foo{
public function __construct(){
echo 'XingYun';
}
}
}
namespace foo{
use My\Full\Classname;
use My\Full\NSname;
use FOO\bar;
new Classname();// 实例化 My\Full\Classname 对象
NSname\subns\func();// 调用函数 My\Full\NSname\subns\func
bar\say();
echo constant('\FOO\bar\name').'
';
new namespace\foo();
}
?>
对于函数和常量来说,如果当前命名空间中不存在该函数或常量,PHP 会退而使用全局空间中的函数或常量。
PS:没研究出来,之后再看
名称解析遵循下列规则:
对完全限定名称的函数,类和常量的调用在编译时解析。例如 new \A\B 解析为类 A\B。
所有的非限定名称和限定名称(非完全限定名称)根据当前的导入规则在编译时进行转换。例如,如果命名空间 A\B\C 被导入为 C,那么对 C\D\e() 的调用就会被转换为 A\B\C\D\e()。
在命名空间内部,所有的没有根据导入规则转换的限定名称均会在其前面加上当前的命名空间名称。例如,在命名空间 A\B 内部调用 C\D\e(),则 C\D\e() 会被转换为 A\B\C\D\e() 。
非限定类名根据当前的导入规则在编译时转换(用全名代替短的导入名称)。例如,如果命名空间 A\B\C 导入为C,则 new C() 被转换为 new A\B\C() 。
在命名空间内部(例如A\B),对非限定名称的函数调用是在运行时解析的。例如对函数foo()的调用是这样解析的:
在命名空间(例如A\B)内部对非限定名称或限定名称类(非完全限定名称)的调用是在运行时解析的。下面是调用new C()及new D\E()的解析过程:
new C()的解析:
new D\E()的解析:
为了引用全局命名空间中的全局类,必须使用完全限定名称new \C()。
namespace A;
use B\D, C\E as F;
// 函数调用
foo(); // 首先尝试调用定义在命名空间"A"中的函数foo()
// 再尝试调用全局函数 "foo"
\foo(); // 调用全局空间函数 "foo"
my\foo(); // 调用定义在命名空间"A\my"中函数 "foo"
F(); // 首先尝试调用定义在命名空间"A"中的函数 "F"
// 再尝试调用全局函数 "F"
// 类引用
new B(); // 创建命名空间 "A" 中定义的类 "B" 的一个对象
// 如果未找到,则尝试自动装载类 "A\B"
new D(); // 使用导入规则,创建命名空间 "B" 中定义的类 "D" 的一个对象
// 如果未找到,则尝试自动装载类 "B\D"
new F(); // 使用导入规则,创建命名空间 "C" 中定义的类 "E" 的一个对象
// 如果未找到,则尝试自动装载类 "C\E"
new \B(); // 创建定义在全局空间中的类 "B" 的一个对象
// 如果未发现,则尝试自动装载类 "B"
new \D(); // 创建定义在全局空间中的类 "D" 的一个对象
// 如果未发现,则尝试自动装载类 "D"
new \F(); // 创建定义在全局空间中的类 "F" 的一个对象
// 如果未发现,则尝试自动装载类 "F"
// 调用另一个命名空间中的静态方法或命名空间函数
B\foo(); // 调用命名空间 "A\B" 中函数 "foo"
B::foo(); // 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法
// 如果未找到类 "A\B" ,则尝试自动装载类 "A\B"
D::foo(); // 使用导入规则,调用命名空间 "B" 中定义的类 "D" 的 "foo" 方法
// 如果类 "B\D" 未找到,则尝试自动装载类 "B\D"
\B\foo(); // 调用命名空间 "B" 中的函数 "foo"
\B::foo(); // 调用全局空间中的类 "B" 的 "foo" 方法
// 如果类 "B" 未找到,则尝试自动装载类 "B"
// 当前命名空间中的静态方法或函数
A\B::foo(); // 调用命名空间 "A\A" 中定义的类 "B" 的 "foo" 方法
// 如果类 "A\A\B" 未找到,则尝试自动装载类 "A\A\B"
\A\B::foo(); // 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法
// 如果类 "A\B" 未找到,则尝试自动装载类 "A\B"
?>
class phpclass{
//主体框架:class 类的名字
}
类创建后,我们可以使用 new 运算符来实例化该类的对象:
url = $par;
}
function getUrl(){
echo $this->url . PHP_EOL;
}
function setTitle($par){
$this->title = $par;
}
function getTitle(){
echo $this->title . PHP_EOL;
}
}
$runoob = new Site;
$taobao = new Site;
$google = new Site;
// 调用成员函数,设置标题和URL
$runoob->setTitle( "菜鸟教程" );
$taobao->setTitle( "淘宝" );
$google->setTitle( "Google 搜索" );
$runoob->setUrl( 'www.runoob.com' );
$taobao->setUrl( 'www.taobao.com' );
$google->setUrl( 'www.google.com' );
// 调用成员函数,获取标题和URL
$runoob->getTitle();echo '
';
$runoob->getUrl();echo '
';
$taobao->getTitle();echo '
';
$taobao->getUrl();echo '
';
$google->getTitle();echo '
';
$google->getUrl();echo '
';
?>
构造函数是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,在创建对象的语句中与 new 运算符一起使用。
class Site {
/* 成员变量 */
var $url;
var $title;
function _construct($par1,$par2){
$this->url = $par1;
$this->title = $par2;
}
/* 成员函数 */
function setUrl($par){
$this->url = $par;
}
function getUrl(){
echo $this->url . PHP_EOL;
}
function setTitle($par){
$this->title = $par;
}
function getTitle(){
echo $this->title . PHP_EOL;
}
}
$runoob = new Site;
$taobao = new Site;
$google = new Site;
// 调用成员函数,设置标题和URL
$runoob->setTitle( "菜鸟教程" );
$taobao->setTitle( "淘宝" );
$google->setTitle( "Google 搜索" );
$runoob->setUrl( 'www.runoob.com' );
$taobao->setUrl( 'www.taobao.com' );
$google->setUrl( 'www.google.com' );
// 调用成员函数,获取标题和URL
$runoob->getTitle();echo '
';
$runoob->getUrl();echo '
';
$taobao->getTitle();echo '
';
$taobao->getUrl();echo '
';
$google->getTitle();echo '
';
$google->getUrl();echo '
';
?>
析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
class MyDestructableClass {
function __construct() {
print "构造函数";
$this->name = "MyDestructableClass";
print '
';
}
function __destruct() {
print "销毁 " . $this->name . "\n";
}
}
new MyDestructableClass();
?>
PHP 使用关键字 extends 来继承一个类,PHP 不支持多继承。
class a
{
function printItem($string)
{
echo 'a: ' . $string . '
';
}
function printPHP()
{
echo 'PHP is great.' . '
';
}
}
class b extends a
{
function printItem($string)
{
echo 'a: ' . $string . '
';
}
}
$a = new a();
$b = new b();
$a->printItem('233');
$a->printPHP();
$b->printItem('233');
$b->printPHP();
?>
如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
';
}
function printPHP()
{
echo 'PHP is great.' . '
';
}
}
class b extends a
{
function printItem($string)
{
echo 'b: ' . $string . '
';
return $string;
}
}
$a = new a();
$b = new b();
$a->printItem('233');
$a->printPHP();
$b->printItem('233');
$b->printPHP();
?>
PHP 对属性或方法的访问控制,是通过在前面添加关键字 public(公有),protected(受保护)或 private(私有)来实现的。
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
两个错误
Uncaught Error: Cannot access protected property MyClass::$protected
Uncaught Error: Cannot access private property MyClass::$private
类中的方法可以被定义为公有,私有或受保护。如果没有设置这些关键字,则该方法默认为公有。
';
}
// 声明一个受保护的方法
protected function MyProtected() {
echo '保护
';
}
// 声明一个私有的方法
private function MyPrivate() {
echo '私有
';
}
// 此方法为公有
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
$myclass = new MyClass;
$myclass->MyPublic(); // 这行能被正常执行
//$myclass->MyProtected(); // 这行会产生一个致命错误
//$myclass->MyPrivate(); // 这行会产生一个致命错误
$myclass->Foo(); // 公有,受保护,私有都可以执行
?>
两个错误
Uncaught Error: Call to protected method MyClass::MyProtected()
Uncaught Error: Call to private method MyClass::MyPrivate()
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是公有,这是接口的特性。
要实现一个接口,使用 implements 操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称。
name;
}
function setName($_name) {
$this->name = $_name;
}
}
$apple = new Apple(); //创建对象
$apple->setName("苹果");
echo "创建了一个" . $apple->getName();
echo "
";
echo "MAX_GRADE is " . Apple::MAX_WEIGHT; //静态常量
?>
可以把在类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用 $ 符号。
常量的值必须是一个定值,不能是变量,类属性,数学运算的结果或函数调用。
';
}
}
echo MyClass::constant . '
';
$classname = "MyClass";
echo $classname::constant . '
';
$class = new MyClass();
$class->showConstant();
echo $class::constant . '
';
?>
任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。
定义为抽象的类不能被实例化。
被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。
继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。
getValue() . '
';
}
}
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_') . '
';
$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') . '
';
?>
声明类属性或方法为 static(静态),就可以不实例化类而直接访问。
静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。
静态属性不可以由对象通过 -> 操作符来访问。
class Foo {
public static $my_static = 'foo';
public function staticValue() {
return self::$my_static;
}
}
print Foo::$my_static . '
';
$foo = new Foo();
print $foo->staticValue() . '
';
?>
final 关键字。如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承。
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;
}
}
// 方法声明final报错信息 Fatal error: Cannot override final method BaseClass::moreTesting()
// 类声明final Fatal error: Class ChildClass may not inherit from final class (BaseClass)
?>
PHP 不会在子类的构造方法中自动的调用父类的构造方法。要执行父类的构造方法,需要在子类的构造方法中调用 parent::__construct()
class BaseClass {
function __construct() {
print "BaseClass 类中构造方法" . '
';
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct(); // 子类构造方法不能自动调用父类的构造方法
print "SubClass 类中构造方法" . '
';
}
}
class OtherSubClass extends BaseClass {
// 继承 BaseClass 的构造方法
}
// 调用 BaseClass 构造方法
$obj = new BaseClass();
// 调用 BaseClass、SubClass 构造方法
$obj = new SubClass();
// 调用 BaseClass 构造方法
$obj = new OtherSubClass();
?>